How to Encrypt Local data with EncryptedSharedPreferences in Android

Posted By : Prabhat Pandey | 31-Jan-2023

You must have used SharedPreferences in your app to store data locally in Key-Value pairs. But do you know, any malicious person can find and read all your SharedPreferences data? 

In this article, I will tell you how you can encrypt your local preferences using EncryptedSharedPrefs in your app.

 

EncryptedSharedPreferences

EncryptedSharedPreferences is a library offered by Android SDK. It is a wrapper around the SharedPreferences class and allows developers to automatically encrypt and decrypt keys and values while saving and reading the local data. 

Saving and reading the data is similar to SharedPreferences hence it becomes too easy to use this library. The only different thing is the setup of this library.

 

How to use EncryptedSharedPreferences?

Below are the steps to configure and use the EncryptedSharedPreference library. Keep in mind that you should not back up the preferences file with Auto Backup. Because it is more likely that the key used to encrypt the preferences will not be present after you restore the file. For more information on backup rules, visit [here].

 

Step 1

Add the below dependency inside your app-level build.gradle file.

 


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

 

Step 2

Create an object named Keys in your application. This will hold all the keys that we will use in our secured shared prefs implementation.

 


// The singleton object to hold all keys for our secret prefs
object Keys {
    // ...
    // ...
    private const val EMAIL = "key_email"
    // ...
    // ...
}

 

Step 3

Create a new class as a delegation of EncryptedSharedPreferences and define context as a constructor argument. You can name it whatever you want but I name it SecretPrefs. 

If you are using any Dependency Injection (which you should), inject this class as a singleton. Because you don’t need to create a new instance of it every time you use it.

 


class SecretPrefs(private val context: Context) {

    // your code here

}

 

Step 4

Inside the SecretPrefs class, create a master key alias using the MasterKeys class.

 


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

 

Step 5

Create an instance of SharedPreferences using EncryptedSharedPreferences.create() factory method. Pass the master key alias, file name, and encryption schemes for keys and values as arguments.

 


private val sharedPreferences = EncryptedSharedPreferences.create(
    "secret_prefs",
    masterKeyAlias,
    context,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

override val editor: SharedPreferences.Editor?
    get() = sharedPreferences.edit()
    

 

Step 6

Create functions for saving and reading the data using our EncryptedSharedPrefs instance.

 


// Method to save the email to encrypted prefs
fun saveEmail(email: String) {
    editor?.putString(Keys.EMAIL, email)
    editor?.apply()
}


// Method ro read the email from encrypted prefs
fun email() : String? = sharedPreferences.getString(Keys.EMAIL, null)

 

Step 7

Create a companion object inside SecretPrefs and put the below code inside that. It will make sure that you create only one instance of SecretPrefs and use it everywhere you need. You can also use dependency injection libraries like Hilt or Koin and inject SecretPrefs as a singleton.

 


companion object {

    @Volatile private var INSTANCE: SecretPrefs? = null

    fun getInstance(context: Context) : SecretPrefs =
        INSTANCE ?: synchronized(this) {
            INSTANCE ?: SecretPrefs(context).also { INSTANCE = it }
        }
}

 

Step 8

Create an instance of SecretPrefs and use it to save or read the data in key and value format from any class. 

 


class PlayStreamFragment : Fragment() {

    private var prefs: SecretPrefs? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {


        // get singleton instance of SecretPrefs
        prefs = SecretPrefs.getInstance(requireContext())


        // save values
        prefs?.saveEmail("[email protected]")


        // read values 
        val savedEmail = prefs?.email()

    }

}

Verify

You can also verify that your locally saved data is encrypted. Go to Device File Explorer tab on your Android Studio while your device is connected. Navigate to data/data/YOUR_PACKAGE_NAME and open the shared preferences file. You will see that the keys and values you saved in it are encrypted.

About Author

Author Image
Prabhat Pandey

Prabhat is an accomplished and detail-oriented Android Developer with extensive experience in Android, Kotlin, Java, and problem-solving. He possesses excellent communication skills and excels in bringing team members together to achieve common goals within given timeframes and budgets. Committed to delivering viable and functional app solutions, Prabhat consistently produces impeccable code. He has made valuable contributions to various projects, including the development of the Pandojo Android app using Kotlin and WebRTC, the DytaBank Android app using Kotlin and Jetpack Compose, the BancMania Android app using Firebase and Kotlin, and the TutorX Android app using WebSockets and WebRTC.

Request for Proposal

Name is required

Comment is required

Sending message..