添加新生物识别时使 SecretKey 无效

Invalidate SecretKey when new Biometrics are added

我 运行 遇到一个问题,当用户将新指纹添加到他们的 Android 设备时,我想使 SecretKey 失效。我可以生成密钥,毫无问题地提取生物识别提示。当我添加一个新的指纹时,密钥没有抛出异常..它仍然允许出现提示。

我可以从设备中删除所有指纹,并抛出 KeyPermanentlyInvalidatedException。

我正在使用 BiometricPrompt AndroidX 库,我的 minSDK 设置为 28。我一直在遵循这个指南:https://developer.android.com/training/sign-in/biometric-auth#crypto

我的代码如下 - 如果有人愿意帮助我解决这个问题,我将不胜感激。

package com.example.dogtime

import android.os.Bundle
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyPermanentlyInvalidatedException
import android.security.keystore.KeyProperties
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import butterknife.ButterKnife
import java.security.KeyStore
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey


class MainActivity : AppCompatActivity() {

    private lateinit var biometricPrompt: BiometricPrompt
    private lateinit var biometricPromptInfo: BiometricPrompt.PromptInfo

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ButterKnife.bind(this)
        setContentView(R.layout.activity_main)

        // Set up prompt
        biometricPrompt = BiometricPrompt(
            this,
            ContextCompat.getMainExecutor(baseContext),
            object : BiometricPrompt.AuthenticationCallback() {
                // no-op
            }
        )

        // Prompt info
        biometricPromptInfo = BiometricPrompt.PromptInfo.Builder()
            .setTitle("Title")
            .setNegativeButtonText("Test")
            .build()

        // Generates key
        findViewById<Button>(R.id.count_btn).setOnClickListener {
            generateKey()
        }

        // Shows biometric prompt
        findViewById<Button>(R.id.random_btn).setOnClickListener {
            getCrypto()?.let { it1 -> biometricPrompt.authenticate(biometricPromptInfo, it1) }
                ?: run {
                    // Key is invalidated - this is never triggered
                }
        }
    }

    private fun generateKey() {
        val keyGenerator = KeyGenerator
            .getInstance(KeyProperties
                .KEY_ALGORITHM_AES, "AndroidKeyStore")
        keyGenerator.init(getKeyGen())
        keyGenerator.generateKey()
    }

    private fun getCipher() : Cipher {
        return Cipher.getInstance(
            KeyProperties.KEY_ALGORITHM_AES + "/"
        + KeyProperties.BLOCK_MODE_CBC + "/"
        + KeyProperties.ENCRYPTION_PADDING_PKCS7
        )
    }

    private fun getKey() : SecretKey {
        val keyStore = KeyStore.getInstance("AndroidKeyStore")
        keyStore.load(null)
        return keyStore.getKey("key6", null) as SecretKey
    }


    private fun getKeyGen() : KeyGenParameterSpec {
        return KeyGenParameterSpec.Builder(
            "key6",
            KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
        ).setBlockModes(KeyProperties.BLOCK_MODE_CBC)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
            .setUserAuthenticationRequired(true)
            .setInvalidatedByBiometricEnrollment(true)
            .build()
    }

    private fun getCrypto() : BiometricPrompt.CryptoObject? {
        return try {
            val cipher = getCipher()
            val key = getKey()
            cipher.init(Cipher.ENCRYPT_MODE, key)
            BiometricPrompt.CryptoObject(cipher)
        } catch(e: KeyPermanentlyInvalidatedException) {
            val keyStore = KeyStore.getInstance("AndroidKeyStore")
            keyStore.load(null)
            keyStore.deleteEntry("key6")
            null
        }
    }
}

(回答我自己的问题)。我已将其与上述解决方案一起用于以下设备规格。

  • 设备:三星 A31、Pixel 2XL
  • Android版本:10
  • 生物识别:指纹

之前我是用模拟器测试的,密钥不会失效。我不确定为什么,但模拟器测试无法有效地测试这种情况。