DrBrad
DrBrad

Reputation: 358

Java encryption won't decrypt on Android

Okay, so when I encrypt anything, lets say in this case a file, with my computer. It works fine encrypting and decrypting said file. However if encrypt the file with my computer then send it too my android and run the same decryption code I wrote it wont decrypt the file properly. It doesn't show any errors, however the file is clearly not decrypted properly.

So I've learned that Bouncy Castle is quite different than JVM/JDK standard encryption library, so I'm not 100% sure if that's the problem. However it would make sense. The issue is that if it is I don't know how to use the JVM/JDK library for encryption on my android. I don't want too use the Bouncy Castle library on my computer.

public static void encrypt(File source, File dest, String password){
    try{
        FileInputStream inFile = new FileInputStream(source.getPath());
        FileOutputStream outFile = new FileOutputStream(dest.getPath());

        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey secretKey = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));

        byte[] input = new byte[64];
        int bytesRead;

        while((bytesRead = inFile.read(input)) != -1){
            byte[] output = cipher.update(input, 0, bytesRead);
            if(output != null){
                outFile.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            outFile.write(output);
        }

        inFile.close();
        outFile.flush();
        outFile.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

public static void decrypt(File source, File dest, String password){
    try{
        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey tmp = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
        FileInputStream fis = new FileInputStream(source.getPath());
        FileOutputStream fos = new FileOutputStream(dest.getPath());
        byte[] in = new byte[64];
        int read;
        while((read = fis.read(in)) != -1){
            byte[] output = cipher.update(in, 0, read);
            if(output != null){
                fos.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            fos.write(output);
        }
        fis.close();
        fos.flush();
        fos.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

The outcome would be too be able too encrypt any file with my computer using the standard JVM/JDK encryption library and being able too decrypt the same file with my android.

However if there is a different library other than Bouncy Castle that would work with android I'm open for ideas.

Upvotes: 2

Views: 213

Answers (1)

touhid udoy
touhid udoy

Reputation: 4442

I've faced similar issue. First check if your encryption and decryption is setup properly.

If those are okay, then you should convert the encrypted text to Base64 or similar encoding.

Then decode the Base64 encoding first on the mobile and then decrypt the file.

The issue occurs because, some characters are not suitable for saving or transfering between mediums. They also gets affected by the underlying OS. Even if a bit is changed, your whole decrypted text will be changed, that might be the case here

ANDROID CODE

public static void decrypt(File source, File dest, String password){
    try{
        Base64InputStream fis = new Base64InputStream(new DataInputStream(new FileInputStream(source.getPath())), Base64.DEFAULT);
        FileOutputStream fos = new FileOutputStream(dest.getPath());


        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey tmp = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));

        byte[] in = new byte[64];
        int read;
        while((read = fis.read(in)) != -1){
            byte[] output = cipher.update(in, 0, read);
            if(output != null){
                fos.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            fos.write(output);
        }
        fis.close();
        fos.flush();
        fos.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

Regular JVM

public static void encrypt(File source, File dest, String password){
    try{
        FileInputStream inFile = new FileInputStream(source.getPath());
        OutputStream outFile = Base64.getEncoder().wrap(new FileOutputStream(dest.getPath()));

        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey secretKey = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));

        byte[] input = new byte[64];
        int bytesRead;

        while((bytesRead = inFile.read(input)) != -1){
            byte[] output = cipher.update(input, 0, bytesRead);
            if(output != null){
                outFile.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            outFile.write(output);
        }

        inFile.close();
        outFile.flush();
        outFile.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

public static void decrypt(File source, File dest, String password){
    try{
        InputStream fis = Base64.getDecoder().wrap(new FileInputStream(source.getPath()));
        //FileInputStream fis = new FileInputStream(source.getPath());
        FileOutputStream fos = new FileOutputStream(dest.getPath());

        byte[] salt = new byte[8], iv = new byte[16];

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
        SecretKey tmp = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));

        byte[] in = new byte[64];
        int read;
        while((read = fis.read(in)) != -1){
            byte[] output = cipher.update(in, 0, read);
            if(output != null){
                fos.write(output);
            }
        }

        byte[] output = cipher.doFinal();
        if(output != null){
            fos.write(output);
        }
        fis.close();
        fos.flush();
        fos.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

Upvotes: 1

Related Questions