powerman
@powerman
Systems Architect, Senior Go/Perl Linux Developer

Как безопаснее хранить пароли пользователей в базе данных (хеширование, bcrypt, соль, перец)?

Поправьте меня, если я не прав, но, насколько я понимаю, если перец не используется, то на сегодняшний день оптимальное решение это bcrypt($password) (случайная соль, cost=10). При этом будут использованы только первые 72 символа пароля, что допустимо. Возможные вариации - scrypt($password) если есть вероятность, что ломать будут всерьёз на спец.железе либо sha256($password . $salt) если есть опасность, что использование bcrypt может привести к DoS атаке вашего сервиса из-за отсутствия адекватной защиты от перебора паролей.

А вот с перцем всё не настолько однозначно. Он должен быть достаточно большим, поэтому если просто добавить его к паролю, это сильно снизит количество используемых символов пароля. Чтобы этого избежать, нужно использовать комбинацию из bcrypt и HMAC, и вот тут есть варианты, разница между которыми с точки зрения криптографии мне не ясна:
bcrypt(hmac_sha256($pepper, $password))
hmac_sha256($pepper, bcrypt($password))
Какой из этих вариантов лучше?

Ещё один вопрос - в качестве примера часто используют hmac_sha256($password, $pepper) но мне кажется что логичнее первым параметром (в качестве ключа) передавать перец: hmac_sha256($pepper, $password) Есть ли между этими вариантами какая-то разница с точки зрения криптографии?

P.S. Да, подразумевается что hmac_sha256() возвращает результат в base64 - иначе могут возникнуть проблемы из-за нулевого байта в некоторых реализациях bcrypt.
  • Вопрос задан
  • 4243 просмотра
Решения вопроса 1
powerman
@powerman Автор вопроса
Systems Architect, Senior Go/Perl Linux Developer
Судя по всему, правильнее вместо HMAC использовать шифрование любым стандартным алгоритмом использующим IV:encrypt_aes_cbc($pepper, bcrypt($password))Причин несколько:
  • Возможность заменить $pepper в любой момент (периодически, или после утечки).
  • Использовать MAC для этой цели это misuse - он предназначен для другой задачи, в отличие от шифрования, которое здесь как раз на своём месте.
  • Последовательное хеширование разными алгоритмами без криптоанализа может ослабить безопасность; кроме того это изобретение собственного крипто-алгоритма, чего лучше избегать.
Но если есть такая возможность, то гораздо надёжнее не использовать шифрование и $pepper, а вместо этого запретить пользователям использовать слишком простые пароли (всё-таки если хакеры нашли SQLi, то часто они могут добраться и до чтения файлов, а значит узнать $pepper).

Что касается моего второго вопроса, то смутившая меня передача $pepper последним параметром была вызвана тем, что в примерах использовался синтаксис PHP, а там ключ передаётся последним.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы