Расшифровка строки Java AES «заданный последний блок заполнен неправильно»

1

Для всех ненавистников я ПРОЧИТАЛ МНОГО таких тем, как этот, и не из них было полезно.

например. здесь javax.crypto.BadPaddingException: данный окончательный блок неправильно исправлен ошибкой при расшифровке или здесь. Этот конечный блок неправильно заполнен

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

Мои занятия:

package aes;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JOptionPane;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class EncryptionExample {

private static SecretKeySpec    key;
private static IvParameterSpec  ivSpec;
private static Cipher           cipher; 
private static byte[]           keyBytes;
private static byte[]           ivBytes;
private static int              enc_len;

public static void generateKey() throws Exception
        {

            String complex = new String ("9#82jdkeo!2DcASg");
            keyBytes = complex.getBytes();
            key = new SecretKeySpec(keyBytes, "AES");

            complex = new String("@o9kjbhylK8(kJh7"); //just some randoms, for now
            ivBytes = complex.getBytes();
            ivSpec = new IvParameterSpec(ivBytes);

            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        }

        public static String encrypt(String packet) throws Exception
        {
            byte[] packet2 = packet.getBytes();
            cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
            byte[] encrypted = new byte[cipher.getOutputSize(packet2.length)];
            enc_len = cipher.update(packet2, 0, packet2.length, encrypted, 0);
            enc_len += cipher.doFinal(encrypted, enc_len);

            return packet = new String(encrypted);
        }

        public static String decrypt(String packet) throws Exception
        {
            byte[] packet2 = packet.getBytes();
            cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
            byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
            int dec_len = cipher.update(packet2, 0, enc_len, decrypted, 0);
HERE EXCEPTION>>>>> dec_len += cipher.doFinal(decrypted, dec_len);  <<<<<<<<<

            return packet = new String(decrypted);
        }


        // and display the results
    public static void main (String[] args) throws Exception 
    {

          // get the text to encrypt
        generateKey();
        String inputText = JOptionPane.showInputDialog("Input your message: ");

        String encrypted = encrypt(inputText);
        String decrypted = decrypt(encrypted);            

        JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
                    "Encrypted:  " + new String(encrypted) + "\n"
                      +  "Decrypted: : " + new String(decrypted));
          .exit(0);
    }
}

Дело в том, что когда я дешифрую строки (около 4/10 снимков), я получаю это исключение:

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:479)
at javax.crypto.Cipher.doFinal(Cipher.java:2068)
at aes.EncryptionExample.deszyfrujBez(EncryptionExample.java:HERE tag)
at aes.EncryptionExample.main(EncryptionExample.java:Main starting)

Кто-нибудь знает, что здесь изменить (ключ? *.DoFinal() метод?), Чтобы заставить его работать?

@для тех, кто любопытен - методы должны быть статичными, так как это часть чего-то большего;)

  • 0
    Вы можете проверить здесь stackoverflow.com/questions/20297621/… или stackoverflow.com/questions/8049872/…
  • 0
    прочитайте две ссылки перед этим. ни у одного из них нет решения для этого, так почему -1? Я написал, что ЧИТАЮ МНОГО ТЕМ, КАК ЭТО
Показать ещё 1 комментарий
Теги:
encryption
aes
badpaddingexception

2 ответа

4

Когда вы используете byte[] packet2 = packet.getBytes() вы преобразовываете строку на основе кодировки по умолчанию, которая может быть, например, UTF-8. Это здорово. Но затем вы преобразуете зашифрованный текст обратно в строку следующим образом: return packet = new String(encrypted) и это может вызвать у вас проблемы, если это не будет округлять до одного и того же массива байтов позже в decrypt() с другим byte[] packet2 = packet.getBytes().

Попробуйте это вместо: return packet = new String(encrypted, "ISO-8859-1") и byte[] packet2 = packet.getBytes("ISO-8859-1") - это не то, что я бы предпочел, но это должен объединить байтовые массивы.

0

Результатом шифрования являются двоичные данные. В большинстве случаев его нельзя интерпретировать как допустимую строчную кодировку. Таким образом, вызов new String(encrypted) скорее всего исказит зашифрованные байты, а после выполнения packet.getBytes() вы получите массив байтов с различным контентом.

Теперь дешифрование завершилось неудачно, потому что текст cypher был изменен. Байты заполнения неправильно восстанавливаются и не могут быть удалены.

Чтобы исправить это, не конвертируйте текст cypher в строку, сохраните массив байтов.

  • 0
    Я не могу сохранить байтовый массив, то есть весь смысл; (а также строка хранит заполненные байты. Когда я хочу напечатать его, он напечатает что-то вроде "print_text _ [] [] [] [] [] [] [ ] "где [] - байт заполнения (просто квадрат в консоли)
  • 0
    Если вам нужно преобразовать байтовый массив в строку, используйте кодировку, которая может восстановить двоичное содержимое, например base64.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню