#android #android-biometric-prompt #android-biometric
Вопрос:
Я успешно зашифровал данные, используя поток биометрического менеджера, как показано в Google, но при попытке расшифровать зашифрованные данные я продолжаю нажимать на предложение IllegalBlockSizeException. Мне нужна помощь, пожалуйста.
Это мой класс, который обрабатывает все шифрование отпечатков пальцев( которое хорошо работает), но расшифровка не работает, так как он продолжает попадать в предложение IllegalBlockSizeException
public class FingerPrintEncrypter { private static FingerPrintEncrypter fingerPrintEncrypter; private static final String ENCRYPTION_BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC; private static final String ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7; private static final String ENCRYPTION_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES; private static final String ANDROID_KEY_STORE = "AndroidKeyStore"; byte[] initVector; private FingerPrintEncrypter(){ } public static synchronized FingerPrintEncrypter getInstance(){ if(fingerPrintEncrypter == null){ fingerPrintEncrypter = new FingerPrintEncrypter(); } return fingerPrintEncrypter; } /* gets the Cipher obj in encryptionMode for encryption tasks. */ public Cipher getCipherForEncryption(String aliasKeyName){ try { Cipher cipher = getCipher(); SecretKey secretKey = getOrCreateSecreteKey(aliasKeyName); cipher.init(Cipher.ENCRYPT_MODE, secretKey); initVector = cipher.getIV(); return cipher; } catch (InvalidKeyException e) { e.printStackTrace(); } return null; } /* gets the Cipher obj in decryptionMode for decryption tasks. */ public Cipher getCipherForDecryption(String aliasKeyName){ try{ Cipher cipher = getCipher(); SecretKey secretKey = getOrCreateSecreteKey(aliasKeyName); IvParameterSpec decryptParamSpec = new IvParameterSpec(initVector); cipher.init(Cipher.DECRYPT_MODE, secretKey, decryptParamSpec); return cipher; }catch (InvalidKeyException e){ e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } return null; } private SecretKey getOrCreateSecreteKey(String aliasKeyName) { try { KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE); keyStore.load(null); SecretKey key = ((SecretKey)keyStore.getKey(aliasKeyName, null)); if(key == null){ // key previously create so just grab it generateSecretKey(aliasKeyName); } return key; } catch (KeyStoreException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (UnrecoverableKeyException e) { e.printStackTrace(); } return null; } private void generateSecretKey(String aliasKeyName){ try { // key not create create a new one KeyGenParameterSpec parameterSpec = new KeyGenParameterSpec.Builder(aliasKeyName, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(ENCRYPTION_BLOCK_MODE) .setEncryptionPaddings(ENCRYPTION_PADDING) .setUserAuthenticationRequired(true) .build(); KeyGenerator keyGenerator = KeyGenerator.getInstance(ENCRYPTION_ALGORITHM, ANDROID_KEY_STORE); keyGenerator.init(parameterSpec); keyGenerator.generateKey(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } } private Cipher getCipher() { try { return Cipher.getInstance(ENCRYPTION_ALGORITHM "/" ENCRYPTION_BLOCK_MODE "/" ENCRYPTION_PADDING); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } return null; } public String encryptData(String info, Cipher cipher){ try { byte[] encryptedData = cipher.doFinal(info.getBytes("UTF-8")); return Base64.encodeToString(encryptedData, Base64.NO_WRAP); } catch (BadPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } public String decryptData(String stringToDecrypt, Cipher cipher){ try { return new String(cipher.doFinal(Base64.decode(stringToDecrypt, Base64.NO_WRAP))); } catch (BadPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } return null; } }
Комментарии:
1. Одна вещь, которую я задаюсь вопросом, так как я каждый раз генерирую новый IV, всегда ли инициатор IV, который вы получаете от шифра, остается неизменным или он каждый раз генерирует новые инициаторы? В этом случае было бы трудно получить правильный IV для вашего дешифрующего шифра. Тем не менее, если мне не изменяет память (я также потратил много времени на поиск подобных проблем), похоже, у вас могут возникнуть проблемы с заполнением
2. Я помню, что большой проблемой для меня был неправильный размер бита в IV, но если cipher.getIV() работает так, как вы его используете, то я полагаю, что класс шифра должен дать вам рабочий
3. ну, это тоже предполагается, но, честно говоря, я не знаю, почему я продолжаю получать эту ошибку, и официальный документ Google тоже не помогает показать, как работает процесс расшифровки.
4. Но теперь, если вы шифруете значение, вы назначаете свой байт[] initVector. Затем, если вы сохраните то, что зашифровали, перезагрузите приложение и попытаетесь расшифровать данные, не попытается ли оно расшифровать их с помощью нулевого байта[] initVector, если вы ничего не шифровали раньше (для настройки initVector)?
5. Проблема заключалась в том, что байт[] initVector, переданный в IVParameterSpec, должен был быть вызван, как я предполагал, из cipher.getIV (), если только шифр выполнял шифрование, а не раньше.