Android Jetpack Security
By: Kayvan Kaseb
Tags: Security, Android, Encryption, Android App Development, Jetpack

The picture is provided by Unsplash

Without doubt, security is an essential issue in Android application development; however, accomplishing all tasks correctly could be tricky. At Google IO/2019, Google introduced the Jetpack Security library, which aims to address some significant issues in Android security to ease the process of making apps more secure. This essay seeks to discuss some features in Android Jetpack Security for having more secure apps.

Overview and Introduction

Even though the Android operating system is extremely secure and we have separate file-based encryption system, there are some vital reasons for consideration as below:

If you have built an Android app that has been running on a rooted or compromised device, the file system is unlocked when the user is actively on the device. This means that even though you have full disk encryption, the data would be available for an attacker or someone that has an access to the device.

Probably, you have sensitive data that you do not want to allow to a user to observe. Therefore, if you have such as API keys and tokens, you probably do not want those leaked. Technically, when they can access to those sensitive data, they could start pretending to be you, and using your quota for their purposes as well.

At Google IO/2019, Google introduced the new Jetpack Security library, which aims to solve some significant issues in Android security like those problems that were mentioned before. Jetpack Security provides an abstraction over security. In fact, it is a wrapper around primitives that are built into the platform. As a result, it makes encrypting files and shared preferences more effectively. There are three main features that Jetpack Security provides for you as follows: Key management, File encryption, and SharedPreferences encryption.

The Security library, part of Android Jetpack, provides an implementation of the security best practices related to reading and writing data at rest, as well as key creation and verification.

Basically, this library uses the builder pattern to create safe default settings for the following security levels:

Strong security that make balances between noticeable encryption and acceptable performance. This level of security is appropriate for consumer apps such as banking and chat apps.

2. Maximum security. This level of security is appropriate for applications that need a hardware-backed key-store and user presence for supporting key access.

Initially, AndroidX Security is using the Tink library under the hood. Tink is an open-source crypto library created by Google that provides cryptographic APIs. Additionally, we have two kinds of data that an Android app should protect: Data at rest and data in transit. Data in transit is data that is actively moving through the network; for instance, when you are transferring data from the device’s local storage to cloud storage. Data at rest is data that is not actively moving like data stored locally on your device. In most cases, data at rest is a much more precious target to obtain in comparison with data in transit. So, Android Jetpack Security currently supports data at rest.

Installation

To use this library in your Android app (It is available for Android version 6.0 or higher), all you need to do is adding this line of code to the app’s Gradle file:

dependencies {

implementation "androidx.security:security-crypto:1.0.0-rc02"

}

Also, you must add the Google Maven repository to your project for using the library.

Key Management

Fundamentally, the Android Key-store system allows to you store cryptographic keys in a container to make it much more difficult to extract from the Android device. Key-store very similar to a map where you have a description of a key for each key you have, and also all keys in Android Key-store have an alias.. Notwithstanding the fact that your app has access to the keys, it does not know what the key content is. Besides, it provides facilities to restrict when and how keys can be used such as requiring user authentication for key use, or restricting keys to be used only in certain cryptographic modes. By using Jetpack Security, you can be able to store your key in the Android Key-store via using the MasterKeys class efficiently and easily. This class allows you to use key-store keys out of the box. MasterKeys class uses a popular recommended standard, which is called Advanced Encryption Standard (AES). In other words, it is one of the most important secure methods that you can use on Android.

In addition, the Security library uses two types of key for key management concept as below:

A key-set that includes one or more keys to encrypt a file or shared preferences data. The key-sets are encrypted and stored in the shared preferences.

that includes one or more keys to encrypt a file or shared preferences data. The key-sets are encrypted and stored in the shared preferences. A master key that encrypts all key-sets. Only the master key is stored in the Android Key-store system to make it more difficult to extract from the device.

MasterKeys class allows you to have a recommended default master key with default settings as below:

val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC

val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

MasterKeys class consists of methods to create and obtain master keys in Android Key-store. getOrCreate() method gets or creates the master key provided. The encryption scheme is a required field. So, in this code, there is only one value that you can use, MasterKeys.AES256_GCM_SPEC . Thus, we use the block mode GCM, and there is no padding. In other words, if you want to encrypt a small amount of data that is of the key size or less, you do not really need any padding or blocking modes. The important issue here is that a number of attacks and challenges happen with encryption when you have data that is longer than the key length. Therefore, you can be able to use padding and blocking in this case.

In addition to this section, if you want to have your own configuration, you can build your own custom master key by using the KeyGenParameterSpec class. Another important point is that you can add an extra level of protection by using bio-metric prompt, fingerprint, or face identification. This would need authorization for both encryption and decryption of keys.

File Encryption

Another important feature of Jetpack Security Library is file encryption, which you can encrypt your files in your app at the same time. All you need to perform is creating a file, and then make this file as an encrypted file as follows:

val fileToRead = "my_sensitive_data.txt"

val encryptedFile = EncryptedFile.Builder(

File(directory, fileToRead),

context,

masterKeyAlias,

EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB

).build()

EncryptedFile class represents custom implementations of FileInputStream and FileOutputStream. It makes your app more secure in reading and writing operations. EncryptedFile is a streaming file; thus, you can encrypt very large files via this capability.

After obtaining the encrypted file, if you want to write some data to your encrypted file or read from it, you can use the openFileOutput() and openFileInput() methods as below:

encryptedFile.openFileOutput().bufferedWriter().use { bufferedWriter -> // Writing some data.. }



encryptedFile.openFileInput().bufferedReader().useLines { lines -> // Reading data.. }

SharedPreferences Encryption

You can also encrypt shared preferences with Jetpack Security. Encrypting shared preferences is similar to encrypting files. Generally, we store our data in SharedPreferences because it is easy to use. In the meantime, it would be an easy target for the attackers to obtain the keys from SharedPreferences. Therefore, we require to encrypt our SharedPrefernce data with utilizing EncryptedSharedPreferences feature in Security library. The important note to indicate is that the keys and values are encrypted in a different way. You can encrypt shared preferences as follows:

val sharedPrefs = EncryptedSharedPreferences.create( "my_secure_preferences", MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),

context, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM )

Although reading and writing operations on the encrypted shared preferences have some positive consequences, they are slower because they are decrypted every time in order to access them. In short, there is a notable performance difference when initializing encrypted shared preferences in comparison with regular situation. So, you should use this feature when it is needed.

In conclusion

This article explained some features in Android Jetpack Security in Android app development. Even though there are some prominent classes in this library for Android developers, there are some drawbacks are remained to consider such as some limitations in applying some algorithms and comparability of Android devices in working with this library (This is available for Android version 6.0 or higher).