Какой алгоритм шифрования лучше всего подходит для шифрования файлов 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, чтобы он:
а) злонамеренные пользователи не могут прочитать его содержимое,
б) злонамеренные пользователи не могут сфабриковать свой собственный файл cookie или тампер.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Предупреждение о безопасности . Эти две функции не являются безопасными. Они используют режим 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'); 

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

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

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

Убедитесь, что для каждого шифрования используется новое значение nonce, и используйте поле «связанные данные», чтобы убедиться, что вещь, которую вы зашифровали для одной цели, не представлена ​​как другая, поэтому такие вещи, как имя пользователя и имя файла cookie, могут там)

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

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

Быстрые, зашифрованные файлы 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 .

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

шифрование

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

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

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

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

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


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

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

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

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

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

Погашение значка «Запомнить меня»

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

даже если кто-то «украл» куки, они не смогут его использовать 🙂

Надеюсь это поможет 🙂

feha vision.to

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

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