Подтвердить что ты не робот

Как выбрать подходящий IV (вектор инициализации) для AES/CTR/NoPadding?

Я хотел бы зашифровать файлы cookie, написанные webapp, и я хотел бы сохранить размер файлов cookie до минимума, поэтому причина, по которой я выбрал AES/CTR/NoPadding.

Что бы вы порекомендовали использовать в качестве IV достаточно случайным образом и по-прежнему держать приложение безстоящим. Я знаю, что могу просто создать случайный IV и добавить его в сообщение, но это увеличит размер файла cookie.

Кроме того, какой рекомендуемый размер IV для 128-битного AES?

Как все это делают? Существуют ли какие-либо "проверенные и истинные" способы? Я не хочу изобретать велосипед.

4b9b3361

Ответ 1

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

Легкий способ сделать это - использовать криптографически безопасный генератор случайных чисел и создать новый 16-байтовый случайный IV для каждого сообщения. Я подчеркиваю "криптографически безопасную", потому что это важно; базового генератора случайных чисел недостаточно. С помощью Java используйте java.util.SecureRandom. С помощью Win32 вызовите CryptGenRandom(). При случайном выборе пространство возможного 128-битного IV достаточно велико, что столкновения крайне маловероятны. На самом деле, почему AES использует 128-битные блоки (таким образом, подразумевая 128-бит IV).

Сущность, которая расшифровывает сообщение, должна знать IV, поэтому вам необходимо сохранить его вместе с зашифрованным сообщением. Это дополнительные 16 байт. Я понимаю, что это накладные расходы - это то, чего вы хотите избежать, хотя 16 байтов не так много для файла cookie. Эффективная максимальная длина файла cookie зависит от веб-браузера, но 4000 символов работают повсюду. 16-байтовый IV, когда он закодирован в символах (например, Base64), будет использовать около 22 символов, т.е. Значительно меньше 1% от вашего максимального размера файла cookie: возможно, вы можете себе это позволить?

Теперь мы можем получить фанки и попытаться уменьшить длину IV через обман:

  • Генерировать IV с хэш-функцией: на стороне сервера, использовать счетчик, который начинается с 0 и увеличивается каждый раз, когда требуется новый IV. Чтобы получить IV, вы используете хэш-счетчик с подходящей хеш-функцией, например. SHA-256, и вы сохраняете первые 16 байтов хэш-значения. "Свойства рандомизации" хэш-функции будут достаточными, чтобы сделать IV достаточно случайным в отношении требований CTR. Для этого требуется криптографически безопасная хеш-функция, поэтому SHA-256 (избегайте MD5). Затем вам нужно сохранить значение счетчика в файле cookie, а счетчик будет короче 16 байт (например, если у вас не более 4 миллиардов клиентов, счетчик будет соответствовать 4 байтам). Однако есть скрытые затраты: сервер (я полагаю, сервер выполняет шифрование в вашей системе) должен убедиться, что он никогда не использует значение счетчика, поэтому он должен хранить "текущий счетчик" где-то таким образом, который сохраняется сервер перезагружается, а также не прерывается, если вы масштабируете до нескольких фронтов. Кажется, что не так легко.

  • Использовать внешнее уникальное значение:, возможно, файл cookie может быть частью контекста, который предоставляет достаточно данных для генерации значения, которое будет уникальным для каждого шифрования. Например, если запрос также содержит (в ясном) "идентификатор пользователя", вы можете использовать идентификатор пользователя в качестве источника IV. Настройка похожа на приведенную выше: вы получаете все эти данные, загружаете их в SHA-256, а первые 16 байтов вывода SHA-256 - это IV, который вам нужен. Это работает только в том случае, если эти данные не изменяются для данного зашифрованного сообщения и если они действительно уникальны. Это редкое явление: например, "идентификатор пользователя" хорош для этого только в том случае, если никогда не требуется повторно шифровать новое сообщение для одного и того же пользователя, и если никогда не существует возможности повторного использования идентификатора пользователя (например, старый пользователь завершает работу, появляется новый пользователь и выбирает теперь бесплатный идентификатор пользователя).

