0

I am attempting to perform a signing operation with a secret key that can only be used after user authenticates with their device biometrics. I have the logic like this

            val mac = initMac(keyAlias)
            val biometricPrompt = createBiometricPrompt()

            biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(mac))

The initMac function gets a Mac Crypto object to be used for the signing after successful authentication

 private fun initMac(keyName: String): Mac {
    val keyStore = KeyStore.getInstance("AndroidKeyStore")
    keyStore.load(null)
    var secretKey = keyStore.getKey(keyName, null) as SecretKey?
    if(secretKey == null) {
        secretKey = generateKey(keyName, this)
    }
    val mac = Mac.getInstance("HmacSHA256")
    mac.init(secretKey)
    return mac
}

The key generation itself looks like this

val keyGenerator =
            KeyGenerator.getInstance(KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore")
keyGenerator.init(KeyGenParameterSpec.Builder(keyAlias, PURPOSE_SIGN)
.setUserAuthenticationRequired(true))
.build()

When I run this I get the fingerprint dialog as expected and on fingerprint scanned the onAuthenticationSucceeded funtion in the callback gets triggered and the Mac object get's supplied as argument as expected. The problem though is that when I attempt to perform the signing with the Mac object I get a Keystore operation failed error even though I have successfully scanned my biometrics(which means authentication was successful). Here is the logic for the signing and the error I get.

object : BiometricPrompt.AuthenticationCallback() {
 override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
            super.onAuthenticationSucceeded(result)
            Log.d(TAG, "Authentication was successful")
            val fingerprint = result.cryptoObject?.mac?.doFinal(SALT.toByteArray())
        }
}

The error

 java.security.ProviderException: Keystore operation failed
    at android.security.keystore2.AndroidKeyStoreHmacSpi.engineDoFinal(AndroidKeyStoreHmacSpi.java:241)
    at javax.crypto.Mac.doFinal(Mac.java:667)
    at javax.crypto.Mac.doFinal(Mac.java:742)
     Caused by: android.security.KeyStoreException: Key user not authenticated (internal Keystore code: -26 message: In KeystoreOperation::finish

Caused by:
    0: In finish: KeyMint::finish failed.
    1: Error::Km(ErrorCode(-26))) (public error code: 2 internal Keystore code: -26)
    at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:369)
    at android.security.KeyStoreOperation.handleExceptions(KeyStoreOperation.java:78)
    at android.security.KeyStoreOperation.finish(KeyStoreOperation.java:128)
    at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer$MainDataStream.finish(KeyStoreCryptoOperationChunkedStreamer.java:228)
    at android.security.keystore2.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:181)
    at android.security.keystore2.AndroidKeyStoreHmacSpi.engineDoFinal(AndroidKeyStoreHmacSpi.java:237)
        ... 13 more
Oyebisi
  • 562
  • 2
  • 9
  • 23
  • Just tried this on a real device(not emulator) and it works. Maybe it's just an issue with the emulator. – Oyebisi Dec 09 '22 at 06:31

0 Answers0