Java 尝试解密指纹API密码时出现BadPaddingException

Java 尝试解密指纹API密码时出现BadPaddingException,java,android,encryption,fingerprint,Java,Android,Encryption,Fingerprint,在我的应用程序中,当用户在初始设置[指纹注册]中扫描手指时,我会保存用户访问代码的加密版本。当用户稍后尝试解锁应用程序时,我将尝试使用指纹API[指纹验证]解密此访问代码 但是,Cipher.doFinal在解密时抛出以下异常: javax.crypto.BadPaddingException at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.

在我的应用程序中,当用户在初始设置[指纹注册]中扫描手指时,我会保存用户访问代码的加密版本。当用户稍后尝试解锁应用程序时,我将尝试使用指纹API[指纹验证]解密此访问代码

但是,
Cipher.doFinal
在解密时抛出以下异常:

javax.crypto.BadPaddingException
 at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:482)
 at javax.crypto.Cipher.doFinal(Cipher.java:1502)
 (...)

Caused by: android.security.KeyStoreException: Invalid argument
         at android.security.KeyStore.getKeyStoreException(KeyStore.java:940)
         at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
         at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:473)
        ... 12 more
指纹扫描仪显示在
对话框fragment
中。无论是注册还是验证指纹,以下函数始终按顺序从构造函数调用

初始化密钥库:

private void initializeKeystore() {

    try {
        mKeyStore = KeyStore.getInstance(KEY_STORE_NAME); //AndroidKeyStore
    } catch (KeyStoreException e) {
        mKeyStore = null;
    }

    try {
        mKeyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEY_STORE_NAME);
    } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
        mKeyGenerator = null;
    }
}
创建密钥:

private void createKey() {
    if (mKeyGenerator != null) {
        try {
            mKeyStore.load(null);

            KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(KEY_NAME,
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                    .setUserAuthenticationRequired(true)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);

            mKeyGenerator.init(builder.build());
            mKeyGenerator.generateKey();
        } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException |
                CertificateException | IOException e) {
            mKeyGenerator = null;
        }
    }
}
创建密码对象:

private void createCipher() {
    try {
        mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                + KeyProperties.BLOCK_MODE_CBC + "/"
                + KeyProperties.ENCRYPTION_PADDING_PKCS7);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        mCipher = null;
    }
}
当指纹扫描仪API成功验证用户身份时,将依次调用以下代码:

@Nullable Cipher getCipher(@NonNull final FingerprintStore ivStore) {
    if (mKeyStore != null && mKeyGenerator != null && mCipher != null) {
        try {
            mKeyStore.load(null);
            SecretKey key = (SecretKey)mKeyStore.getKey(KEY_NAME, null);

            switch (mEncryptionMode) {
                case MODE_ENCRYPT:
                    mCipher.init(Cipher.ENCRYPT_MODE, key);
                    ivStore.writeIv(mCipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV());
                    break;
                case MODE_DECRYPT:
                    byte[] iv = ivStore.readIv();
                    mCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
                    break;
            }
            return mCipher;
        } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
                | NoSuchAlgorithmException | InvalidKeyException | InvalidAlgorithmParameterException
                | InvalidParameterSpecException | NullPointerException e) {
            return null;
        }
    }

    return null;
}
并且,使用刚刚从上一次调用返回的Cipher实例:

@Nullable byte[] encryptOrDecrypt(@NonNull Cipher cipher, @NonNull byte[] subject) {
    try {
        return cipher.doFinal(subject);
    } catch (BadPaddingException | IllegalBlockSizeException e) {
        e.printStackTrace();
        return null;
    }
}

doFinal
的调用在加密数据时工作正常,但在解密时抛出异常。我检查了初始化向量和加密数据的
字节[]
,发现它们被存储到磁盘(Base64)并正确读回内存。

没关系,显然我忽略了一个事实,即
SecretKey
只应在注册阶段生成。因为在尝试解密数据时调用了
createKey
,所以在调用
doFinal
之前,它被新生成的密钥覆盖。代码现在运行得很好。

Ragavendra M,我想添加详细信息以获得帮助。 您需要使用下一个代码来解决此问题:

val keyStore = KeyStore.getInstance(...)
 ...
if (!keyStore.containsAlias(KEY_NAME)) {
  generateKey()
}

你能详细说明一下吗?我面临着这个问题。