Search code examples
kotlinencrypted-shared-preference

How to create masterKey after MasterKeys deprecated in Android


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);

Solution

  • 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