Flutter原生调用Android KeyStore密钥未触发身份验证问题求助
解决方案:通过BiometricPrompt触发身份验证后使用KeyStore密钥签名
可以实现,问题出在你直接使用KeyStore中的私钥进行签名,没有触发Android的身份验证流程。KeyStore要求这类受保护的密钥必须在用户验证通过后才能使用,所以需要借助BiometricPrompt完成身份验证,获取经过授权的密钥实例后再执行签名操作。
实现步骤:
- 先检查设备是否支持生物识别或设备凭据验证
- 创建
BiometricPrompt并配置验证弹窗信息,绑定签名用的CryptoObject - 在验证成功的回调中,使用授权后的密钥执行签名操作
- 通过自定义回调将签名结果返回给Flutter侧
完整示例代码
1. 确保依赖配置(build.gradle)
implementation "androidx.biometric:biometric:1.1.0"
2. 签名逻辑实现(MainActivity.kt)
import android.security.keystore.KeyStore import androidx.biometric.BiometricManager import androidx.biometric.BiometricPrompt import androidx.core.content.ContextCompat import java.security.PrivateKey import java.security.Signature // 定义回调接口,用于向Flutter传递签名结果 interface SignResultCallback { fun onSignatureSuccess(signedData: ByteArray) fun onSignatureFailed(errorMsg: String) } class MainActivity : FlutterActivity() { private var currentCallback: SignResultCallback? = null // 暴露给Flutter的签名方法 fun startSigning(dataToSign: ByteArray, callback: SignResultCallback) { currentCallback = callback checkAuthenticationSupport(dataToSign) } private fun checkAuthenticationSupport(data: ByteArray) { val biometricManager = BiometricManager.from(this) val authTypes = BiometricManager.Authenticators.BIOMETRIC_STRONG or BiometricManager.Authenticators.DEVICE_CREDENTIAL when (biometricManager.canAuthenticate(authTypes)) { BiometricManager.BIOMETRIC_SUCCESS -> launchBiometricPrompt(data) else -> currentCallback?.onSignatureFailed("设备不支持生物识别或设备凭据验证") } } private fun launchBiometricPrompt(data: ByteArray) { try { // 初始化Signature实例,关联KeyStore中的密钥 val signature = Signature.getInstance("SHA256withECDSA") val keyStore = KeyStore.getInstance("AndroidKeyStore") keyStore.load(null) val privateKey = keyStore.getKey("xxx", null) as PrivateKey signature.initSign(privateKey) // 绑定Signature到CryptoObject val cryptoObject = BiometricPrompt.CryptoObject(signature) // 配置验证弹窗信息 val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("身份验证") .setSubtitle("请验证身份以完成签名") .setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG or BiometricManager.Authenticators.DEVICE_CREDENTIAL) .build() // 创建BiometricPrompt并启动验证 val executor = ContextCompat.getMainExecutor(this) val biometricPrompt = BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) result.cryptoObject?.signature?.let { authSignature -> try { authSignature.update(data) val signedBytes = authSignature.sign() currentCallback?.onSignatureSuccess(signedBytes) } catch (e: Exception) { currentCallback?.onSignatureFailed("签名失败:${e.message}") } } ?: currentCallback?.onSignatureFailed("无法获取授权的签名实例") } override fun onAuthenticationFailed() { super.onAuthenticationFailed() currentCallback?.onSignatureFailed("身份验证失败") } override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) currentCallback?.onSignatureFailed("验证错误:$errString") } }) biometricPrompt.authenticate(promptInfo, cryptoObject) } catch (e: Exception) { currentCallback?.onSignatureFailed("初始化签名流程失败:${e.message}") } } // 你的密钥生成代码... }
核心说明:
- CryptoObject绑定:将Signature实例与BiometricPrompt绑定后,验证通过时KeyStore会自动授权该实例使用受保护的私钥,避免直接调用未授权密钥抛出异常。
- 验证类型匹配:弹窗配置的
AllowedAuthenticators与密钥生成时的AUTH_DEVICE_CREDENTIAL or AUTH_BIOMETRIC_STRONG保持一致,确保验证方式兼容。 - Flutter通信:通过
SignResultCallback结合MethodChannel,可将签名结果无缝传递给Flutter侧调用方。
内容的提问来源于stack exchange,提问作者user2801516
相关产品推荐
相关产品推荐

