I'm using some basic encryption in my app, which is running Android v20 (4.4.4)
This used to work, but I think with the newer version of Android I'm running, there is now an error throwing the following exception:
10-28 12:42:02.312 5173-5332/com.app W/System.err﹕ javax.crypto.BadPaddingException: pad block corrupted
10-28 12:42:02.312 5173-5332/com.app W/System.err﹕ at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:739)
10-28 12:42:02.322 5173-5332/com.app W/System.err﹕ at javax.crypto.Cipher.doFinal(Cipher.java:1204)
10-28 12:42:02.322 5173-5332/com.app W/System.err﹕ at com.app.utils.CryptoClass.decrypt(CryptoClass.java:47)
10-28 12:42:02.322 5173-5332/com.app W/System.err﹕ at com.app.utils.CryptoClass.decrypt(CryptoClass.java:30)
The method throwing this is here:
private static byte[] decrypt(byte[] rawKey, byte[] encrypted) throws Exception {
SecretKeySpec spec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, spec);
return cipher.doFinal(encrypted); //THIS LINE THROWS EXCEPTION
}
When I run this same code as a Java project, it works correctly (using the same version of Java, 1.7 as Android is using).
I've tried various combinations for the getInstance parameter based on what I've found online, like AES/CBC/PKCS5PADDING
but that doesn't solve the problem.
The getRawKey method I'm using:
private static byte[] getRawKey(byte[] bytes) throws Exception {
KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", "SECRET");
secureRandom.setSeed(bytes);
keygen.init(128, secureRandom);
SecretKey secretKey = keygen.generateKey();
return secretKey.getEncoded();
}
Any help appreciated, thanks.
The problem of using
SecureRandom
to derive keys is that:SecureRandom
uses an undefined algorithm, which may change between implementations (even from the same vendor).SecureRandom
only uses the given seed as entropy is flawed, this may (and does) change for different implementations.Above is even true if you specify
"SHA1PRNG"
, which is not a well defined or standardized algorithm.In Android, the proprietary functionality of
SecureRandom
in the Oracle provider - and the providers that tried to stay compatible - was changed in favor of the OpenSSL related provider. This happened from 4.2 onwards. In OpenSSL,SecureRandom
only mixes the given seed into the entropy pool. In other words, you get a fully random key even if you use the same "password" as seed.So if you ever see
getRawKey
as defined as above, please try and take it down. And for your own implementations just useSecretKeySpec
for keys or PBKDF2 for passwords.