Использование случайного 16-байтового IV, сгенерированного с криптографически защищенным PRNG, по-прежнему является "безопасным" способом и тем, который я рекомендую. Если вы находите место в файле cookie плотно, это означает, что вы приближаетесь к пределу 4 kB, после чего вы можете использовать сжатие (по данным перед шифрованием, после шифрования сжатие очень маловероятно для работы). Используйте zlib (в Java вы можете получить доступ к zlib через java.util.zip).

Предупреждение: во всем вышеизложенном, я ничего не говорю о том, помогает ли шифрование файлов cookie в предоставлении любых характеристик безопасности, которые вы пытаетесь достичь. Обычно, когда требуется шифрование, вам действительно нужны как шифрование, так и целостность, а затем вы должны использовать режим комбинированного шифрования и целостности. Поиск GCM и CCM, Более того, шифрование файлов cookie в основном хорош для одной цели, что позволяет избежать затрат на хранение на стороне сервера немного пользовательских данных. Если вы хотите зашифровать файл cookie для чего-то другого, например. для проверки подлинности действительного пользователя, тогда вы делаете это неправильно: шифрование для этого не подходит.

Ответ 2

У меня нет прямого ответа на ваш вопрос, но есть несколько вещей, которые нужно добавить.

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

Еще одно замечание - никогда не использовать IV, который все 0 просто для удобства.

IV равны по размеру с вашим блоком. В случае AES-128 размер блока равен 128, ключ - 128 и, следовательно, IV - 128 бит.

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

изменить

Вы можете посмотреть эту страницу вики, чтобы узнать больше о том, какой режим использовать. Однако никогда не используйте ECB, если вы не уверены, что его следует использовать. И даже тогда, проверьте с экспертом. CBC, насколько я знаю, самый безопасный (вместе с PCBC).

http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation

Ответ 3

Если вы не делаете IV случайным (т.е. используете какую-то повторяющуюся группу чисел), будет легче определить ключ, если файл cookie всегда начинается с того же чистого текста.

Размер IV для AES-128 составляет 128 бит. IIRC, IV имеет тот же размер, что и блок шифрования. 128 бит - 16 байт. 32 байта, если вы храните его как шестнадцатеричную строку ASCII. Это действительно слишком много? 32 байта в этот день и возраст совсем невелик...

Ответ 4

Включите большое количество случайных чисел в файл cookie. Число 64 или 128 бит, вероятно, достаточно велико. Он должен быть достаточно большим, чтобы получить очень много дубликатов. Не забудьте поставить достаточно энтропии в это число. Не просто используйте gettime(). Если у вас есть доступ к CRNG, используйте его здесь.

Храните 256-битный мастер-ключ с вашим приложением. Используйте SHA256 для получения вашей ключевой информации. Опять же, используйте CRNG для этого.

$keyblob = sha256( concat("aeskeyid", $masterkey , $randomnumberwithcookie ) )
$aeskey = $keyblob[0..15]
$aesiv = $keyblob[16..31]

Вы также можете получить ключ для HMAC.

$mackeyblob = sha256( concat("hmackeyid", $masterkey , $randomnumberwithcookie ) )

В качестве альтернативы вы можете объединить два вышеперечисленных хэш-операций в один с помощью SHA512.

$keyblob = sha512( concat("randomkeyid", $masterkey , $randomnumberwithcookie ) )
$aeskey = $keyblob[0..15]
$aesiv = $keyblob[16..31]
$hmackey = $keyblob[32..63] 

Ответ 5

Можно избежать случайного IV, используя CBC и сохраняя HMAC перед сообщением. Использование случайно подобранной константы IV нормально. Но вы должны быть уверены, что все сообщения разные.

Это тот случай, когда зашифрованное сообщение всегда отличается. Лицензионный ключ с серийным номером будет соответствовать этим критериям. Файл cookie с идентификатором пользователя или идентификатором сеанса будет соответствовать ему.

Вы можете использовать CBC со случайной константой IV, если вы храните hmac перед сообщением. Хэш будет накапливать все изменения, распространенные в сообщении в первом блоке. Вы также можете добавить несколько случайных байтов или, желательно, серийный номер, если вы можете убедиться, что он будет уникальным или не будет повторно использован в течение очень долгого времени.

Даже не думайте использовать CTR с константой IV.