问题描述
手机更换指纹时后,之前配合使用的密钥Cipher失效,爆出
代码语言:javascript复制 Key permanently invalidated (该密钥已被永久无效)错误
然后返回给BiometricPrompt 使用时报错:
代码语言:javascript复制 Caused by: java.lang.IllegalStateException: Crypto primitive not initialized
解决办法
对已经报错的密钥,进行删除操作:
代码语言:javascript复制 _keystore.deleteEntry(KEY_NAME);
而后重新获取新的密钥
代码语言:javascript复制 /**
* 获取key
*/
Key GetKey() throws Exception {
Key secretKey;
if (!_keystore.isKeyEntry(KEY_NAME)) {
return CreateKey();
}
secretKey = _keystore.getKey(KEY_NAME, null);
return secretKey;
}
/**
* 创建key
*/
@RequiresApi(api = Build.VERSION_CODES.M)
Key CreateKey() throws Exception {
Log.e(TAG, "CreateKey ");
KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHM, KEYSTORE_NAME);
KeyGenParameterSpec keyGenSpec =
new KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(BLOCK_MODE)
.setEncryptionPaddings(ENCRYPTION_PADDING)
.setUserAuthenticationRequired(true)
.build();
keyGen.init(keyGenSpec);
SecretKey secretKey = keyGen.generateKey();
return secretKey;
}
并进行初始化(关键)
代码语言:javascript复制Cipher createCipher(boolean retry, int operMode, byte[] iv) throws Exception {
Key key = GetKey();
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
try {
if (operMode == Cipher.ENCRYPT_MODE) {
cipher.init(Cipher.ENCRYPT_MODE, key);
} else if (operMode == Cipher.DECRYPT_MODE) {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
}
} catch (KeyPermanentlyInvalidatedException e) {
// 该密钥已被永久无效 Key permanently invalidated
Log.e(TAG, "createCipher: " e.getMessage() );
_keystore.deleteEntry(KEY_NAME);
if (retry) {
return createCipher(false, operMode, iv);
} else {
throw new Exception("Could not create the cipher for fingerprint authentication.", e);
}
}
return cipher;
}
并且非常要注意的一点是, 当返回的时候, 重复执行的createCipher方法 递归, 递归返回时的结果值,第一次运行返回的是第一次执行的, 如果在retry 之后没有进行return createCipher 那么即使执行了第二次,返回的依旧是第一次的值!