使用Android指纹时发出:解密时需要IV。 使用IvParameterSpec或AlgorithmParameters来提供它

我遵循Google提供的ConfirmCredential Android示例,但仅显示如何encryption数据。 当我尝试解密它时,我得到exception:

java.security.InvalidKeyException: IV required when decrypting. Use IvParameterSpec or AlgorithmParameters to provide it. 

我使用下面的代码:

 String transforation = KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7; KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); SecretKey secretKey = (SecretKey) keyStore.getKey(KEY_NAME, null); // encrypt Cipher cipher = Cipher.getInstance(transforation); cipher.init(Cipher.ENCRYPT_MODE, secretKey); String encriptedPassword = cipher.doFinal("Some Password".getBytes("UTF-8")); // decrypt cipher = Cipher.getInstance(transforation); cipher.init(Cipher.DECRYPT_MODE, secretKey); String password = new String(cipher.doFinal(encriptedPassword), "UTF-8")); 

例外情况如下:

 cipher.init(Cipher.DECRYPT_MODE, secretKey); 

任何想法在这种情况下解密的正确方法是什么?

Solutions Collecting From Web of "使用Android指纹时发出:解密时需要IV。 使用IvParameterSpec或AlgorithmParameters来提供它"

基本上你必须通过IvParameterSpec解密模式,而你不应该手动设置为encryption模式。

所以这就是我所做的,它运作良好:

 private initCipher(int mode) { try { byte[] iv; mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7); IvParameterSpec ivParams; if(mode == Cipher.ENCRYPT_MODE) { mCipher.init(mode, generateKey()); ivParams = mCipher.getParameters().getParameterSpec(IvParameterSpec.class); iv = ivParams.getIV(); fos = getContext().openFileOutput(IV_FILE, Context.MODE_PRIVATE); fos.write(iv); fos.close(); } else { key = (SecretKey)keyStore.getKey(KEY_NAME, null); File file = new File(getContext().getFilesDir()+"/"+IV_FILE); int fileSize = (int)file.length(); iv = new byte[fileSize]; FileInputStream fis = getContext().openFileInput(IV_FILE); fis.read(iv, 0, fileSize); fis.close(); ivParams = new IvParameterSpec(iv); mCipher.init(mode, key, ivParams); } mCryptoObject = new FingerprintManager.CryptoObject(mCipher); } catch(....) } 

您也可以使用Base64对IV数据进行编码,并将其保存在共享首选项中,而不是将其保存在文件下。

无论是哪种情况,如果您已经使用了Android M的全新备份function,请记住, 应该允许这些数据进行备份/恢复,因为当用户重新安装应用程序或在其他设备上安装应用程序时,该数据无效。

我在github项目中为google提供的示例创build了一个问题(链接到这里的问题)。 我得到的答复是,我必须使用值被encryption时生成的IV。 (和@钱前提供的解决scheme一样)

 cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(encryptCipher.getIV())); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); 

我创build了一个示例应用程序,显示如何执行此操作。 它在github上可用, 在这里 。

希望这对某人有用。

这个怎么样,

mCipher.init(Cipher.DECRYPT_MODE, key, mCipher.getParameters());

如果您使用Google repo的示例代码,上面的代码行也可以工作,同样需要注意的是,对于每个mChiper.init,我们需要使用一次指纹进行身份validation,这意味着需要两个指纹authentication,一个用于encryption,一个用于解密。

https://github.com/googlesamples/android-FingerprintDialog