Такие хеширующие алгоритмы как MD5, SHA1 и SHA256 были спроектированы очень быстрыми и эффективными. При наличии современных технологий и оборудования, стало довольно просто выяснить результат этих алгоритмов методом "грубой силы" для определения оригинальных вводимых данных.

Из-за той скорости, с которой современные компьютеры могут "обратить" эти хеширующие алгоритмы, многие профессионалы компьютерной безопасности строго не рекомендуют использовать их для хеширования паролей. С PHP 5.5 появилось API хеширования паролей, которое безопасно работает и с хешированием и с проверкой паролей.

API хеширования паролей предоставляет простую в использовании обертку функции crypt() и некоторых других алгоритмов хеширования пароля для легкого создания и управления паролями.

Для сборки этого расширения не требуются внешние библиотеки. Для хеширования паролей через Argon2 требуется "libargon2". Начиная с PHP 7.3.0, требуется libargon2 версии 20161029 или выше.

Хэш API состоит из следующих функций:

  • password_get_info - Возвращает информацию о заданном хеше.
  • password_hash - Создает хеш пароля.
  • password_needs_rehash - Проверяет, что указанный хеш соответствует заданным опциям.
  • password_verify - Проверяет, соответствует ли пароль хешу.

password_get_info()

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

  • algo - константа с названием алгоритма
  • algoName - название алгоритма
  • options - различные настройки
$pswd = password_hash('mypswd', PASSWORD_BCRYPT);

print_r(password_get_info($pswd));

/*
Array
(
    [algo] => 1
    [algoName] => bcrypt
    [options] => Array
        (
            [cost] => 10
        )
)
*/

password_hash()

Функция password_hash() упрощает процесс настолько, насколько это возможно. Если вам нужно создать хэш пароля, вызовите эту функцию и запишите значение в базу данных. Пример:

$hash = password_hash('mypswd', PASSWORD_BCRYPT);

echo $hash; // $2y$10$Nd6ZwKdOgN7WLwWC1JdCweM6rnufbtl4lGpVgUATWj/O8BlEg44tm

Первый параметр - это строка представляющая собой пароль; второй - алгоритм, который будет применён.

В данный момент поддерживаются следующие алгоритмы:

  • PASSWORD_DEFAULT - используется алгоритм bcrypt.
  • PASSWORD_BCRYPT - использует алгоритм CRYPT_BLOWFISH. Генерирует стандартный хеш, совместимый с генерированным функцией crypt() с использованием идентификатора "$2y$". В результате будет сгенерирована строка длиной 60 символов, или FALSE в случае возникновения ошибки.
  • PASSWORD_ARGON2I - Использовать алгоритм хеширования Argon2i. Этот алгоритм доступен только если PHP собран с поддержкой Argon2.
  • PASSWORD_ARGON2ID - Использовать алгоритм хеширования Argon2id. Этот алгоритм доступен только если PHP собран с поддержкой Argon2.

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


password_needs_rehash()

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

$password = 'mypswd';
$hash = '$2y$10$YCFsG6elYca568hBi2pZ0.3LDL5wjgxct1N8w/oLR/jfHsiQwCqTS';

// Параметр стоимости может изменяться в связи со сменой оборудования
$options = ['cost' => 11];

// Проверка сохраненного хеша с помощью пароля
if (password_verify($password, $hash)) {
    // Проверяем, не нужно ли использовать более новый алгоритм или другую алгоритмическую стоимость
    if (password_needs_rehash($hash, PASSWORD_BCRYPT, $options)) {
        // Если таки да, перехешируем и сохраняем новый хеш
        $new_hash = password_hash($password, PASSWORD_BCRYPT, $options);
    }
	
    // Авторизуем пользователя
}

password_verify()

Функция password_verify() принимает пароль в обычном виде и его хэш. В зависимости от результатов проверки, возвращает true или false. Пример:

if (password_verify($password, $hash)) {
    // Успех!
} else {
    // Провал
}

// password - полученный пароль от пользователя
// hash - хеш хранящийся в базе данных

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