Какой алгоритм шифрования лучше всего подходит для шифрования файлов cookie?

Поскольку этот вопрос довольно популярен, я счел полезным дать ему обновление.

Подчеркиваю правильный ответ, заданный AviD, на этот вопрос:

Вы не должны хранить данные, требующие шифрования в вашем файле cookie. Вместо этого храните произвольный ключ (128 бит /16 байт) в файле cookie и сохраняйте информацию, которую вы хотите сохранить на сервере, идентифицированный с помощью файла cookie.



Я ищу информацию об "лучшем" алгоритме шифрования для шифрования файлов cookie.

У меня есть следующие требования:

  • Он должен быть быстрым
    шифрование и дешифрование данных будут выполняться для (почти) каждого запроса

  • Он будет работать с небольшими наборами данных, обычно строки длиной около 100 символов

  • Он должен быть безопасным, но это не похоже на то, что мы обеспечиваем банковские транзакции.

  • Нам нужно иметь возможность расшифровать информацию, чтобы SHA1 и т.п. отсутствовали.

Теперь я прочитал, что Blowfish является быстрым и безопасным, и я прочитал, что AES является быстрым и безопасным. С Blowfish с меньшим размером блока.

Я думаю, что оба алгоритма обеспечивают более чем адекватную безопасность? поэтому скорость станет решающим фактором. Но я действительно не знаю, подходит ли этот алгоритм для строки с небольшим символом, и если есть, возможно, более подходящий алгоритм для шифрования файлов cookie.

Итак, мой вопрос:
Какой алгоритм шифрования лучше всего подходит для шифрования данных cookie?

Обновление
Чтобы быть более точным, мы хотим зашифровать 2 файла cookie: один с информацией о сеансе, а другой с информацией "remeber me".

Платформа - это PHP как модуль apache для Linux на VPS.

Обновление 2
Я согласен с cletus, что сохранение любой информации в файле cookie небезопасно.

Однако у нас есть требование реализовать функцию "remeber me". Принятый способ сделать это - установить cookie. Если клиент представляет этот файл cookie, ему или ей разрешен доступ к системе с (почти) равными правами, как если бы он представил правильную комбинацию имени пользователя.

Поэтому мы по крайней мере хотим зашифровать все данные в файле cookie, чтобы он:
a) злонамеренные пользователи не могут прочитать это содержимое,
b) злонамеренные пользователи не могут сфабриковать свой собственный файл cookie или тампер.

(Все данные из файлов cookie дезинфицируются и проверяются на достоверность, прежде чем мы что-либо с ним сделаем, но это другая история)

Файл cookie сеанса больше не содержит sessionId/timestamp. Его можно было бы использовать без шифрования, но я не вижу вреда в его шифровании? (кроме времени вычисления).

Итак, учитывая, что мы должны хранить некоторые данные в файле cookie, что лучший способ его зашифровать?

Обновление 3
Ответы на этот вопрос заставили меня пересмотреть выбранный подход. Я действительно могу сделать то же самое без необходимости шифрования. Вместо шифрования данных я должен отправлять только те данные, которые бессмысленны без контекста и не могут быть угаданы.

Однако я тоже не понимаю:
Я думал, что шифрование позволило нам отправить данные в BigBadWorld & trade;, и по-прежнему (честно) уверен, что никто не сможет читать или вмешиваться в это...
Разве это не все, что нужно для шифрования?

Но реакции ниже продвигаются вперед: не доверяйте шифрованию для обеспечения безопасности.

Что мне не хватает?

Ответы

Ответ 1

Нет реальной причины не идти с AES с 256 бит. Обязательно используйте это в режиме CBC и дополнении PKCS # 7. Как вы сказали, быстро и безопасно.

