Issue while using Android fingerprint: IV required when decrypting. Use IvParameterSpec or AlgorithmParameters to provide it

后端 未结 3 855
春和景丽
春和景丽 2021-02-04 04:38

I\'m following the ConfirmCredential Android example provided by Google, but it only shows how to encrypt the data. When I try to decrypt it I get exception:

ja         


        
相关标签:
3条回答
  • 2021-02-04 05:23

    I created an issue in the github project for the sample provided by google (link to the issue here). The response I got is that I must use the IV that was generated when the value was encrypted. (same as in the solution provided by @Qianqian)

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

    I created a sample application that shows how to do this. It is available on github, here.

    Hope this is useful to someone.

    0 讨论(0)
  • 2021-02-04 05:27

    Basically you have to pass the IvParameterSpec for the decrypt mode whereas you should not manually set it for encryption mode.

    So here is what I did and it worked well:

    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(....)
    }
    

    You can also encode the IV data with Base64 and save it under shared preferences instead of saving it under a file.

    In either case, If you have employed the new full backup feature for Android M, keep in mind that this data should NOT be allowed to backup/restore since it is invalid when a user reinstall the app or install the app on another device.

    0 讨论(0)
  • 2021-02-04 05:38

    How about this,

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

    If you use the sample code from Google repo, above line will work, also note, for every mChiper.init we need to authenticate with fingerprint once, that means two fingerprint auth is required, one for encryption and one for decryption.

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

    0 讨论(0)
提交回复
热议问题