Android encryption "pad block corrupted" exception

20,285

Solution 1

owlstead's advice was helpful, but for this case when using the code in

Attention Android developers: Keep user data safe http://www.techrepublic.com/blog/software-engineer/attention-android-developers-keep-user-data-safe/

I made some changes to the code that might be helpful for other people in the future. I completely deleted the getkey method.

private static String seed;

/**
 * Encrypts the text. 
 * @param clearText The text you want to encrypt
 * @return Encrypted data if successful, or null if unsucessful
 */
protected String encrypt(String clearText) {
    byte[] encryptedText = null;
    try {
        byte[] keyData = seed.getBytes();
        SecretKey ks = new SecretKeySpec(keyData, "AES");
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.ENCRYPT_MODE, ks);
        encryptedText = c.doFinal(clearText.getBytes("UTF-8"));
        return Base64.encodeToString(encryptedText, Base64.DEFAULT);
    } catch (Exception e) {
        return null;
    }
}

/**
 * Decrypts the text
 * @param encryptedText The text you want to encrypt
 * @return Decrypted data if successful, or null if unsucessful
 */
protected String decrypt (String encryptedText) {
    byte[] clearText = null;
    try {
        byte[] keyData = seed.getBytes();
        SecretKey ks = new SecretKeySpec(keyData, "AES");
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.DECRYPT_MODE, ks);
        clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));
        return new String(clearText, "UTF-8");
    } catch (Exception e) {
        return null;
    }
}   

Solution 2

Java + Android + Encryption + Exception means just one thing normally, somebody is using the SecureRandom class again as a key derivation function. This fails when the SecureRandom implementation of "SHA1PRNG" does not behave as the one in Sun's implementation in Java SE. Especially if the seed is added to the state of the random number generator instead of the seed being used as a starting point of the PRNG.

Basically, simply use SecretKey aesKey = new SecretKeySpec(byte[] keyData, "AES") instead, or - if you start off with a password - try and generate the key using PBKDF2.

Solution 3

For me, the problem is in getKey()

Make sure that two invocation of getKey() return the same value.

I used new SecureRandom(password.getBytes()) to generate key. It worked on Windows, but on Android, it returned different value for different call.

Share:
20,285
Esqarrouth
Author by

Esqarrouth

World-class code copy paster.

Updated on July 21, 2022

Comments

  • Esqarrouth
    Esqarrouth almost 2 years

    In this code, this line is causing an exception:

    clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));

    javax.crypto.BadPaddingException: pad block corrupted

    I got the code from: http://www.techrepublic.com/blog/software-engineer/attention-android-developers-keep-user-data-safe/

    Any ideas?

        private String decrypt (String encryptedText) {
            byte[] clearText = null;
            try {
                SecretKeySpec ks = new SecretKeySpec(getKey(), "AES");
                Cipher c = Cipher.getInstance("AES");
                c.init(Cipher.DECRYPT_MODE, ks);
                clearText = c.doFinal(Base64.decode(encryptedText, Base64.DEFAULT));
                return new String(clearText, "UTF-8");
            } catch (Exception e) {
                return null;
            }
        }
    

    Details: I am encrypting it on the android as well

  • Esqarrouth
    Esqarrouth over 10 years
    Isn't it more secure in the way stated in the link? If the guy took time to make a guide, it probably works on his machine, but why not mine?
  • Esqarrouth
    Esqarrouth over 10 years
    byte[] keyData = "0123456789012345".getBytes(); SecretKey ks = new SecretKeySpec(keyData, "AES"); I tried this, it works. Buttt, since now it doesn't convert to 128-192-256-bits automatically, I had to enter it manually, I think I need to add a method which converts automatically, any recommendation?
  • Maarten Bodewes
    Maarten Bodewes over 10 years
    @Esq There is no standardized way of creating smaller or larger keys by just adding zero values as it would obviously bring down the security provided by the key. So to do this it is required to use a KDF, that could be a KBKDF if there is enough entropy in the key data you now have. If there is less than 16 bytes of data (for AES-128) then you should strengthen the key by using a PBKDF. The PBKDF2 method has been implemented by Java. KBKDF's are not present, but they are relatively easy to construct from a HMAC, e.g. you could use HKDF.
  • Maarten Bodewes
    Maarten Bodewes over 10 years
    You should not be creating such examples if you are not sure what you are doing. For instance, you are still using AES ECB mode, which is unsafe. You are using getBytes() without specifying an encoding. You are using a string as if it was a key. Basically, you've fixed one issue but kept at least three others.
  • Esqarrouth
    Esqarrouth over 10 years
    opened up to community wiki in case if you want to fix the things you mentioned.
  • Maarten Bodewes
    Maarten Bodewes over 10 years
    Thanks, however I would have to do a rewrite, and in the end I would end up with code similar to this answer. Maybe you want to take a look at it, it also contains some security advice.
  • Raj
    Raj over 8 years
    if i use like above without getKey genaration process, its thowing exception. java.security.InvalidKeyException: Key length not 128/192/256 bits.
  • Maarten Bodewes
    Maarten Bodewes over 8 years
    Alternatively you can use a simple KDF such as KDF1. Basically you append an four bytes set to zero to the key seed, and then you append an OtherInfo structure to that (say, the ASCII representation of "ENC" or "MAC"). Finally you hash it using any cryptographically secure hash, e.g. SHA-256. Then use the leftmost bytes as output of your KDF.
  • Maarten Bodewes
    Maarten Bodewes over 7 years
    Oh, and I've added the missing KDF's to Bouncy Castle. Alternatively use PBKDF2 with an iteration count of 1 as KBKDF.
  • dphans
    dphans over 6 years
    I have same problem. I have separate the method to encrypt user's password to SHA1PRNG key, but everytime I call that method, it generated many difference strings.