1

I have this test code:

byte[] aesPass1 = { (byte) 204, (byte) 204, (byte) 204, (byte) 204, (byte) 204};

encrypted = encryptAES256("Anything".getBytes("UTF8"), new String(aesPass1, "UTF8"), salt, 1000, iv_b);

to encrypt some data, and this test code:

byte[] aesPass1 = { (byte) 204, (byte) 204, (byte) 204, (byte) 204, (byte) 204};

decryptAES256(encrypted, new String(aesPass1, "UTF8"), salt, 100, iv_b);

to decrypt data.

If I encrypt on Android 4.4.4 I can decrypt on the same device (Android 4.4.4) with no problems, but if I try to decrypt on Android 4.2.2 I get "pad block corrupted" error.

Similar, if I encrypt on Android 4.2.2 I can decrypt on the same device (Android 4.2.2) with no problems, but on Android 4.4.4 I get "error06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt" error.

To make this even stranger for me, if I use this code:

encrypted = encryptAES256("Anything".getBytes("UTF8"), "pass", salt, 1000, iv_b);

to encrypt, and:

decryptAES256(encrypted, "pass", salt, 100, iv_b);

everything works fine on both Android 4.2.2 and Android 4.4.4.

The only difference I can see is using new String(aesPass1, "UTF8") fuction.

My encrypt and decrypt functions:

public static byte[] encryptAES256(byte[] data, String passphrase, byte[] salt, int iterations, byte[] ivbytes) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException  {
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    PBEKeySpec specKey = new PBEKeySpec(passphrase.toCharArray(), salt, iterations, 256);
    SecretKey secretKey = factory.generateSecret(specKey);
    SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

    cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(ivbytes));
    return cipher.doFinal(data);
}

public static byte[] decryptAES256(byte[] data, String passphrase, byte[] salt, int iterations, byte[] ivbytes) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException  {
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    PBEKeySpec specKey = new PBEKeySpec(passphrase.toCharArray(), salt, iterations, 256);
    SecretKey secretKey = factory.generateSecret(specKey);
    SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

    cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivbytes));
    return cipher.doFinal(data);
}

Can you help?

Thank you in advance!

milosh
  • 200
  • 3
  • 11

2 Answers2

0

BadPaddingException is what you should expect if the wrong password/key was used during decryption.

The exception that is thrown when a padding mechanism is expected for the input data, but the input data does not have the proper padding bytes.

As I can bet your code has the correct password, the problem must be about hash of the new String() against declaring it as a "normalString" for different devices.

IMO Android 4.4.4 device must be using a newer version of Java (8) where String memory usage has changed as you can see in this answer so hash are differents and passwords checksums does not match.

Community
  • 1
  • 1
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • But then, is there a way to convert byte[] to String safely? My password must be stored as byte[]. – milosh Aug 03 '15 at 15:14
  • creating an own object (like `MyHashedString`) with overriden `equals` and `hashcode` can be the sollution for cross versions.... – Jordi Castilla Aug 03 '15 at 15:18
  • Also, encrypt and decrypt functions use toCharArray() function on String. How is new String() hash affecting that? BTW, I have no clue how to do what you proposed :) – milosh Aug 03 '15 at 15:36
  • I'm not 100% sure this is the problem, no time for me to go deeper, sorry but it smells to me that problem comes from this part... – Jordi Castilla Aug 03 '15 at 15:41
0

I still do not understand Android cross version issue, but I found the source of the problem.

byte[] aesPass1 must have values that can be converted to readable characters by new String(), so:

byte[] aesPass1 = { (byte) 204, (byte) 204, (byte) 204, (byte) 204, (byte) 204 };

does not work, but:

byte[] aesPass1 = { (byte) 65, (byte) 33, (byte) 126, (byte) 77, (byte) 66 };

works.

milosh
  • 200
  • 3
  • 11