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

StackOverflow https://stackoverflow.com/questions/606179

Вопрос

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

Позвольте мне подчеркнуть правильный ответ как указано АвиД на этот вопрос:

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



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

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

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

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

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

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

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

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

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

Обновлять
Точнее, мы хотим зашифровать 2 файла cookie:один с информацией о сеансе, а другой с информацией «запомнить меня».

Платформой является PHP в качестве модуля Apache в Linux на VPS.

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

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

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

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

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

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

Похоже, мы немного отклонились от темы вашего первоначального конкретного вопроса и изменили основу вашего вопроса, изменив дизайн....
Пока мы это делаем, я бы НАСТОЯТЕЛЬНО рекомендовал ПРОТИВ Эта особенность настойчивого «запомни меня» обусловлена ​​несколькими причинами, самой большой из них:

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

Другие советы

Это затрагивает два отдельных вопроса.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Для тех, кто читает и хочет использовать этот метод в сценариях 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 случайным образом.

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

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

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

Быстрые зашифрованные файлы cookie с помощью Libsodium

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

<?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-битную случайную строку.Это будет твой мастер ключ.

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

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

Шифрование

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

Расшифровка

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

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

Если вам кажется, что это слишком большая работа, используйте обезвредить/php-шифрование или Zend-крипта и на этом закончим.


Запомни меня печенье

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Feha Vision.to

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top