Связь между длиной ввода и длиной зашифрованного текста в AES

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

Два вопроса:

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

И для бонусных очков: следует ли хранить шифрованный текст base64 в кодировке varchar или хранить его как необработанные байты и хранить их в varbinary? Существуют ли риски, связанные с хранением байтов в моей базе данных (я использую параметризованные запросы, поэтому теоретически случайное нарушение экранирования не должно быть проблемой)?

ТИА!

Дополнительно: Шифр, который я использую, это AES/Rijndael-256 - имеет ли это соотношение между доступными алгоритмами?

Ответы

Ответ 1

Отношение зависит от используемого режима заполнения и цепочек, а также от размера блока алгоритма (если это блок-шифр).

Некоторые алгоритмы шифрования - это потоковые шифры, которые шифруют данные "бит за битом" (или "byte by byte" ). Большинство из них генерируют зависящий от ключа поток псевдослучайных байтов, а шифрование выполняется посредством XORing этого потока с данными (дешифрование идентично). С помощью шифрования потока зашифрованная длина равна простой длине данных.

Другие алгоритмы шифрования - это блок-шифры. Блочный шифр, номинально, шифрует один блок данных фиксированной длины. AES - это блок-шифр с 128-битными блоками (16 байт). Обратите внимание, что AES-256 также использует 128-битные блоки; "256" - это длина ключа, а не длина блока. Режим цепочки связан с тем, как данные должны быть разделены на несколько таких блоков (это непросто сделать безопасно, но режим CBC в порядке). В зависимости от режима цепочки данные могут потребовать некоторого заполнения, то есть несколько дополнительных байтов, добавленных в конец, так что длина подходит для режима цепочки. Прокладка должна быть такой, чтобы она могла быть недвусмысленно удаляется при расшифровке.

В режиме CBC входные данные должны иметь длину, кратную длине блока, поэтому принято добавлять дополнение PKCS # 5: если длина блока равна n, то добавляется не менее 1 байт, не более n, так что общий размер кратен n, а последние добавленные байты (возможно, все из них) имеют числовое значение k, где k - количество добавленных байтов. После дешифрования достаточно просмотреть последний расшифрованный байт для восстановления k и, следовательно, знать, сколько байтов заполнения должно быть в конечном счете удалено.

Следовательно, в режиме CBC и AES, предполагая заполнение PKCS # 5, если входные данные имеют длину d, тогда зашифрованная длина (d + 16) & ~15. Здесь я использую C-образную нотацию; в простых словах длина между d + 1 и d + 16 и кратная 16.

Существует режим CTR (как "счетчик" ), в котором блок-шифр шифрует последовательные значения счетчика, давая поток псевдослучайных байтов. Это фактически превращает блок-шифр в потоковый шифр, и, таким образом, сообщение длины d зашифровывается в d байтов.

Предупреждение: обо всех системах шифрования (включая потоковые шифры) и режимах требуется дополнительное значение, называемое IV (начальное значение). Каждое сообщение должно иметь свой IV, и никакие два сообщения, зашифрованные одним и тем же ключом, не должны использовать один и тот же IV. В некоторых режимах есть дополнительные требования; в частности, как для CBC, так и для CTR, IV выбирается случайным образом и равномерно с криптографически сильным генератором псевдослучайных чисел. IV не является секретом, но должен быть известен decrypter. Поскольку каждое сообщение получает свой собственный IV, часто необходимо кодировать IV вместе с зашифрованным сообщением. С CBC или CTR IV имеет длину n, поэтому для AES это дополнительные 16 байт. Я не знаю, что делает mcrypt с IV, но, криптографически говоря, IV должен управляться в какой-то момент.

Что касается Base64, это полезно для передачи двоичных данных через текстовые носители, но это не обязательно для надлежащей базы данных. Кроме того, Base64 увеличивает данные примерно на 33%, поэтому его нельзя применять вслепую. Я думаю, вам лучше избегать Base64 здесь.

Ответ 2

Из моего понимания, в блочных режимах (cbc, ecb) длина вывода будет округлена до размера блока, как возвращается mcrypt_enc_get_block_size. Кроме того, вам нужно хранить IV вместе с данными, поэтому размер будет округленным strlen (data) + mcrypt_enc_get_iv_size().

Что касается кодировки base64, я бы не стал беспокоиться (но обязательно используйте шестнадцатеричное кодирование при сбрасывании db).

Ответ 3

Для блочного шифрования AES CBC с дополнением PKCS # 5,

#define BLOCKSIZE 16

size_t CipherTextLen = (PlainTxtLen / BLOCKSIZE + 1) * BLOCKSIZE;

Это не учитывает вектор инициализации