Usage of Jetpack Security with two master keys

258 Views Asked by At

Anyone had success in using Jetpack Security for encryption with two separate master keys? The use case for this is having one set of data encrypted with a "regular" key and another with a key with additional biometric protection.

Tried the following with just two separate keys with the same spec just for testing:

class MainActivity : AppCompatActivity() {

    private val firstMasterKey by lazy {
        MasterKeys.getOrCreate(provideKeyGenParameters("aliasFirst"))
    }

    private val secondMasterKey by lazy {
        MasterKeys.getOrCreate(provideKeyGenParameters("aliasSecond"))
    }

    private val firstEncryptedFile by lazy {
        EncryptedFile.Builder(
            File(filesDir, "firstFile"),
            this,
            firstMasterKey,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        )
            .build()
    }

    private val secondEncryptedFile by lazy {
        EncryptedFile.Builder(
            File(filesDir, "secondFile"),
            this,
            secondMasterKey,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        )
            .build()
    }

    private fun provideKeyGenParameters(alias: String) =
        KeyGenParameterSpec.Builder(
            alias,
            KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
        )
            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
            .setKeySize(256)
            .build()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        saveFiles()
    }

    private fun saveFiles() {
        firstEncryptedFile.openFileOutput().use {
            it.write(ByteArray(1) { Byte.MIN_VALUE })
        }

        // if I comment this save it works fine
        // as soon as I uncomment it the app crashes
        secondEncryptedFile.openFileOutput().use {
            it.write(ByteArray(1) { Byte.MIN_VALUE })
        }
    }
}

but got InvalidProtocolBufferException: Protocol message contained an invalid tag (zero) as soon as the other key was used. This happens on both stable version and and latest alpha03.

I posted a bug report to Google about that https://issuetracker.google.com/issues/192470296 but I have no hope since based on the other reported bugs they don't care at all. Anyways, if you encounter the issue please star it, maybe someone will notice.

1

There are 1 best solutions below

0
Matt Wolfe On

Using the updated androidx.security:security-crypto library (currently alpha06) you can do this:

  companion object {
    private val FIRST_KEY_ALIAS = "aliasFirst"
    private val SECOND_KEY_ALIAS = "aliasSecond"
  }
  private val firstMasterKey by lazy {
        MasterKey.Builder(context, FIRST_KEY_ALIAS)
          .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
          .build()
    }

  private val secondMasterKey by lazy {
        MasterKey.Builder(context, SECOND_KEY_ALIAS)
          .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
          .build()
    }

    private val firstEncryptedFile by lazy {
        EncryptedFile.Builder(
            File(filesDir, "firstFile"),
            this,
            firstMasterKey,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        )
         .setKeyAlias(FIRST_KEY_ALIAS) //don't forget this or it won' work
         .build()
    }

    private val secondEncryptedFile by lazy {
        EncryptedFile.Builder(
            File(filesDir, "secondFile"),
            this,
            secondMasterKey,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        )
         .setKeyAlias(SECOND_KEY_ALIAS) //don't forget this
         .build()
    }

Note that you need to set the key alias on both the MasterKey.Builder and the EncryptedFile.Builder or it won't work. I had this issue where it only worked if I used the same key alias for all encrypted files until I set the key alias for the encrypted file builder.