Глиф Учебники

Как хешировать пароль: password_hash и password_verify

Справочник · PHP · 2 минуты чтения

При регистрации сохраняйте в базу не пароль, а его хеш:

PHP
<?php
$hash = password_hash($password, PASSWORD_DEFAULT);

При входе сверяйте введённый пароль с хешем из базы:

PHP
<?php
if (password_verify($password, $user['password_hash'])) {
    // пароль верный
}

Как это выглядит целиком:

PHP
<?php
$hash = password_hash('секретный пароль', PASSWORD_DEFAULT);
var_dump(password_verify('секретный пароль', $hash));
var_dump(password_verify('другой пароль', $hash));
Вывод
bool(true)
bool(false)

Что такое хеш

Хеш — результат необратимого преобразования: из пароля хеш получить легко, из хеша пароль — нельзя. Если базу украдут, злоумышленник увидит хеши, а не пароли, и подбирать каждый пароль ему придётся долго.

Хеш от password_hash выглядит как строка вида $2y$… длиной 60 знаков (это алгоритм bcrypt). В нём уже есть всё нужное для проверки: алгоритм, «стоимость» вычисления и соль — случайная добавка, которую PHP создаёт сам. Из-за соли один и тот же пароль каждый раз даёт разный хеш, и сравнивать хеши напрямую бесполезно — только через password_verify.

Столбец для хеша в базе делайте VARCHAR(255): при смене алгоритма хеши могут стать длиннее 60 знаков.

Обновление хеша

PASSWORD_DEFAULT — алгоритм, который PHP считает лучшим сейчас; со временем он может измениться, а настройки стать строже. Хеши старых пользователей обновляют при входе — в момент, когда пароль известен:

PHP
<?php
if (password_verify($password, $user['password_hash'])) {
    if (password_needs_rehash($user['password_hash'], PASSWORD_DEFAULT)) {
        $newHash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $pdo->prepare('UPDATE users SET password_hash = ? WHERE id = ?');
        $stmt->execute([$newHash, $user['id']]);
    }
    // вход выполнен
}

Если PHP собран с поддержкой Argon2 (в пакетах Ubuntu и Debian она есть), можно выбрать его явно: password_hash($password, PASSWORD_ARGON2ID). password_verify понимает хеши любого из этих алгоритмов.

Чего делать нельзя

Не храните пароли открытым текстом и не «шифруйте» их функциями md5, sha1, hash('sha256', …). Они считаются очень быстро: по украденной базе такие хеши подбирают миллиардами вариантов в секунду, а для простых паролей есть готовые таблицы ответов.

Пример входа с сессией — в уроке Сессии и куки, работа с базой — в уроке База данных через PDO.