Пароль в PHP: хеширование и проверка как отдельные операции

2 мин чтения

Сохраняем пароль через password_hash, проверяем через password_verify и учитываем ограничения выбранного алгоритма.

Хранение и проверка пароля
  1. Регистрацияpassword_hash создаёт хеш с солью
  2. ХранилищеСохраняем хеш, а не исходный пароль
  3. Входpassword_verify проверяет пароль по хешу

Дважды вызовите password_hash для одного пароля — строки, скорее всего, окажутся разными. Это нормально: при входе не нужно вычислять новый хеш и сравнивать его со старым. Для проверки есть password_verify. Покажем обе операции и разберём, что хранить в базе, а что не должно попасть даже в журнал.

Минимальный жизненный цикл

<?php
$registrationPassword = 'учебный-пароль-47';
$storedHash = password_hash($registrationPassword, PASSWORD_DEFAULT);
if ($storedHash === false) {
    throw new RuntimeException('Не удалось создать хеш');
}
// В приложении storedHash сохраняется в записи пользователя.
$loginPassword = 'учебный-пароль-47';
$accepted = password_verify($loginPassword, $storedHash);
echo $accepted ? 'Совпало' : 'Не совпало';

Пример демонстрирует операции в одном процессе, чтобы не отвлекаться на базу данных. В рабочем приложении исходная строка после регистрации не сохраняется в журнале, таблице или сообщении об ошибке. В записи пользователя остаётся хеш. Он содержит сведения, необходимые функции проверки, поэтому отдельно придумывать, хранить и передавать соль для этого API не требуется. Выбор PASSWORD_DEFAULT позволяет опираться на алгоритм, предусмотренный установленной версией PHP.

Ограничения нужно знать заранее

В рассматриваемой версии PHP PASSWORD_DEFAULT использует bcrypt. У bcrypt учитываются первые семьдесят два байта пароля, поэтому политика максимальной длины должна учитывать байты и многобайтовый ввод. Нельзя без обсуждения добавлять самодельное предварительное хеширование: это меняет формат проверки и создаёт новый договор между регистрацией и входом. Для хранения предусматривайте запас длины, например поле на двести пятьдесят пять символов, поскольку значение алгоритма по умолчанию может измениться.

Хеширование не ограничивает число попыток входа и не заменяет защищённое соединение. Ограничения частоты, защита восстановления доступа и обращение с сессией проектируются отдельно. Стоимость вычисления выбирайте после измерения в своём окружении и с учётом нагрузки; этот учебный пример не устанавливает универсального времени ответа. Не принимайте настройки алгоритма из пользовательского запроса. Обновление политики требует возможности постепенно обновлять сохранённые хеши после успешной проверки.

Проверка без секретов в выводе

Проверьте верный пароль, ошибку в одной букве и пустую строку. Два хеша одного пароля должны различаться, а password_verify — принимать оба. Убедитесь, что поле базы не обрезает хеш. В результатах теста достаточно записать успех или причину отказа; пароль и полную запись пользователя сохранять не нужно.

Источники и дальнейшее чтение