Android X库 BiometricPrompt 中 Crypto primitive not initialized 问题研究

2023-05-10 19:21:11 浏览数 (1)

问题描述

手机更换指纹时后,之前配合使用的密钥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 那么即使执行了第二次,返回的依旧是第一次的值!

0 人点赞