Android MasterKeys deprecated — Migrate to EncryptedSharedPreferences

Tuong, Nguyen Thanh (aka Alan)
2 min readJul 13, 2020

--

Photo by Chris Panas on Unsplash

If your application needs to save key-value pairs — such as API keys — Android Jetpack provides the EncryptedSharedPreferences class, which uses the same SharedPreferences interface that you’re used to.

Setup

To get started with the security library, add the following dependency:

dependencies {
implementation 'androidx.security:security-crypto:1.1.0-alpha03'
}

But after upgraded to 1.1.0-alpha01, MasterKeys is deprecated:

New MasterKey class provides more options for keys, also deprecating MasterKeys to support new features and versions of Android that do not have KeyGenParamSpec.

We need to use MasterKey.Builder instead. To create MasterKey:

companion object {
const val MASTER_KEY_ALIAS = "yourKeyAlias"
const val KEY_SIZE = 256
}
private val keyGenParameterSpec = KeyGenParameterSpec.Builder(
MASTER_KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
).setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setKeySize(KEY_SIZE)
.build()

private val masterKeyAlias = MasterKey.Builder(context, MASTER_KEY_ALIAS)
.setKeyGenParameterSpec(keyGenParameterSpec)
.build()

private val preferences = EncryptedSharedPreferences.create(
context,
context.getString(R.string.preference_file_key),
masterKeyAlias,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

For some device, the error appears on creating EncryptedSharedPreferences (1.1.0-alpha03)

Caused by: com.google.crypto.tink.shaded.protobuf.InvalidProtocolBufferException: 
at com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite.parsePartialFrom (GeneratedMessageLite.java:1566)
at com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite.parseFrom (GeneratedMessageLite.java:1664)
at com.google.crypto.tink.proto.Keyset.parseFrom (Keyset.java:957)
at com.google.crypto.tink.integration.android.SharedPrefKeysetReader.read (SharedPrefKeysetReader.java:84)
at com.google.crypto.tink.CleartextKeysetHandle.read (CleartextKeysetHandle.java:58)
at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.read (AndroidKeysetManager.java:328)
at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.readOrGenerateNewKeyset (AndroidKeysetManager.java:287)
at com.google.crypto.tink.integration.android.AndroidKeysetManager$Builder.build (AndroidKeysetManager.java:238)
at androidx.security.crypto.EncryptedSharedPreferences.create (EncryptedSharedPreferences.java:155)
at androidx.security.crypto.EncryptedSharedPreferences.create (EncryptedSharedPreferences.java:120)

Because after uninstalling the application you still have backed up your crypto file which you definitely can’t decrypt after installing a new version.

You can disable backups by setting android:allowBackup to false:

<manifest ... >
...
<application
android:allowBackup="false"
android:fullBackupContent="false">
...
</application>
</manifest>

Exclude specific shared preferences

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="sharedpref" path="."/>
</full-backup-content>

https://developer.android.com/guide/topics/data/autobackup#IncludingFiles

Thanks for reading!

--

--

No responses yet