How to create masterKey after MasterKeys deprecated in Android

19.8k Views Asked by At

I am using the following code to store some information encrypted in my app.

    val masterKey = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)

    val sharedPreferences = EncryptedSharedPreferences.create(
        "secret_shared_prefs",
        masterKey,
        this,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )

Since the MasterKeys class deprecated in Android, I should use the MasterKey class and but I cannot figure out what is the right method to get the same mastery defined.

Could somebody show the exact match with the available MasterKey and MasterKey.Builder classes?

The below solution worked like this:

val spec = KeyGenParameterSpec.Builder(
        "_androidx_security_master_key_",
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    )
        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
        .setKeySize(256)
        .build()

    val masterKey: MasterKey = MasterKey.Builder(this)
        .setKeyGenParameterSpec(spec)
        .build()

    val sharedPreferences = EncryptedSharedPreferences.create(
        this,
        "secret_shared_prefs",
        masterKey, // masterKey created above
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
7

There are 7 best solutions below

7
xproph On BEST ANSWER

I had exactly the same problem today. See below for fix/workaround (example is in Java code but you can easily do the same in Kotlin)

  1. Use MasterKey.Builder to create MasterKey (instead of MasterKeys). Build it with "manually" created KeyGenParameterSpec:

     // this is equivalent to using deprecated MasterKeys.AES256_GCM_SPEC
     KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
             MASTER_KEY_ALIAS,
             KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
             .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
             .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
             .setKeySize(KEY_SIZE)
             .build();
    
     MasterKey masterKey = new MasterKey.Builder(MainActivity.this)
             .setKeyGenParameterSpec(spec)
             .build();
    
  2. Create EncryptedSharedPreferences using slightly different version of "create" method:

     EncryptedSharedPreferences.create(
             MainActivity.this,
             "your-app-preferences-name",
             masterKey, // masterKey created above
             EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
             EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
    

That should do the trick :)

Reference and more details: https://devmainapps.blogspot.com/2020/06/android-masterkeys-deprecated-how-to.html

4
yohannes  seifu On

try this one


MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
        .build();

SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
        context,
        SHARED_PREF_NAME,
        masterKey,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM);
0
Neha Rathore On

you can use either of the way

KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
     MASTER_KEY_ALIAS,
     KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
     .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
     .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
     .setKeySize(KEY_SIZE)
     .build();

MasterKey masterKey = new MasterKey.Builder(MainActivity.this)
     .setKeyGenParameterSpec(spec)
     .build();

or

MasterKey masterKey = new 
              MasterKey.Builder(context,MasterKey.DEFAULT_MASTER_KEY_ALIAS).
              setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build();

MasterKey.KeyScheme.AES256_GCM internally use same key generatespec as stated above.

0
Jimale Abdi On

You can use it like this below

//Creating MasterKey
            val masterKey = MasterKey.Builder(context)
                .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
                .build()

            val fileToRead = "your_file_name.txt"
            val encryptedFile = EncryptedFile.Builder(context,
                File(context.filesDir, fileToRead),
                masterKey,
                EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
            ).build()
1
CmoiJulien On

My version to get secret shared preference :

private fun getSecretSharedPref(context: Context): SharedPreferences {
    val masterKey = MasterKey.Builder(context)
            .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
            .build()

    return EncryptedSharedPreferences.create(context,
            "secret_shared_prefs",
            masterKey,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )
}
0
Matt Robertson On

If you're using the -ktx version of androidx.security:security-crypto you can reduce some of the boilerplate to just this:

val encryptedSharedPrefs = EncryptedSharedPreferences(
    context,
    ENCRYPTED_STORAGE_FILENAME,
    MasterKey(context)
)
1
mtrakal On

Kotlin version based on responses here with dependency on Security kotlin version androidx.security:security-crypto-ktx

class EncryptedPrefsImpl(context: Context) { 
    private companion object {    
        const val PREFERENCES_NAME = "some_file_name_here"
    }

    private val spec = KeyGenParameterSpec.Builder(
        MasterKey.DEFAULT_MASTER_KEY_ALIAS,
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    ).apply {
        setBlockModes(KeyProperties.BLOCK_MODE_GCM)
        setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
        setKeySize(MasterKey.DEFAULT_AES_GCM_MASTER_KEY_SIZE)
    }.build()

    private val masterKey = MasterKey.Builder(context).apply {
        setKeyGenParameterSpec(spec)
    }.build()

    val preferences: SharedPreferences by lazy {
        EncryptedSharedPreferences(
            context,
            PREFERENCES_NAME,
            masterKey
        )
    }
}