BouncyCastle AES error when upgrading to 1.45
Asked Answered
S

3

6

Recently upgraded from BC 1.34 to 1.45. I'm decoding some previously-encoded data with the following:

    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] decrypted = cipher.doFinal(encrypted);

When using BC 1.45 I get this exception:

javax.crypto.BadPaddingException: pad block corrupted
 at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(JCEBlockCipher.java:715)
 at javax.crypto.Cipher.doFinal(Cipher.java:1090)

EDIT: More about this issue. I am using the following to generate raw keys from a passphrase:

    KeyGenerator kgen = KeyGenerator.getInstance("AES", "BC");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
    sr.setSeed(seed);
    kgen.init(128, sr);
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();

What I have found is that this results in two different values for BC 1.34 vs 1.45.

It might also not be BouncyCastle-related (I am testing on Android 2.3)

Stylet answered 10/12, 2010 at 3:17 Comment(0)
S
3

Looks like the problem is SecureRandom not being portable across the Froyo-Gingerbread boundary. This post describes a similar problem:

http://groups.google.com/group/android-security-discuss/browse_thread/thread/6ec015a33784b925

I am not sure what exactly changed in SecureRandom, but the only way I found to fix it was to reencrypt the data with keys generated using a portable method.

Stylet answered 10/12, 2010 at 22:6 Comment(2)
You are correct. The contract for SecureRandom does not promise that the seed you manually supply will be the only seed it uses. It will use other sources, like /dev/random on linux/bsd.Rauwolfia
For future readers: In other words, use a well known key derivation method instead, such as PBKDF2.Neilneila
G
6

I just finished tracking this down. It's because of a bug fix on line 320 (in Gingerbread source) of SHA1PRNG_SecureRandomImpl.java in the engineNextBytes() method where

bits = seedLength << 3 + 64;

was changed to

bits = (seedLength << 3) + 64;

Clearly it was a bug that was fixed, but it means that given the same seed, SecureRandom will generate different data pre- and post-gingerbread.

I have a "fix" for it. I stole enough code from android-7 to be able to generate random bytes in the same way that SecureRandom did. I try to decrypt my information and if it fails, use my jacked up SecureRandom to decrypt it. Then I can obviously reencrypt it using the newer SecureRandom, although I'm kind of thinking of moving away from SecureRandom entirely...

Grover answered 18/3, 2011 at 2:53 Comment(2)
I'm trying to implement the same thing... How did you create the Provider?Leavitt
@Ben Demboski could you post your workaround? that would be most usefulBronchoscope
S
3

Looks like the problem is SecureRandom not being portable across the Froyo-Gingerbread boundary. This post describes a similar problem:

http://groups.google.com/group/android-security-discuss/browse_thread/thread/6ec015a33784b925

I am not sure what exactly changed in SecureRandom, but the only way I found to fix it was to reencrypt the data with keys generated using a portable method.

Stylet answered 10/12, 2010 at 22:6 Comment(2)
You are correct. The contract for SecureRandom does not promise that the seed you manually supply will be the only seed it uses. It will use other sources, like /dev/random on linux/bsd.Rauwolfia
For future readers: In other words, use a well known key derivation method instead, such as PBKDF2.Neilneila
G
0

According to the release notes, this fix was included in version 1.40:

PKCS7Padding validation would not fail if pad length was 0. This has been fixed.

This sounds like it may be pertinent.

Glazed answered 10/12, 2010 at 7:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.