We are all aware that it’s important to store data securely inside an app. With the Android Jetpack Security library, this is easier than ever. In just a few lines of code, you can set up the data encryption and decryption system. Additionally, we are going to cover the usage of BiometricPrompt as an extra level of security, using time-bound keys.
Unlike iOS, where it’s possible to store your password, PIN, certificates, etc. directly in KeyChain, Android uses a different approach:
Okay, let’s get started.
Jetpack Security (JetSec) is a part of Android Jetpack. It provides abstractions for encrypting and decrypting SharedPreferences and Files. It also provides us with easy key management for the Android Keystore system.
To use JetSec in our application you need to include it in your project first. Add this to your app-module build.gradle file:
You must also add the Google Maven repository to your project. The 1.1.0 version provides support for devices that run Android 5.0 (API level 21) and higher. But I should mention that on Android 5.0 (API level 21) and Android 5.1 (API level 22), you cannot use the Android Keystore to store keysets.
To encrypt or decrypt a message, you first need to generate a key for the cryptographic operations. To do that, you will use the MasterKey class. Masterkey will also take care of the key management as it saves the key in the Android Keystore system.
“The Android Keystore system lets you store cryptographic keys in a container to make it more difficult to extract from the device. Once keys are in the keystore, they can be used for cryptographic operations with the key material remaining non-exportable.”
To generate the key with default parameters, try doing this:
If you chose AES256_GCM for the KeyScheme, these will be the default parameters for the key generation:
If you need to further configure your key, you can use KeyGenParameterSpec to make it specific for the use case.
Let me introduce you to two additional options for increasing key security:
If you choose to increase the security of your application with user authentication, learn how to do it below.
After you set the option setUserAuthenticationRequired to “true”, you can use BiometricPrompt for user authentication (switch to the feature/biometrics branch in the project to see this feature).
Now, place the function that requires the key (in our example, that’s the lambda function onSuccess()) inside of the AuthenticationCallback in the onAuthenticationSucceeded:
And change the key generation to:
The second parameter in setUserAuthenticationRequired is optional and it’s the number of seconds that the key should remain accessible for following user authentication. If not previously set, it will, by default, last 300 seconds.
In case your user doesn’t authenticate, and you try to use the key, this will be the outcome:
Now, let’s finally get to data encrypting and decrypting. First, you need to create an EncryptedFile object:
To write into the file, use openFileOutput:
Using the Device File Explorer, you can explore the file content and check if the encryption was successful. The path should look something like this: data/data/projectName/files/FILE_NAME.
To read from the encrypted file, use the following:
In case the file doesn’t exist, you will get an exception and the empty string will return.
If you need to store smaller data securely, you can use EncryptedSharedPreferences.
Using EncryptedSharedPreferences is really easy and after you initialise the EncryptedSharedPreferences, the approach is the same as with SharedPreferences, so let’s get started.
To create EncryptedSharedPreferences, use:
As you can see, EncryptedSharedPreferences.create() returns an instance of SharedPreferences.
And now to encrypt and decrypt data, simply use the Editor interface:
If you check the XML file, from the SharedPreferences, using the Device File Explorer, you’ll see that the value is encrypted. This is what I’ve received for using ‘123456789’ as input:
Click here to see Jetpack security in a sample app I’ve built.
The sample app covers encrypting and decrypting data with EncryptedFile and EncryptedSharedPreferences. It uses MasterKey to generate and handle key management of the encryption/decryption key. Also, you can switch to the feature/biometrics branch to see how BiometricPrompt increases security.
Android is safe enough, but sometimes you want to use an extra level of security for the sensitive data like passwords, API keys or whatever you define as sensitive in your app.
Jetpack security provides out-of-the-box security for general purposes, but also allows you to customize and enhance your security, if needed, with adding StrongBox or specifying parameters for key generation. It’s simple to use and in just a few lines of code you can additionally secure your data.
If you run into any questions, feel free to reach out. Good luck!