Cipher.doFinal выходной размер - PullRequest
       60

Cipher.doFinal выходной размер

3 голосов
/ 13 августа 2010

Я делаю расшифровку AES CBC в Java, используя javax.crypto. Я использую следующие методы класса Cipher:

  • public final void init (int opmode, Key key, AlgorithmParameters params) метод инициализации,
  • final int update(byte[] input, int inputOffset, int inputLen, byte[] output) метод расшифровки данных,
  • и, наконец, я вызываю метод final int doFinal(byte[] output, int outputOffset), чтобы завершить расшифровку.

Мой запрос таков: могу ли я предположить, что размер данных, возвращаемых мне вызовом doFinal, всегда будет меньше или равен размеру блока AES? Документация описывает метод doFinal как:

«Завершает преобразование из нескольких частей (шифрование или дешифрование). Процессы любые байты, которые могли быть буферизованы в предыдущих обновлениях звонков. Финал преобразованные байты хранятся в выходной буфер. ”

Но нигде не говорится, что выходной буфер будет содержать не более одного блока данных. Хотя я понимаю, что это общее поведение API-интерфейсов AES, и это поведение, которое мой код демонстрировал до сих пор, но будет ли это предположение всегда верно?

Ответы [ 2 ]

3 голосов
/ 13 августа 2010

В общем (как, например, в контексте класса Cipher), я не верю, что было бы безопасно предположить это. Согласно javadocs для этого doFinal метода:

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

Так что, если вы размещаете выходной буфер "около" точки, где вы вызываете метод doFinal, то имеет смысл вызвать getOutputSize и выделить буфер соответствующего размера. Работа выполнена.

С другой стороны, если вы передаете буфер из «далека», который был создан именно для размера блока, у вас могут возникнуть дополнительные проблемы. Было бы совершенно законно (по крайней мере, в соответствии с открытым интерфейсом класса Java) для реализации Cipher возвращать вывод, превышающий размер блока, при условии, что метод getOutputSize возвращает соответствующий размер.

На самом деле, если вы выполняете расшифровку CBC, не требует ли это, чтобы вы передавали все блоков в метод update? В этом случае вы должны получить полный вывод открытого текста из doFinal, а не только из одного блока?

0 голосов
/ 13 августа 2010

Вообще говоря, небезопасно предполагать, что буферизация предназначена только для одного блока; и когда вы посмотрите на детали, вы можете увидеть, что это зависит от типа заполнения. При обычном заполнении "PKCS # 5" добавляется как минимум один байт и максимум n байтов (для блоков размером n ), поэтому система дешифрования может ограничиться n байт буферизации. Некоторые другие типы отступов немного сложнее, например, CTS требует 2n байтов буферизации. Похоже, что криптографический уровень Java не поддерживает CTS, но это может быть добавлено в будущей версии.

Cipher.getOutputSize(len) даст вам максимальный размер вывода, учитывая len дополнительные входные байты. Возвращаемое значение может быть несколько больше, чем будет возвращено, особенно при расшифровке, поскольку оно зависит от того, какие байты заполнения будут фактически найдены при расшифровке.

Можно с уверенностью предположить, что общая длина дешифрованного сообщения не превышает общую длину зашифрованного сообщения (симметричное шифрование не включает сжатие данных). Таким образом, вы можете поддерживать два счетчика, один для байтов входных данных (зашифрованные блоки) и один для полученных байтов выходных данных; разница будет максимальной оценкой того, что можно получить из doFinal(). Но это то, что getOutputSize() делает в любом случае.

...