Android Cipher throwing BadPaddingException, but n

2020-06-30 03:44发布

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.

1条回答
Juvenile、少年°
2楼-- · 2020-06-30 04:29

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).
  • the fact that 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 use SecretKeySpec for keys or PBKDF2 for passwords.

查看更多
登录 后发表回答