Securing User Data with Encrypted Shared Preferences in Android

Photo by Liam Tucker on Unsplash

Securing User Data with Encrypted Shared Preferences in Android

API access tokens are the key to unlocking the power of various services for your mobile and web applications. But with this power comes the need for security to prevent unauthorized access to sensitive information.

In this article, we will dive into the technique of securing your app's data using Encrypted Shared Preferences of the Jetpack security library.

By the end of this article, you will have a solid understanding of how to safeguard your data in your Android applications and keep your user's data protected using encrypted shared preferences.

Encrypted SharedPreferences

Encrypted shared preference Wraps the SharedPreferences class and automatically encrypts keys and values using a two-scheme method: Keys are encrypted using a deterministic encryption algorithm such that the key can be encrypted and properly looked up. Values are encrypted using AES-256 GCM and are non-deterministic

Include the library in your project

To use the Security library, add the following dependencies, as appropriate, to your app module's build.gradle file:

dependencies {

// security
implementation "androidx.security:security-crypto:1.0.0-alpha02"

}

Show me the code!

To demonstrate encrypted shared preferences, we'll create a helper class with two functions saveData and getData which as the name suggests, will be used to save and get data in a secure way.

Saving Data

private val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

fun saveData(context: Context, key: String, data: String) {
    // Initialize/open an instance of EncryptedSharedPreferences
    val sharedPreferences = EncryptedSharedPreferences.create(
        // passing a file name to share a preferences
        FILE_NAME,
        masterKeyAlias,
        context,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )
    sharedPreferences.edit().putString(key, data).apply()
}

In the snippet above, We start by initializing the android Keystore class which gives us access to a master key alias we'll be using to initialize an instance of the EncryptedSharedPreferences object.

On initializing the EncryptedSharedPreferences, we can then save our data as we normally would using the sharedPreferences edit() and apply() method

Retrieving Data

fun getData(context: Context, key: String): String? {
    // Initialize/open an instance of EncryptedSharedPreferences on below line.
    val sharedPreferences = EncryptedSharedPreferences.create(
        // passing a file name to share a preferences
        FILE_NAME,
        masterKeyAlias,
        context,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )

    //return the value or an empty string if it's null
    return sharedPreferences.getString(key, "")

}

Again, we initialize an instance of the EncryptedSharedPreferences object using the master key alias we created earlier and passing in the name of the key value we want to retrieve.

We can use the functions from our mainActivity.kt file or anywhere in our application like this:

And our complete sharedPreferencesHelper.kt file should look like this:

After running the code we should see:

The username is Astrocoder and the access token is MY_ACCESS_TOKEN printed in the logcat.

You can also check the emulator's data storage to see the encrypted My_file_name.xml file and its content, just like in the image below

Conclusion

The Jetpack team has made it really easy to securely store and retrieve sensitive data in our apps with EncryptedSharedPreferences; Here are some of the advantages of using it:

  • It uses Android keystore to automatically remove the pain of having to achieve the same thing using other methods of encryption

  • Every data we feed it is encrypted, including the key names used to access the shared preference values, as we can see in the image above, making it a lot harder for any attacker to know what data to attack

That's a wrap!!! feel free to reach out to me on any of my social media accounts should you have any questions.

You can find the complete code to this example on GitHub, here

Thank you for reading! Cheers!!!