How to encrypt data safely on the device and use the AndroidKeyStore?

How to encrypt data safely on device and use the AndroidKeystore?

Data encryption is very important in every Android application. You must have some way to secure your data, your Android files, your shared preferences, the keys that are used in your application. No doubt, even after applying some encryption technique, your data can be retrieved back by some professional but your aim should be how to make it harder for them to get the data by providing some extra layers of security in your application. In this blog, we will learn how to encrypt data safely on the device and use the AndroidKeyStore for storing keys in Android. So, let's get started.

Jetpack Security Library

At Google I/O 19, the Jetpack Security Library was introduced that allows us to easily encrypt data, files, and shared preferences. It provides strong security by keeping the balance between great encryption and good performance. So, all we need to do is just use the Jetpack Security library.

But the Android operating system is very secure and we have a separate file-based encryption system, so why use this Android Jetpack Security Library? There are various reasons for the same, some of these are:

  • If we consider a rooted Android device then the file system is unlocked and the data is easily accessible by some attacker even though you have full disk encryption.
  • Another reason can be securing your keys or tokens in your application because you don't want even your users to access these keys.

So, this Jetpack Security Library is used for encryption on disk and is made available for Android version 6.0 or higher. All you need to do is add this library in your build.gradle file.

dependencies {
    ...
    implementation 'androidx.security:security-crypto:{latest-version}'
}

Key Management

The keys that we use in our Android application must be secured. So, to protect our keys from being used by someone else, we have something called Android Keystore System in Android.

In Jetpack Security, we have a MasterKeys class that allows us to create a private key(by default, AES256 is used). Basically, this class provides convenient methods to create and obtain master keys in Android Keystore.

val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

Here, we are using the block mode GCM_SPEC with no padding. If you want to encrypt a small data that is of the size of a key, then you don't need any padding or blocking. But when the data that is to be encrypted is longer than the size of a key, then we use padding and blocking.

You have other options available with you like setBlockModes(), setEncryptionPaddings, setKeySize(), setUserAuthenticationRequired(), setUnlockedDeviceRequired(), etc. You can check all the options here.

Now, we are having the key and we can use this key to do other stuff like we can use for File Encryption. Let's see how.

File Encryption

With the help of the Jetpack Security Library, you can encrypt your files present in your app. It uses the Streaming AES to handle files of all sizes. All you need to do is create a file and then convert this file into an encrypted file. After getting the encrypted file, if you want to write some data to your encrypted file then you can use the openFileOutput() method and if you want to read data from your encrypted file then you can use the openFileInput() method. Following is the code for the same:

val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

val file = File("YOUR_FILE")

val encryptedFile = EncryptedFile.Builder(
    file,
    applicationContext,
    masterKeyAlias,
    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()

encryptedFile.openFileOutput().use { outputStream ->
    //write data to your encrypted file
}

encryptedFile.openFileInput().use { inputStream ->
    //read file from your encrypted file
}

That's it. Everything is encrypted and decrypted under the hood and you need not worry about anything.

SharedPreferences Encryption

We store our data in SharedPreferences because it is easy to use and at the same time, it also becomes easy for the attackers to get the key and value from the SharedPreferences. So, we need to encrypt our SharedPrefernce data and this can be done with the help of EncryptedSharedPreferences that is available for Android 6.0 or higher.

To use an EncryptedSharedPreference, just create or retrieve a Master Key from the AndroidKeyStore:

val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

After getting the Master Key, now initialize an instance of EncryptedSharedPreferences:

val mySharedPreferences = EncryptedSharedPreferences.create(
    "my_preference_file_name",
    masterKeyAlias,
    applicationContext,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

At last, you can save the data and read the data from the EncryptedSharedPreferences as usual:

val KEY_DATA = "KEY_DATA"
val dataToSave = "Some Data"

//saving the data
mySharedPreferences.edit()
    .putString(KEY_DATA, dataToSave)
    .apply()

//reading the data
val data = mySharedPreferences.getString(KEY_DATA, "")

Closing notes

In this blog, we learned how to encrypt data safely on the device and use the AndroidKeyStore.

Hope you learned something new today.

Have a look at our Android tutorials here.

Do share this blog with your fellow developers to spread the knowledge. You can read more blogs on Android on our blogging website.

Apply Now: MindOrks Android Online Course and Learn Advanced Android

Happy Learning :)

Team MindOrks!