Android X庫 BiometricPrompt 中 Crypto primitive not initialized 問題研究

問題描述

手機更換指紋時後,之前配合使用的密鑰Cipher失效,爆出

		Key permanently invalidated  (該密鑰已被永久無效)錯誤

然後返回給BiometricPrompt 使用時報錯:

	Caused by: java.lang.IllegalStateException: Crypto primitive not initialized

解決辦法

對已經報錯的密鑰,進行刪除操作:

 _keystore.deleteEntry(KEY_NAME);

而後重新獲取新的密鑰

   /**
     * 獲取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;
    }

並進行初始化(關鍵)

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 那麼即使執行了第二次,返回的依舊是第一次的值!

有問題可隨時聯繫QQ, 7641436

需要Android 最新X庫 指紋識別(同時兼容api23&api28)並配合AndroidKetStore密鑰存儲的可以私聊我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章