Open In App

How to Encrypt Data Safely on the Device and Use the Android KeyStore?

Last Updated : 19 Nov, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

We deal with a great number of data in Android. Data from one activity is used in a different activity or fragment. For example, when some data changes, we can modify the UI of an application. So, the main concept is to have efficient communication between the data and the application’s UI, and we all know that the ideal way to do it is to use Android Jetpack’s LiveData.

Security Library in Jetpack

We will be using the Jetpack Security Library, which can be trusted as it’s backed by good, it was also launched in 2019 making it relatively new. It even allows securing the shared_prefs and other data. It maintains a solid level of security by striking a balance between excellent encryption and fast performance. So we simply need to use the Jetpack Security library. Why utilize this Android Jetpack Security Library when the Android operating system is incredibly safe and we have a separate file-based encryption solution? 

There are a number of causes for this, including:

  1. Even if you have full disc encryption, the file system on a rooted Android device is unlocked, and the data is easily accessible by an attacker.
  2. Another argument could be that you don’t want even your users to have access to your application’s keys or tokens.
dependencies {
    ...
    implementation 'androidx.security:security-crypto:{latest-version}'
}

Management Personnel

We need to keep track of the keys we use in our Android app. So, on Android, we have something called the Android Keystore System, which protects our keys from being exploited by others. We have a MasterKeys class in Jetpack Security that allows us to construct a private key (by default, AES256 is used). Essentially, this class provides easy-to-use methods for creating and retrieving master keys from the Android Keystore.

val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

We’re utilizing the block mode GCM SPEC with no padding in this case. You don’t need any padding or blocking if you wish to encrypt a little piece of data the size of a key. When the data to be encrypted is larger than the size of a key, padding and blocking are used.

Encryption of files

You may encrypt your app’s files using the Jetpack Security Library. To handle files of any size, it employs the Streaming AES algorithm. It’s as simple as creating a file and then converting it to an encrypted file. If you want to write data to your encrypted file after acquiring it, you may use the openFileOutput() method, and if you want to read data from your encrypted file, you can use the openFileInput() method. The code for this is as follows:

val gfgKeyAlias= MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
val file = File("ANY_FILE_NAME")
val encryptedFile = EncryptedFile.Builder(
    file,
    applicationContext,
    gfgKeyAlias,
    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()

encryptedFile.openFileOutput().use { outputStream ->

}

Encryption of SharedPreferences

We use SharedPreferences to store our data since it is simple to use, but it also makes it simple for attackers to obtain the key and value from SharedPreferences. As a result, we’ll need to encrypt our SharedPreferences data, which we can achieve with EncryptedSharedPreferences, which is available for Android 6.0 and higher. Simply create or retrieve a Master Key from the AndroidKeyStore to use an EncryptedSharedPreference:

val gfgKeyAlias= MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

After obtaining the Master Key, create an instance of EncryptedSharedPreferences as follows:

val anySharedPrefs= EncryptedSharedPreferences.create(
    "your_name_of_shared_prefs",
    masterKeyAlias,
    applicationContext,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

Finally, as normal, you can store and read data from the EncryptedSharedPreferences:

val KEY_DATA = "SHARED_DATA"
val dataToSave = "Some raw values"

// storing the data
anySharedPrefs.edit()
    .putString(SHARED_DATA, someDataBound)
    .apply()

// reading
val sharedData = anySharedPrefs.getString(SHARED_DATA, "")

Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads