Недавно я начал использовать криптографию в своем приложении, и я нахожу себя озадаченным связью между длиной входного текста и зашифрованным текстом, в котором он приводит. Перед применением криптования было легко определить размер столбца базы данных. Теперь, однако, размер столбца немного меняется.
Два вопроса:
И для бонусных очков: должен ли я хранить шифрованный текст base64-кодированный в varchar или хранить его как необработанные байты и хранить их в varbinary? Существуют ли риски, связанные с хранением байтов в моей базе данных (я использую параметризованные запросы, поэтому теоретически случайное нарушение выхода не должно быть проблемой)?
ТИА!
Дополнительно: Шифр, который я использую, это AES / Rijndael-256. Разница между этими алгоритмами варьируется?
Отношение зависит от используемого режима заполнения и цепочек , а также от размера блока алгоритма (если это блок-шифр).
Некоторые алгоритмы шифрования – это потоковые шифры, которые шифруют данные «бит за битом» (или «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 здесь.
По моему мнению, в выходной части блока (cbc, ecb) длина вывода будет округлена до размера блока, как указано mcrypt_enc_get_block_size. Кроме того, вам нужно хранить IV вместе с данными, поэтому размер будет округленным strlen (data) + mcrypt_enc_get_iv_size ().
Что касается кодировки base64, я бы не стал беспокоиться (но обязательно используйте шестнадцатеричное кодирование при сбросе вашего db).
Для блочного шифрования AES CBC с дополнением PKCS # 5,
#define BLOCKSIZE 16 size_t CipherTextLen = (PlainTxtLen / BLOCKSIZE + 1) * BLOCKSIZE;
Это не учитывает вектор инициализации