Android Security: Beware of the default IV!

Written on September 27, 2017

A quick one today.

A couple of people I have spoken to recently have been unaware of the need to ensure a random IV is being used when performing AES encryption on Android.

What is an IV?

In cryptography, an initialization vector (IV) or starting variable (SV)[1] is a fixed-size input to a cryptographic primitive that is typically required to be random or pseudorandom. Randomization is crucial for encryption schemes to achieve semantic security, a property whereby repeated usage of the scheme under the same key does not allow an attacker to infer relationships between segments of the encrypted message. For block ciphers, the use of an IV is described by the modes of operation. Wikipedia

The unawareness seems to fall into two camps:

  1. I didn’t know I needed to use an IV
  2. I am using the IV that is generated by the Cipher

I didn’t know I needed to use an IV

Yup!

I am using the IV that is generated by the Cipher

Potentially an Uh oh!

Poking around a little, I can see that on old versions of Android (tested 4.3) the AndroidOpenSSL provider can return an all 0 IV with the below, whereas the same code on 7 will spit out seemingly-random IVs.

secret_key_iv.java

Using the newer KeyGenParameterSpec APIs and the AndroidKeyStore Provider seems to be fine regarding this issue from the small amount of testing I have done.

Enforcing a random IV

It may be worth explicitly declaring an IV to avoid the potential of the default one zero-ing out, which from the above depends on the providers implementation in use. This can be as simple as:

explicit_iv.java

Worth being aware of isRandomizedEncryptionRequired() exists if you want to manually ensure the IV is randomised, otherwise cipher.init will throw if an IV is supplied.

Some of the Android examples do now suggest this, but I find it can be easy to forget when looking at other example code.

If interested in Android security take a look at doridori/Android-Security-Reference