BadPaddingException: блок pad поврежден - PullRequest
7 голосов
/ 15 мая 2009

Я пытаюсь расшифровать файл на Java, который был зашифрован в C # с помощью Rijndael / CBC / PKCS7. Я продолжаю получать следующее исключение:

javax.crypto.BadPaddingException: поврежден блок пэдов
в org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal (Неизвестный источник)
на javax.crypto.Cipher.doFinal (DashoA13 * ..)
в AESFileDecrypter.decrypt (AESFileDecrypter.java:57)

, когда веб-сервер вызывает метод doFinal(inpbytes) для первого байта []. Я предполагаю, что это проблема с ключом или IV. У меня есть зашифрованные файлы в моей файловой системе для тестирования. Есть ли что-нибудь, что кто-то может увидеть явно неправильно с моим кодом ниже?

*** keyStr в кодировке base64

public AESFileDecrypter(String keyStr){
    try {
            Security.addProvider(new BouncyCastleProvider());   
            convertIvParameter();
            key = new sun.misc.BASE64Decoder().decodeBuffer(keyStr);

            //use the passed in Base64 decoded key to create a key object
            decryptKey = new SecretKeySpec(key, "AES");

            //specify the encryption algorithm
            decryptCipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");

            //make a parameter object for the initialization vector(IV)             
            IvParameterSpec ivs = new IvParameterSpec(_defaultIv);

            //initialize the decrypter to the correct mode, key used and IV
            decryptCipher.init(Cipher.DECRYPT_MODE, decryptKey, ivs);    
        } 
     catch (Exception e) {
             e.printStackTrace();
     } 
}

public void convertIvParameter() {

   int[] iv = new int[] {11, 190, 165, 33, 68, 88, 11, 200, 245, 35, 68, 23, 60, 24, 223, 67};

   _defaultIv = new byte[16];

   for(int x = 0; x < _defaultIv.length; x++) {
      _defaultIv[x] = (byte)iv[x];
   }
}

public void decryptUpdate(byte[] inpBytes) throws Exception {
   //decrypt the byte passed in from the web server
   decryptCipher.update(inpBytes);  
}

public byte[] decryptFinal() throws Exception {
   //decrypt the byte passed in from the web server
   return decryptCipher.doFinal();
}

//sends bytes to the client for diaply
private void sendBytes(FileInputStream fis, OutputStream os)throws Exception {
    //set the buffer size to send 4k segments of data
aesFileDecrypter = new AESFileDecrypter(<Insert Key string here>);

    byte[] buffer = new byte[4096];
    int bytes = 0, totalBytes = fis.available();

    //while there is still data to be sent keep looping and write the data
    //to the output stream as the buffer is filled
    try {
       while ((bytes = fis.read(buffer)) != -1) {   
          aesFileDecrypter.decryptUpdate(buffer);
          //os.write(buffer, 0, bytes);
       }

       os.write(aesFileDecrypter.decryptFinal(), 0, totalBytes);
   }
   catch(Exception e) {
      e.printStackTrace();
   }
}

Ответы [ 4 ]

6 голосов
/ 15 мая 2009

Во-первых, для ясности, из приведенных ниже комментариев не следует вызывать doFinal () для каждого блока, поскольку doFinal () ожидает какого-либо дополнения в конце, которого, очевидно, не будет в промежуточных блоках. Либо (a) вызовите update () для промежуточных данных, затем doFinal () в конце, либо (b) просто организуйте, чтобы все ваши данные были в одном буфере или байтовом массиве, и вызовите doFinal () один раз для всей партии работ.

Из кода, который вы выложили, не ясно, что именно это вы и делаете, но об этом следует упомянуть на всякий случай.

Если этого не сделать, то в качестве первого шага к отладке я бы предложил, какой из этих двух вариантов проще для вас:

  • Расшифровка в режиме ECB без заполнения и просмотр того, что вы получите. Посмотрите на первый блок данных, это возвращает. Если вы можете выполнить XOR с помощью своих байтов IV и получить ожидаемые расшифрованные данные, вы знаете, что ваш ключ в порядке.
  • Вывод фактических байтов ключа из C # до кодирования base 64 и Java после декодирования и проверки того, что они совпадают.

Насколько я помню, C # имеет неподписанные байты (тогда как Java подписан), поэтому есть несколько мест, где есть место для вещей, которые могут слегка не работать с байтовой подписью.

3 голосов
/ 26 июля 2011

Я сталкивался с этой проблемой раньше.

Когда я написал код для шифрования и дешифрования, например:

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sec, "AES"),new IvParameterSpec(new byte[cipher.getBlockSize()]));
    byte[] encode = cipher.doFinal(data);

    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sec, "AES"), new IvParameterSpec(new byte[cipher.getBlockSize()]));
    byte[] decode = cipher.doFinal(encode);

Я забыл первое IvParameterSpec(new byte[cipher.getBlockSize()]) при шифровании данных, затем я получил исключение «блок блок поврежден», поэтому, возможно, вам следует проверить код шифрования.

1 голос
/ 18 мая 2009

doFinal () был отменой кода выше, и я закончил тем, что использовал только шифрованные потоки вместо подхода update / doFinal. Таким образом, я мог бы использовать FileInputStream и мой шифр в качестве параметров для CipherInputStream, а затем передать вывод в веб-браузер через OutputStream. Разделение update и doFinal на их собственные вызовы методов значительно усложнило задачу, и оба метода были удалены из класса decrypter (оставив один цикл while, который считывает фрагменты данных и выводит их в браузер). Поставщик Bouncy Castle в этом случае также не требовался, и было достаточно PKCS5Padding, который был предоставлен SunJCE.

1 голос
/ 15 мая 2009

Насколько я знаю, AES основан на Rijndael, но спецификация не совсем такая же. Я бы посоветовал проверить ключ и размер блока, который вы используете для шифрования в C #, и размеры, используемые в Java. (. Net различия между Rijndael и AES ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...