Android Key Store

Android key store is best bet to store cryptographic key on an Android device. The keys stored here will be stored in the best possible way available. If the device is relatively new this means that it will be probably be in a separated processing environment where not even the kernel can access the key material or in a separated encryption hardware.

The KeyStore API is a standard Java API, with an Android specific provider that handles all the communications for you. This implementation will allow the user to restrict the usage of the key to certain conditions. Keys can be generated to encrypt or sign only. Availability of the keys might be restricted to the user lock state, requiring the user to use it’s unlock method to release the key, this means that keys can be protected by fingerprints on devices that have those.

Much of the KeyStore was originally designed to store asymmetric keys or public/private key pairs. But the latest version of the APIs will allow user to store AES symmetric keys. Even if symmetric keys are not available it is easy enought to wrap generated keys using the public key, so you can unencrypt it with the private KEY.

The basics on how to use this API are here, but the Java cryptographic APIs have some caveats that might get you by surprise.

KeyStore caveats.

  • You need to load the KeyStore.

This KeyStore is not associated with any file or stream of data that is available to the main program. I assumed that the instance would be already loaded after construction. But this is bad assumption, instance are built in an invalid state that is validated when you load the keys using the method load(null).

  • Initialization vectors.

Some block modes require initialization vectors, IV for short. Those IV are selected automatically when you encrypt data, but you need to explicitly provide them at decryption stage. If you are using the default IV make sure you save the value used to encrypt since each provider might use a different default value. Different IVs will make the decryption impossible, even with the key.

  • Signature algorithms have their own names.

  • The Android KeyStore have a set of valid key sizes.

  • I found that key generation fails sometimes.

It is a good practice to attempt to retrieve the key and retry if this fails. You might need to remove the bad key from the KeyStore before continuing.

  • Signatures digest algorithm has to be at most the size of the key, at least for RSA algorithm

This seem obvious but I did not know this. Just the tiny things that you don’t really think about until they come to bite you.