2009-08-04 4 views
8

Я реализую шифрование/дешифрование с использованием Java Cipher и AES. Все работает хорошо, за исключением того, что на вызов doFinal() добавлено 5 дополнительных байтов. Итак, я заканчиваю правильно декодированной строкой с добавлением 5 дополнительных байтов.Java cipher.doFinal() написать дополнительные байты

Я считаю, что причина в том, что весь блок из 16-байтов записывается. Я вижу 3 16-байтных блока, в том числе и последний. Зашифрованный файл ввода - 64 байта. Незашифрованный текст должен быть 43 байта.

Документация для doFinal указывает, что она может вернуть количество байтов, записанных в выходной буфер. Однако это 0,16,16,16. Я пробовал каждую форму doFinal и обновлял и не изменял поведение.

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

Должен ли я использовать другой алгоритм? AES256 - это требование, но мне интересно, может ли другой тип блока или тип заполнения позволить ему записать правильное количество байтов.

Любые указания?

пропущено (некоторых) краткостью:

decryptCipher = Cipher.getInstance("AES"); 
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey); 

Деловая часть подпрограммы дешифрования.

long bytesToRead = inputFile.length(); 

    while ((inLen = in.read(buffer)) > 0) { 
     int bytesOut = 0; 
     byte[] cryptBytes = null; 
     int outLen = cipher.getOutputSize(inLen); 
     cryptBytes = new byte[outLen]; 

     if (bytesToRead <= buffer.length) { 
      try { 
       bytesOut = cipher.doFinal(buffer, 0, inLen, cryptBytes, 0); 
      } catch (ShortBufferException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } else 
      try { 
       bytesOut = cipher.update(buffer, 0, inLen, cryptBytes, 0); 
      } catch (ShortBufferException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     out.write(cryptBytes, 0, bytesOut); 
     bytesToRead -= inLen; 

    } 
    try { 
     out.flush(); 
     in.close(); 
     out.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

ответ

14

Вы должны указать механизм заполнения при вызове Cipher.getInstance() - очевидно, что он должен быть одинаковым как при шифровании, так и в режиме дешифрования. например:

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

Без механизма заполнения, сторона дешифрования не имеет никакой информации о том, где конец открытого текста является (в последнем блоке).

+0

Удивительно, спасибо большое. Это решило. У меня создалось впечатление, что если вы указали только AES, у вас есть режим блока ECB и PCKS5Padding по умолчанию. Угадайте, что это неправильно. – wadesworld

+1

То же самое касается всех двигателей AES, в том числе не на Java. – Cheeso

1

AES является блочным шифром, естественно, это будет давать вам целые блоки, как будет все блочные шифры.

Для получения дополнительной информации см. Wikipedia article on AES.

Вы сказали, что хотите получить «правильное количество байтов». Как вы определили, каково правильное количество байтов?

+1

Думаю, он знает, что AES делает это, вопрос в том, как использовать Java API. – skaffman

+0

Чтобы узнать правильный размер незашифрованного изображения после дешифрования, он должен записать исходный размер потока. –

Смежные вопросы