Secure your data with Encrypted Shared Preferences from Jetpack libraries
Security is a very important topic and has to be taken seriously when developing Android applications, especially if sensitive data is stored on the device such as user information or API tokens. Some third party libraries already exist to secure the app data like SecurePreferences but Google introduced its own security library within the Jetpack suite. Let see how we can use it to encrypt the shared preferences of an application and do the migration from SecurePreferences.
Jetpack Security libraries overview
The Jetpack suite provides two security libraries to secure your app data. Security-crypto is there to encrypt files stored by your application or to secure the keysets stored the shared preferences. Security-identity-credential provides a secure store for user identity documents. For devices running Android 11 where Identity Credential is supported, the Identity Credential APIs will be used, otherwise an Android Keystore-backed implementation will be applied.
The crypto and identity libraries are supported from Android 24 and above. Starting with the version 1.1.0-alpha01, the crypto library can be used from Lollipop devices (API 21).
To use these libraries in your projects, you just need to add the following Gradle dependencies:
Under the hood, Jetpack security is using the crypto library Tink developed and maintained by a team of cryptographers and security engineers at Google. Tink is cross-platform and can be used in multiple languages (Java, C++, python…). The library provides secure APIs that are easy to use and offers several cryptographic operations such as HMAC (hash-based message authentication code), AES-GCM (Advanced Encryption Standard), ECDSA (Elliptic Curve Digital Signature Algorithm) or even supports envelope encryption with a Google Cloud KMS key for example.
Tink is a multi-language, cross-platform, open source library that provides cryptographic APIs
Now that we are all set, let’s dig into the crypto library in order to secure the shared preferences of our applications.
Encrypted shared preferences
Here, we are going to use
EncryptedSharedPreferences to secure the key value pairs stored in the shared preferences. You can create a new preference file when you are building your current or new application, or you can easily migrate your existing preference file to an encrypted one.
EncryptedSharedPreferences relies on Advanced Encryption Standard (AES) for securing the data in your shared preferences. Two kinds of AES mode of operation will be used to do so: Galois/Counter Mode (AES-GCM) and Synthetic Initialization Vector (AES-SIV) which is similar to GCM. If you want to know more about these algorithms you can check the RFC 5116 documentation from IETF. You can also provide your custom mode of operation using the Tink library.
If we look closely at the class,
EncryptedSharedPreferences is an implementation of
SharedPreferences that allows the keys and values to be encrypted. Getting the encrypted key value pairs will be the same as it is for the common shared preferences.
You can define your
EncryptedSharedPreferences instance as the following. You will have to pass the preferences file name, a context, a master key alias created thanks to a key spec that uses the AES-GCM encryption scheme (MasterKeys.AES256_GCM_SPEC) and the encryption schemes for the preference keys and values.
Starting with the version 1.1.0-alpha01, the APIs methods have changed to support Lollipop devices. It now uses a builder to generate the master key depending on the Android version you target.
Jetpack security libraries provide only one encryption key but you can create your own key generator spec using the class
KeyGenParameterSpec.Builder which is available since the Android API level 23.
The first time the file is created, you will see a very long warning in your Logcat that might be a bit scary. But do not worry, it is just there to notify that the keyset is not yet created and has to be generated by Tink.
Now that your encrypted shared preferences are settled, you can easily access the stored data or put new values as usual with SharedPreferences.
In debug mode, if you take a look at the preference file in the app data (data/data/<app.package.name>/shared_prefs/), you should have access to the secured file and see the encrypted keys and value. It should be something like this:
Now, let’s see how we can migrate from the deprecated SecurePreferences library to the Jetpack one.
Migrate from SecurePreferences
Before Google introduced its security libraries, Scott Alexander-Bown released a library (Secure-preferences) to secure the shared preferences of applications. This library has been marked as deprecated by its author and he invites the users to migrate to
EncryptedSharedPreferences from androidx.security. Let’s see how you can easily handle the migration.
Please use EncryptedSharedPreferences from androidx.security in preferenced to secure-preference.
If you try to create the new
EncryptedSharedPreferences file using the current
SecurePreferences file name, you won’t be able to access the keyset. First,
SecurePreferences has to coexist with the encrypted shared preferences to copy the secure data from the deprecated library to the new encrypted file. Remember that file names must be different. Then, right after the data has been copied, you will be able to delete the old file to only use the file from
Once all your users are on the new version where
EncryptedSharedPreferences is supported, you will be able to drop the support of Secure-preferences and remove it from your dependencies. That’s the main drawback here, the process of migrating all users to the new version can take a very long time.
Security is very important while developing applications. Everyone should think of using these libraries as much as possible to ensure that users evolve in a secure environment. Thanks to that, you will be able to easily secure your sensitive information without any hardcoded secure key in your APKs and you will avoid working directly with the Android KeyStore.
If you are already using DataStore for storing key-value pairs or typed objects, I advise you to take a look at the article “DataStore: Security” written by Mark Allison where he shows how to secure data thanks to a Cipher.
I hope you liked this article and learnt how to secure your shared preferences. Do not hesitate to ping me on Twitter if you have any question 🤓