Я прочитал (не тестировал), что Blowfish может быть немного быстрее... Однако у Blowfish есть главный недостаток длительного времени настройки, что ухудшит вашу ситуацию. Кроме того, AES более "доказана".

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

  • длинное случайное число, хранящееся в базе данных и сопоставленное с учетной записью пользователя;
  • или хеш-ключ (например, HMAC), содержащий, например, имя пользователя, метка времени, mebbe соль, и секретный ключ сервера. Это, конечно, может быть проверено на стороне сервера...

Похоже, мы немного отвлеклись от вашего оригинального, конкретного вопроса - и изменили основы вашего вопроса, изменив дизайн....
Так до тех пор, как мы делаем это, я бы также настоятельно рекомендуем эту особенность стойких "запомнить меня", по нескольким причинам, самая большая из них:

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

Ответ 2

Это касается двух отдельных проблем.

Во-первых, захват сеанса. Здесь третья сторона обнаруживает, скажем, аутентифицированный файл cookie и получает доступ к другим деталям.

Во-вторых, существует безопасность данных сеанса. Под этим я подразумеваю, что вы храните данные в файле cookie (например, имя пользователя). Это не очень хорошая идея. Любые такие данные в принципе недостоверны, так же как и данные формы HTML ненадежны (независимо от того, какие ограничения на использование Javascript и/или ограничения длины HTML вы используете, если таковые имеются), поскольку клиент может свободно отправлять то, что они хотят.

Вы часто найдете людей (справедливо), защищающих дезинфекцию данных формы HTML, но данные cookie будут вслепую приняты по номиналу. Большая ошибка. На самом деле, я никогда не храню информацию в cookie. Я рассматриваю его как ключ сессии и все.

Если вы намерены хранить данные в файле cookie, я настоятельно рекомендую вам пересмотреть.

Шифрование этих данных не делает информацию более достоверной, поскольку симметричное шифрование восприимчиво к атаке грубой силы. Очевидно, что AES-256 лучше, чем, скажем, DES (heh), но 256-разрядная защита не обязательно означает столько, сколько вы думаете.

С одной стороны, ОСВ обычно генерируются в соответствии с алгоритмом или в других случаях подвержены атаке.

Для другого, данные cookie являются основным кандидатом для crib атак. Если известно или подозревается, что имя пользователя в зашифрованных данных будет эй, там ваша кроватка.

Это возвращает нас к первому пункту: угон.

Следует отметить, что в средах с общим хостингом в PHP (как один пример) ваши данные сеанса просто хранятся в файловой системе и могут быть прочитаны кем-либо еще на том же узле, хотя они не обязательно знают, какой сайт он для. Поэтому никогда не храните незашифрованные пароли, номера кредитных карт, обширные личные данные или что-либо, что в противном случае могло бы считаться конфиденциальным в данных сеанса в таких средах без какой-либо формы шифрования или, еще лучше, просто хранить ключ в сеансе и сохранять фактическую чувствительность данных в базе данных.

Примечание. выше не является уникальным для PHP.

Но это шифрование на стороне сервера.

Теперь вы можете утверждать, что шифрование сеанса с некоторыми дополнительными данными сделает его более безопасным от угона. Общим примером является IP-адрес пользователя. Проблема заключается в том, что многие люди используют один и тот же ПК/ноутбук в разных местах (например, горячие точки Wi-Fi, работа, дома). Также многие среды будут использовать различные IP-адреса в качестве исходного адреса, особенно в корпоративных средах.

Вы также можете использовать агент пользователя, но это возможно.

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

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

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

Ответ 3

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

Для тех, кто читает, желая использовать этот метод в PHP-скриптах. Вот рабочий пример с использованием 256-битного Rijndael (не AES).

function encrypt($text, $salt) 
{ 
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $salt, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); 
} 

function decrypt($text, $salt) 
{ 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $salt, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); 
}

Затем, чтобы сохранить файл cookie

setcookie("PHPSESSION", encrypt('thecookiedata', 'longsecretsalt'));

и прочитать на следующей странице:

$data = decrypt($_COOKIE['PHPSESSION'], 'longsecretsalt');

Ответ 4

