Modern Security in Android (part 3)

Dinorah Tovar
Google Developer Experts
4 min readMay 24, 2020

A fast guide to be safe

This post is related to my lastest talk about “Modern Security for Android Developers”.

Here is the list of the blogs in this series:

Modern Security for Android Developers

In the last post, we talk about Jetpack Security and how it handles the Key Management.

Once you have created your MasterKey the next step is to use it. Inside Jetpack Security you can encrypt a File or a Shared Preferences.

SharedPreferences

Shared preferences are the most primitive way to save data in Android, you can store Key and Values, this data is stored as an XML file in the app internal directory which cannot be accessed by the user. Per recommendation, developers should use the flag: MODE_PRIVATE as file creation, where the created file can only be accessed by the calling application (or all applications sharing the same user ID)

UPDATE:
The last paragraph was modified after a founding an error on the documentation, the original paragrapah was:
Shared preferences are the most primitive way to save data in Android, you can store Key and Values, this data is stored as an XML file in the app internal directory which cannot be accessed by the user. Per recommendation, Google insists that the developer should use the flag: MODE_PRIVATE to restricts other apps from accessing the data. However due to the fact that you can extract any data from the app sandbox using a simple path of data in Android Studio-

data/data/<com.your.package>/shared_prefs/yourFile.xml

We can see anything inside this file, so if you are storing a token or personal data from your user, it will be exposed in seconds.

However, due to the fact that you can extract data from the app in debug mode using the Device Monitor in Android Studio, is also obvious that Jetpack security is not using SharedPreferences and File; for encryption is using: EncryptedSharedPreferences and EncryptedFile

The first one 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.
Creation of EncryptedSharedPreferences

SharedPreferences will require to use Context in order to create an instance of EncryptedSharedPreferences, and we need to call the static method create() in order to create the instance.

  • masterKeyAlias: the key that will be used for the encryption that is on the top of this article
  • context: in order to access the stored preferences.
  • prefKeyEncryptionScheme: the scheme used to store the key.
  • prefValueEncryptionScheme: the scheme used to store the value.

For reading and writing in the Shared preferences, you can go as always:

Files

EncryptedFile also is a custom implementation of FileInputStream and FileOutputStream, granting your app secure streams to read and write.

To provide secure read and write operations from file streams, the Security library uses the Streaming Authenticated Encryption with Associated Data (AEAD) that provides authenticated encryption for data, and is useful when the data to be encrypted is too large to be processed in a single step, this is the same approach that Tink Library has, typical use cases include encryption of large files or encryption of live data streams.

The underlying encryption modes are selected so that partial plaintext can be obtained fast by decrypting and authenticating just a part of the ciphertext, without the need of processing the entire ciphertext.

The downhill of Files is that the encryption must be done once, there is no way to modify the existing ciphertext or to append to it other than to re-encrypt the entire file again and of course, we have a problem with the limits:

  • Plaintext: can have an arbitrary length within the range 0..2³⁸ and associated data can have an arbitrary length within the range 0..2(³¹)–1 bytes

There are two main classes related to the whole EncryptedFile component; the first is the file we want to encrypt and the EncryptedFile.Builder:

  • file: a file instance that will contain the name and path as always
  • context: In order to access to a file location
  • masterKeyAlias: the key that will be used for the encryption that is on the top of this article
  • fileEncryptionScheme: the scheme used to write bytes into the file.

For reading and writing in the File, you can go as always:

Update of 4 June 2020 :
Looks like this library must implement this on the *.pro files if you want to release to production, If not, the app will crash this is an issue commented on Tink library:
https://github.com/google/tink/issues/361

# Security
-keepclassmembers class * extends com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite {
<fields>;
}

This is all for this part of the post, If you need help:

I’m always happy to help, you can find me here:
Medium: https://medium.com/@dinorahto
StackOverflow: https://stackoverflow.com/users/4613259/dinorah-tovar

Happy Coding! 👩🏻‍💻

--

--

Dinorah Tovar
Google Developer Experts

Google Developer Expert on Android | Doing Kotlin | Making Software 24/7 | Kotlin Multiplatform | She/Her | Opinions are my own, and not my employer