android - BiometricPrompt Android:软件或安全更新后三星出现 UnrecoverableKeyException
问题描述
第一次在这里发帖,祝我好运:)
我们使用 BiometricPrompt API 在我们的移动应用程序中开发了对生物特征认证的支持。我们决定使用 CryptoObjects,因为它允许我们遵守法规。
实施后,我们在三星设备和一些华为设备上面临一个问题,在一些设备软件更新之后以及我们获得的几乎每个安全补丁之后:
Caused by java.security.UnrecoverableKeyException: Failed to obtain information about key
at android.security.keystore.AndroidKeyStoreProvider.getKeyCharacteristics(AndroidKeyStoreProvider.java:238)
at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(AndroidKeyStoreProvider.java:360)
at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:116)
at java.security.KeyStore.getKey(KeyStore.java:1062)
at com.*****.mobile.data.crypto.CryptoRepositoryImpl.getSignature(CryptoRepositoryImpl.java:527)
at com.*****.mobile.business.biometric.authentication.BiometricAuthenticationPromptInteractorImpl$getSignatureForAuthentication$1.subscribe(BiometricAuthenticationPromptInteractorImpl.java:52)
Caused by android.security.KeyStoreException: User authentication required
at android.security.KeyStore.getKeyStoreException(KeyStore.java:1151)
at android.security.keystore.AndroidKeyStoreProvider.getKeyCharacteristics(AndroidKeyStoreProvider.java:240)
at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(AndroidKeyStoreProvider.java:360)
at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:116)
at java.security.KeyStore.getKey(KeyStore.java:1062)
这迫使我们生成一个新的密钥对,导致糟糕的用户体验。
有没有人遇到过类似的问题?并且可以建议需要更改/考虑哪些内容以防止我们的密钥在三星安全补丁后失效/损坏?
我们正在使用以下代码生成密钥对 (使用回退,因为我们发现更便宜的三星设备不支持 EC,因此我们在此类设备上使用 RSA):
@RequiresApi(Build.VERSION_CODES.M)
override fun createSigningKey(keyBaseName: KeyBaseName, useFallbackAlgorithm: Boolean): Either<Throwable, JavaPublicKey> = try {
deleteKey(keyBaseName)
when {
useFallbackAlgorithm -> KeyPairGenerator
.getInstance(KEY_ALGORITHM_RSA, ANDROID_KEY_STORE_PROVIDER)
.apply {
initialize(KeyGenParameterSpec.Builder(keyBaseName, PURPOSE_SIGN or PURPOSE_VERIFY)
.setAlgorithmParameterSpec(RSAKeyGenParameterSpec(KEY_SIZE, RSAKeyGenParameterSpec.F4))
.setDigests(DIGEST_SHA256, DIGEST_SHA512)
.setSignaturePaddings(SIGNATURE_PADDING_RSA_PKCS1)
.setUserAuthenticationRequired(true)
.build())
}
else -> KeyPairGenerator
.getInstance(KEY_ALGORITHM_EC, ANDROID_KEY_STORE_PROVIDER)
.apply {
initialize(KeyGenParameterSpec.Builder(keyBaseName, PURPOSE_SIGN or PURPOSE_VERIFY)
.setDigests(DIGEST_SHA256, DIGEST_SHA512)
.setUserAuthenticationRequired(true)
.build())
}
}.generateKeyPair()
.public
.right()
} catch (e: Exception) {
firebaseRepository.logException(RuntimeException("createSigningKey", e))
e.left()
}
谢谢!
解决方案
您可以尝试实施以下 2 个解决方案,看看它是否适合您。
- 将 allowBackup false 添加到 AndroidManifest.xml 文件
<application
android:allowBackup="false"
...
>
- Android 密钥库不是线程安全的,请使用
synchronized
关键字包装所有 Android 密钥库操作。
推荐阅读
- python - 如何迭代行并将基于前一行的值插入新列
- mysql - 比较两个角度的日期时间(一个是从 mysql 数据库中获取,一个是节点服务器)
- java - MapStruct:合并父对象时调用子对象的合并
- r - 如何以 x 轴为因子绘制平滑线 (ggalt::xspline) 图
- c++ - 变量 'qglviewer::QGLVIEWER_EXPORT qglviewer::Constraint' 具有初始化程序但类型不完整
- tensorflow - 关于 TensorFlow 导入
- php - 使用 xPath 抓取 src 属性值,
- python - 在属性等于的数组中分组对象的子数组 - Python
- swift - Swift 包管理器:追溯更新“包产品”的选择?
- mysql - 如何调用rest api将mysql数据库中的数据显示到html表中