Вы можете добиться того, что хотите надежно, используя AES в режиме EAX. Шифрованный текст будет больше, чем открытый текст; это нормально для безопасного шифрования.

Злоумышленник, конечно же, будет знать длину вашего открытого текста из зашифрованного текста, но они не должны ничего определять.

Произвольно генерируйте ключи AES.

Будьте уверены и используйте новое значение для каждого шифрования и используйте поле "связанные данные", чтобы убедиться, что вещь, которую вы зашифровали для одной цели, не представляется для другого (так что такие вещи, как имя пользователя и имя файла cookie может войти туда)

реакции ниже подталкивают: Do не доверять шифрованию для выполнения безопасности.

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

Ответ 5

Быстрые, зашифрованные файлы cookie с Libsodium

Если вам нужны быстрые, защищенные зашифрованные файлы cookie в PHP, посмотрите, как Halite реализует их. Halite полагается на расширение libsodium PECL для обеспечения безопасной криптографии.

<?php
use \ParagonIE\Halite\Cookie;
use \ParagonIE\Halite\Symmetric\Key;
use \ParagonIE\Halite\Symmetric\SecretKey;

// You can also use Key::deriveFromPassword($password, $salt, Key::CRYPTO_SECRETBOX);
$encryption_key = new SecretKey($some_constant_32byte_string_here);

$cookie = new Cookie($encryption_key);

$cookie->store('index', $any_value);
$some_value = $cookie->fetch('other_index');

Если вы не можете установить расширения PECL, попросите своего администратора или хостинг-провайдера сделать это за вас. Если они откажутся, у вас все еще есть варианты.


Защищенные зашифрованные файлы cookie в PHP, удерживайте соль.

Другие ответы дают вам право зашифровать ваши данные с помощью openssl или mcrypt, но они не имеют решающего шага. Если вы хотите безопасно шифровать данные в PHP, вы должны аутентифицировать свои сообщения.

Используя расширение OpenSSL, процесс, который вам нужно выполнить, выглядит следующим образом:


Преамбула

  • (Прежде чем вы даже задумаетесь о шифровании) Создайте 128-битную, 192-битную или 256-битную случайную строку. Это будет ваш главный ключ.

    Не используйте удобочитаемый пароль. Если вы по какой-то причине должны использовать удобочитаемый пароль, спросите Cryptography SE для руководства.

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

Шифрование

  • Создайте случайный вектор инициализации (IV) или nonce. например random_bytes(openssl_cipher_iv_length('aes-256-cbc'))
  • Используйте HKDF или аналогичный алгоритм разделения основного ключа на два ключа:
    • Ключ шифрования ($eKey)
    • Ключ аутентификации ($aKey)
  • Зафиксируйте свою строку с помощью openssl_encrypt() с помощью вашего IV и соответствующего modate (например, aes-256-ctr) с помощью ключа шифрования ($eKey) с шага 2.
  • Вычислить тег аутентификации вашего зашифрованного текста с шага 3 с помощью хеш-функции с ключом, такой как HMAC-SHA256. например hash_hmac('sha256', $iv.$ciphertext, $aKey). Очень важно аутентифицироваться после шифрования и инкапсулировать IV/nonce.
  • Составьте тег аутентификации, IV или nonce и зашифрованный текст вместе и, возможно, закодируйте его с помощью bin2hex() или base64_encode(). (Предупреждение: этот подход может привести к утечке информации о времени кеширования.)

дешифрование

  • Разделите свой ключ в соответствии с шагом 2 при шифровании. Нам нужны те же самые два ключа во время дешифрования!
  • (необязательно, декодировать и) распаковывать MAC, IV и зашифрованный текст из упакованного сообщения.
  • Проверьте тег аутентификации путем пересчета HMAC IV/nonce и зашифрованного текста с предоставленным пользователем HMAC с помощью hash_equals().
  • Если и только если шаг 3 проходит, расшифруйте зашифрованный текст с помощью $eKey.

Если вы хотите увидеть, как все это выглядит вместе, см. этот ответ с образцом кода.

