Ошибка дешифрования: поврежден блок блокировки

У меня есть следующий код.

byte[] input = etInput.getText().toString().getBytes(); byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); // encryption pass cipher.init(Cipher.ENCRYPT_MODE, key); byte[] cipherText = new byte[cipher.getOutputSize(input.length)]; int ctLength = cipher.update(input, 0, input.length, cipherText, 0); ctLength += cipher.doFinal(cipherText, ctLength); cipher.init(Cipher.DECRYPT_MODE, key); byte[] plainText = new byte[cipher.getOutputSize(ctLength)]; int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0); String strLength = new String(cipherText,"US-ASCII"); byte[] byteCiphterText = strLength.getBytes("US-ASCII"); Log.e("Decrypt", Integer.toString(byteCiphterText.length)); etOutput.setText(new String(cipherText,"US-ASCII")); cipherText = etOutput.getText().toString().getBytes("US-ASCII"); Log.e("Decrypt", Integer.toString(cipherText.length)); ptLength += cipher.doFinal(plainText, ptLength); Log.e("Decrypt", new String(plainText)); Log.e("Decrypt", Integer.toString(ptLength)); 

Он отлично работает. Но как только я преобразую его в класс. Он всегда попадает в ошибку в этой строке.

  ptLength += cipher.doFinal(plainText, ptLength); Error:Pad block corrupted 

Я проверил и оба кода точно такие же. Даже значение, переданное в строке преобразования в байтовое число, ничем не отличается от приведенного выше кода. Любая идея, что не так с кодом?

 public String Encrypt(String strPlainText) throws Exception, NoSuchProviderException, NoSuchPaddingException { byte[] input = strPlainText.getBytes(); byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); // encryption pass cipher.init(Cipher.ENCRYPT_MODE, key); byte[] cipherText = new byte[cipher.getOutputSize(input.length)]; int ctLength = cipher.update(input, 0, input.length, cipherText, 0); ctLength += cipher.doFinal(cipherText, ctLength); return new String(cipherText, "US-ASCII"); } public String Decrypt(String strCipherText) throws Exception, NoSuchProviderException, NoSuchPaddingException { byte[] cipherText = strCipherText.getBytes("US-ASCII"); int ctLength = cipherText.length; byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }; SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); // decryption pass cipher.init(Cipher.DECRYPT_MODE, key); byte[] plainText = new byte[cipher.getOutputSize(ctLength)]; int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0); ptLength += cipher.doFinal(plainText, ptLength); return new String(plainText); } 

Как сказал Янн Рамин, использование String является ошибкой для шифрования в / выходе. Это двоичные данные, которые

  • Может содержать 0x00
  • Может содержать значения, которые не определены или не сопоставлены с незнакомыми местами в используемой кодировке

Используйте простой байт [], как в первом примере, или используйте шестнадцатеричное кодирование или base64, кодирующее байты [].

 // this is a quick example - dont use sun.misc inproduction // - go for some open source implementation String encryptedString = new sun.misc.BASE64Encoder.encodeBuffer(encryptedBytes); 

Эта строка может быть безопасно перенесена и отображена обратно в байты.

РЕДАКТИРОВАТЬ

Возможно, самый безопасный способ решения проблемы длины – всегда использовать поточную реализацию (IMHO):

пример

 static public byte[] decrypt(Cipher cipher, SecretKey key, byte[]... bytes) throws GeneralSecurityException, IOException { cipher.init(Cipher.DECRYPT_MODE, key); ByteArrayOutputStream bos = new ByteArrayOutputStream(); for (int i = 0; i < bytes.length; i++) { bos.write(cipher.update(bytes[i])); } bos.write(cipher.doFinal()); return bos.toByteArray(); } 

Вы указали PKCS7 Padding. Сохраняется ли ваше дополнение при сохранении в вашем объекте String? Является ли ваш строковый объект совпадением 1: 1 с байтами, выводимыми шифром? В общем случае String не подходит для передачи двоичных данных, таких как вывод шифрования.

В вашем случае шифр использует прописку, это означает, что, другими словами, входные данные будут дополнены / округлены до блоков с определенным предопределенным размером (который зависит от алгоритма заполнения). Допустим, вы поставили 500 байтов для шифрования, размер блока дополнений – 16 байт, поэтому зашифрованные данные будут иметь размер 512 байт (32 блока) – 12 байтов будут дополнены.

В вашем коде вы ожидаете зашифрованный массив того же размера, что и входной массив, что вызывает исключение. Вам нужно пересчитать размер выходного массива, сохраняя при этом прописку.

Intereting Posts
ListView устанавливает первую видимую позицию Как вы играете в Android InputStream на MediaPlayer? Как добавить значок для прокручиваемых вкладок Запуск процесса загрузки в фоновом режиме, даже когда телефон спит Как предотвратить создание Eclipse объекта fragment_main.xml Android setRepeating () и setInexactRepeating () не срабатывают Как разместить AdMob в верхней части экрана (вверху) в панели действий Android? Intel INDE – захват видео для Unity 3D (как захватить только видео и аудио приложения вместо использования микрофона) Android WebView не загружает кешированный веб-сайт, если нет соединения Макет не отображает контент при загрузке через новую активность в Xamarin DataChannel.state () всегда возвращает CONNECTING webRTC Android Собирает ли шейдер во время рендеринга хорошую / действительную практику в OpenGL ES? Идеи для мультиплатформенной зашифрованной мобильной системы хранения Java Странное поведение с медиапланером и seekTo Как слушать любую клавиатуру на всем приложении?