Как хешировать пароли в PHP: современные алгоритмы

Раздел: Безопасность в PHP -> Управление паролями в PHP

Безопасное хеширование с помощью встроенных функций PHP

Основное решение: функции password_hash и password_verify.

Для хранения паролей в PHP рекомендуется использовать password_hash() с алгоритмом bcrypt или Argon2. Эти функции автоматически генерируют случайную соль и включают её в хеш. Пример создания хеша:

$hash = password_hash('mypassword', PASSWORD_BCRYPT, ['cost' => 12]);

Php логин и пароль вход (логин и пароль для входа в php)

Проверка пароля выполняется функцией password_verify():

if (password_verify('mypassword', $hash)) { echo 'Пароль верен'; }

Php пароль на вход (пароль для входа в php)

Типичная ошибка: использование низкого значения cost (по умолчанию 10). Следует устанавливать cost не ниже 10, а лучше 12, в зависимости от производительности сервера. Также нельзя хранить пароли в открытом виде или использовать md5/sha1.

Цель: защита паролей от перебора и радужных таблиц. Применение: любое приложение, требующее аутентификации пользователей.

Как хешировать пароль используя MD5 с солью?

Устаревший подход, при котором соль (случайная строка) добавляется к паролю, после чего считается MD5-хеш. Пример:

$salt = bin2hex(random_bytes(16));
$hash = md5($salt . $password);

Php хеширования пароля (хеширование пароля в php)

Результат: строка длиной 32 символа (hex). Для проверки требуется хранить соль отдельно.

MD5 не рекомендуется из-за высокой скорости вычисления и уязвимости к коллизиям. Даже с солью такой хеш легко поддаётся перебору на современных GPU. Эта техника считается небезопасной.

Использование: только в старых системах, которые невозможно обновить.

Как хешировать пароль с помощью SHA-256 и соли?

Подобно MD5, но с более стойким алгоритмом SHA-256. Соль генерируется случайно. Пример:

$salt = bin2hex(random_bytes(16));
$hash = hash('sha256', $salt . $password);

Хеш длиннее (64 символа hex).

Хотя SHA-256 криптостойкий, скорость его вычисления всё ещё высока, что делает его уязвимым для быстрого перебора. Для хеширования паролей нужны медленные алгоритмы (bcrypt, Argon2). SHA-256 больше подходит для проверки целостности данных.

Цель: демонстрация неправильного подхода; не следует использовать в новых проектах.

Как хешировать пароль с помощью crypt() в стиле Blowfish?

До появления password_hash часто использовали функцию crypt() с алгоритмом CRYPT_BLOWFISH. Пример генерации соли и хеша:

$salt = '$2y$10$' . bin2hex(random_bytes(22));
$hash = crypt($password, $salt);

Здесь '$2y$10$' обозначает алгоритм Blowfish со стоимостью 10 (2^10 итераций).

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

Применение: для совместимости со старыми версиями PHP (до 5.5). В настоящее время устарел.

Как хешировать пароль без соли?

Хеширование пароля без соли, например, md5($password). Пример:

$hash = md5('password'); // одинаково для всех пользователей с паролем 'password'
Категорически небезопасно: одинаковые пароли дают одинаковые хеши, радужные таблицы позволяют находить исходный пароль мгновенно. Использовать запрещено.

Случаи: никогда не использовать.

Продвинутые примеры хеширования паролей в PHP

Использование алгоритма Argon2id

Настройка параметров памяти, времени и потоков.

Пример
$options = [
    'memory_cost' => 1 << 17, // 128 MB
    'time_cost'   => 4,
    'threads'     => 2,
];
$hash = password_hash('my_strong_password', PASSWORD_ARGON2ID, $options);
echo $hash;
$2y$12$... (или $argon2id$v=19$...)

Пояснение: Argon2id обеспечивает защиту от атак как по времени, так и по памяти. Значения подбираются в зависимости от возможностей сервера.

Проверка необходимости перехеширования

При изменении алгоритма по умолчанию или параметров стоимости.

Пример
$hash = password_hash('old_password', PASSWORD_BCRYPT, ['cost' => 10]);
// Через некоторое время повысили cost
if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12])) {
    $newHash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
    // обновить в базе
}
true (если cost отличается)

Сравнение скорости алгоритмов

Измерение времени выполнения для bcrypt и Argon2.

Пример
$start = microtime(true);
password_hash('test', PASSWORD_BCRYPT, ['cost' => 10]);
$end = microtime(true);
echo 'BCrypt time: ', ($end - $start) * 1000, ' ms';

$start = microtime(true);
password_hash('test', PASSWORD_ARGON2ID, ['memory_cost' => 65536, 'time_cost' => 4]);
$end = microtime(true);
echo ' Argon2 time: ', ($end - $start) * 1000, ' ms';
BCrypt time: 52.3 ms Argon2 time: 89.1 ms

Хеширование с разными алгоритмами в одной системе

Обработка старых хешей и переход на новый алгоритм.

Пример
if (password_verify($password, $hash)) {
    if (password_needs_rehash($hash, PASSWORD_ARGON2ID, $options)) {
        $newHash = password_hash($password, PASSWORD_ARGON2ID, $options);
        // сохранить $newHash
    }
}
Пароль проверен и обновлён.

Генерация соли вручную для устаревших методов (не рекомендуется)

Пример генерации 22-символьной соли для crypt() Blowfish.

Пример
$salt = '$2y$10$' . str_replace('+', '.', base64_encode(random_bytes(22)));
$hash = crypt($password, $salt);
$2y$10$... (64 символа)

Важно: base64 кодировка с заменой '+' на '.' для совместимости с Blowfish.

Хеширование пароля в PHP - comments

En
Php хеширования пароля (php)