CTR безопасность требует, чтобы вы никогда не использовали повторно IV для двух шифрований сообщений с одним и тем же ключом. На самом деле это еще строже: режим CTR работает путем шифрования последовательных значений счетчика (IV - просто начальное значение для этого счетчика), и надлежащая безопасность достигается только в том случае, если одно и то же значение счетчика не используется дважды; это означает, что шифрование значения с помощью IV фактически «потребляет» последовательность последовательных значений IV, которую нельзя использовать с другим шифрованием.
Самый простой способ сделать это - использовать криптографически безопасный генератор случайных чисел и создать новый 16-байтовый случайный IV для каждого сообщения. Я подчеркиваю «криптографически безопасный», потому что это важно; базового генератора случайных чисел недостаточно. С Java используйте java.util.SecureRandom
. С Win32 звоните CryptGenRandom()
. При случайном выборе пространство возможных 128-битных IV достаточно велико, поэтому коллизии крайне маловероятны. Собственно, поэтому AES использует 128-битные блоки (что подразумевает 128-битный IV).
Сущность, которая расшифровывает сообщение, должна знать IV, поэтому вы должны сохранить его вместе с зашифрованным сообщением. Это дополнительные 16 байтов. Я понимаю, что вы должны избегать этих издержек, хотя 16 байт не так уж много для куки. Эффективная максимальная длина файла 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 - это то, что вам нужно. Это работает, только если эти данные не изменяются для данного зашифрованного сообщения, и если оно действительно уникально. Это редкое явление: например, «идентификатор пользователя» подходит для этого только в том случае, если нет необходимости повторно зашифровывать новое сообщение для того же пользователя, и если никогда не существует вероятность повторного использования идентификатора пользователя (например, старый пользователь выходит, новый пользователь приходит и выбирает теперь свободный идентификатор пользователя).
Использование случайного 16-байтового IV, сгенерированного с помощью криптографически безопасного PRNG, все еще остается «безопасным» способом, и я рекомендую его. Если в файле cookie недостаточно места, это означает, что вы приближаетесь к пределу в 4 КБ, и в этот момент вы можете захотеть использовать сжатие (для данных до шифрования; после шифрования сжатие очень очень вряд ли сработает). Используйте zlib (в Java вы можете получить доступ к zlib через java.util.zip
).
Предупреждение: во всех вышеперечисленных случаях я не говорю что-нибудь о том, помогает ли шифрование файлов cookie обеспечивать любые характеристики безопасности, которые вы пытаетесь достичь. Обычно, когда требуется шифрование, вам действительно нужны и шифрование, и целостность, а затем вам следует использовать режим комбинированного шифрования и целостности. Найти GCM и CCM . Кроме того, шифрование cookie в основном подходит для одной цели, которая заключается в том, чтобы избежать затрат на хранение на стороне сервера части пользовательских данных. Если вы хотите зашифровать куки для чего-то другого, например, аутентифицировать действительного пользователя, тогда вы делаете это неправильно: шифрование не является подходящим инструментом для этого.