Sunday 27 September 2020

Invalidate key by biometric enrollment with new androidx.BiometricPrompt

I am using the new androidx.BiometricPromt library to implement authentication with a fingerprint. I want to invalidate key if the user added new fingerprint or deleted one. I am creating key like this:

fun getSecretKey(shouldCreate: Boolean): Key {
    val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
    keyStore.load(null)
    return if (shouldCreate) {
        createSecretKey(keyStore)
    } else {
        keyStore.getKey(ALIAS_BIOMETRICS, null)
    }
}

private fun createSecretKey(keystore: KeyStore): Key {
    val builder = KeyGenParameterSpec.Builder(
        ALIAS_BIOMETRICS,
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    )
        .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
        .setUserAuthenticationRequired(true)
        .setUserAuthenticationValidityDurationSeconds(5)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        builder.setInvalidatedByBiometricEnrollment(true)
        builder.setUserAuthenticationValidWhileOnBody(true)
    }

    val keyGenerator =
        KeyGenerator.getInstance(keyAlgorithm, keystore.provider)
    keyGenerator
        .init(builder.build())
    return keyGenerator.generateKey()
}

And I am starting biometric scan process like this:

val info = BiometricPrompt.PromptInfo.Builder()
    .setTitle(context.getString(R.string.biometric_dialog_title))
    .setSubtitle(context.getString(R.string.biometric_dialog_subtitle))
    .setNegativeButtonText(context.getString(R.string.biometric_dialog_cancel))
    .build()

biometricPrompt = when (screen) {
    is FragmentActivity -> BiometricPrompt(screen, { it.run() }, this)
    is Fragment -> BiometricPrompt(screen, { it.run() }, this)
    else -> throw IllegalArgumentException("Screen type must be FragmentActivity or Fragment")
}

biometricPrompt?.authenticate(info)

I wanted to start biometricPromt?.authenticate(info, cryptoObject) but in this case I need to initialize Cipher and it throwing the exception UserNotAuthenticated. After user successfully scanned biometrics I am creating the SecretKey and use for encryption. Then I am changing fingerprints (add some new fingerprints and remove). And decryption process like encryption but only when getting key I am not creating new one but getting it from keystore. Although I am changed fingerprints everything decyrpting fine. I want to deny decrypting if user changed fingerprints in his device. How to achieve this functionality with androidx.BiometricPrompt library?



from Invalidate key by biometric enrollment with new androidx.BiometricPrompt

No comments:

Post a Comment