Secure your data with Encrypted Shared Preferences from Jetpack libraries
By: Julien Salvi
Tags: Security, Encryption, Android, Android Development, Jetpack Security

Photo by Micah Williams on Unsplash

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:

Jetpack security 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.

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.

Encryption technique

By default, 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.

Use EncryptedSharedPreferences

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.

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 EncryptedSharedPreferences .