Encryption error on Android 4.2

From the Android Jellybean page:

Modified the default implementations of SecureRandom and Cipher.RSA to use OpenSSL

They changed the default provider for SecureRandom to use OpenSSL instead of the previous Crypto provider.

The following code will produce two different outputs on pre-Android 4.2 and Android 4.2:

SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
Log.i(TAG, "rand.getProvider(): " + rand.getProvider().getName());

On pre-4.2 devices:

rand.getProvider: Crypto

On 4.2 devices:

rand.getProvider: AndroidOpenSSL

Fortunately, it’s easy to revert to the old behavior:

SecureRandom sr = SecureRandom.getInstance( "SHA1PRNG", "Crypto" );

To be sure, it’s dangerous to be calling SecureRandom.setSeed at all in light of the Javadocs which state:

Seeding SecureRandom may be insecure

A seed is an array of bytes used to bootstrap random number generation. To produce cryptographically secure random numbers, both the seed and the algorithm must be secure.

By default, instances of this class will generate an initial seed using an internal entropy source, such as /dev/urandom. This seed is unpredictable and appropriate for secure use.

You may alternatively specify the initial seed explicitly with the seeded constructor or by calling setSeed(byte[]) before any random numbers have been generated. Specifying a fixed seed will cause the instance to return a predictable sequence of numbers. This may be useful for testing but it is not appropriate for secure use.

However, for writing unit tests, as you are doing, using setSeed may be okay.

Leave a Comment