Если это звучит слишком много, используйте defuse/php-encryption или zend-crypt и назовите это днем.


Запомнить меня Cookies

Однако у нас есть требование реализовать функцию "remeber me". Принятый способ сделать это - установить cookie. Если клиент представляет этот файл cookie, ему или ей разрешен доступ к системе с (почти) равными правами, как если бы он представил правильную комбинацию имени пользователя.

Шифрование на самом деле не является правильным инструментом для этой работы. Вы хотите следовать этому процессу для secure запомнить мои файлы cookie в PHP:

Создание токена "Запомнить меня"

  • Создайте две случайные строки:
    • A selector, который будет использоваться для поиска базы данных. (Цель случайного селектора вместо простого последовательного идентификатора - не утечка количества активных пользователей на вашем веб-сайте. Если вам удобно утечка этой информации, не стесняйтесь использовать последовательный идентификатор.)
    • A validator, который будет использоваться для автоматической аутентификации пользователя.
  • Вычислить хэш validator (достаточно простого хэша SHA-256).
  • Сохраните selector и хэш validator в таблице базы данных, зарезервированной для автоматического входа в систему.
  • Сохраните selector и validator в файле cookie на клиенте.

Погасить токен "Запомнить меня"

  • Разделите входящий файл cookie на selector и validator.
  • Выполните поиск базы данных (используйте подготовленные инструкции!) на основе selector.
  • Если строка найдена, вычислите хэш validator.
  • Сравните хэш, вычисленный на шаге 3, с хешем, хранящимся в базе данных, снова используя hash_equals().
  • Если шаг 4 возвращает true, запишите пользователя в соответствующую учетную запись.

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

Ответ 6

В то время как оба очень сильные, AES является стандартом.

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

Ответ 7

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

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

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

Ответ 8

Почему вы хотите зашифровать файл cookie?

Как я вижу, есть два случая: либо вы предоставляете клиенту ключ, либо нет.

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

Если вы передадите клиенту ключ, то почему вы зашифруете его в первую очередь? Если вы не зашифруете сообщение ключа, тогда шифрование файла cookie будет спорным: MITM может посмотреть на файл cookie и отправить вам любой куки файл, который он хочет. Если вы используете зашифрованный канал для клиента, почему дополнительные накладные расходы на шифрование сохраненных данных?

Если вы беспокоитесь о том, что другие пользователи на компьютере-клиенте читают куки файлы, откажитесь и предположите, что браузер устанавливает хорошие бит разрешения:)

Ответ 9

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

В частности, в мире PHP полно плохих примеров, которые игнорируют это (см. криптография PHP - продолжайте осторожно), но это применимо к любому языку,

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

Ответ 10

AES (также известный как Rijndael) является самым популярным. Размер блока составляет 128 бит, это всего лишь 16 байт, и вы говорите "около 100 символов".

Ответ 11

Я думаю, что "раздавать" любые данные, даже зашифрованные, когда речь идет о имени пользователя и пароле, не очень хороша... Есть много JS, которые могут нюхать его... Я предлагаю вам создать в таблице пользователей DB поле cookie_auth или что-то еще...

после первого входа в систему: текущий: браузер, IP, ans собственный ключ соля, плюс ваше имя хоста var...

создать хэш и сохранить в этом поле... установить cookie... когда cookie "отвечает", сравните все это с сохраненным хешем и сделайте...

даже если кто-то "украл" куки файлы, они не смогут его использовать: -)

Надеюсь, что это поможет: -)

FEHA vision.to

Ответ 12

Кроме того, я пробовал mcrypt_encrypt и одно, пожалуйста, имейте в виду. Если вы делаете base64_encode(mcrypt_encrypt(...)).

а затем вы выполните base64_decode и выведите зашифрованные данные (echo). Вероятно, вы будете ввернуты и ничего не увидите. Однако, если вы делаете mcrypt_decrypt( ... base64_decode($value) ). Вы увидите исходные данные.