PHP: встроенное API хеширования паролей


Думаю, ни для кого ни секрет, что нельзя хранить пароли в открытом виде. В целях безопасности их необходимо хешировать. Без хеширования пароли могут быть украдены злоумышленниками с помощью найденных уязвимостей в коде приложения, и в дальнейшем могут быть использованы для компрометации аккаунтов на других сервисах.

Увы, но многие пользователи повсюду используют один и тот же пароль, чем и пользуются злоумышленники.

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

Хеширование паролей защищает их только от компрометирования в вашем хранилище, но никак не защищает от внедрения вредоносного кода в ваши приложения (в случае наличия уязвимости разумеется).

Ранее считалось, что алгоритмы MD5, SHA-1 и SHA-256 относительно надежны. Но на данный момент данные хеш-функции не рекомендуется к использованию. Например, для MD5 существует способ нахождения коллизий с приемлемой вычислительной сложностью. Это значит что современные компьютеры могут «обратить» этот хэширующий алгоритм.

Компания Google давно выразила своё недоверие SHA-1, особенно в качестве использования этой функции для подписи сертификатов TLS. Ещё в 2014 году, вскоре после публикации работы Марка Стивенса, группа разработчиков Chrome объявила о постепенном отказе от использования SHA-1. В сравнении с SHA-1 теоретическая криптостойкость ГОСТ Р 34.11-94 равна 2 128, что во много раз превосходит 2 80 для SHA-1.

Многие профессионалы в области кибер-безопасности строго не рекомендуют использовать MD5 и SHA-1 для хеширования паролей.

При хешировании паролей, нужно учитывать две важные особенности: стоимость вычисления и, так называемая «соль» (модификатор). Чем выше стоимость вычисления алгоритма хеширования, тем больше потребуется времени для взлома.

Начиная с версии PHP 5.5 существует встроенное API хеширования паролей, которое позволяет безопасно не только хешировать, но и проверять пароли.

password_hash()

Итак, первая функция password_hash — создает хеш пароля, используя сильный, необратимый алгоритм хеширования. Функция password_hash() совместима с функцией crypt(). Поэтому, хеши паролей, созданные crypt() можно использовать с password_hash().

Список параметров:
string password_hash (string $password, integer $algo [, array $options ])
$password – пользовательский пароль, строковый параметр.
$algo – константа, обозначающая используемый алгоритм хеширования пароля.
$options – ассоциативный массив с опциями salt и cost.

Обратите внимание:
Параметр salt признан устаревшим, начиная с PHP 7.0.0 и настоятельно не рекомендуется к использованию.

Параметр cost – задает необходимую алгоритмическую сложность (стоимость).

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

Функция возвращает хешированный пароль, или FALSE в случае возникновения ошибки.

Пример:

<?php
/**
 * Хеширование пароля с настройками по умолчанию.
 * Будет использован алгоритм BCRYPT и длина хеша 60 символов.
 **/
echo password_hash("MyPassword", PASSWORD_DEFAULT);
?>

Пример поиска хорошего значения стоимости для password_hash():

<?php
/**
 * Данный код замерит скорость выполнения операции хеширования для вашего сервера
 * с разными значениями алгоритмической сложности для определения максимального
 * его значения, не приводящего к деградации производительности. 
 */
$timeTarget = 0.05; // 50 миллисекунд.
$cost = 8;
do {
    $cost++;
    $start = microtime(true);
    password_hash("test", PASSWORD_BCRYPT, ["cost" => $cost]);
    $end = microtime(true);
} while (($end - $start) < $timeTarget);
echo "Оптимальная стоимость: " . $cost;
?>

password_verify()

Вторая функция password_verify — проверяет, соответствует ли пароль созданному хешу.

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

Список параметров:
boolean password_verify (string $password, string $hash)
$password – пользовательский пароль, строковый параметр.
$hash – строковый параметр хеш, созданный функцией password_hash().

Возвращает TRUE или FALSE, в зависимости от результатов проверки.

Пример:

<?php
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
if (password_verify('MyPassword', $hash)) {
    echo 'Пароль правильный!';
} else {
    echo 'Пароль неправильный.';
}
?>

Заключение

Подводя итог, хотелось бы призвать всех программистов, правильно выбирать алгоритмы хеширования и проверки хешей, т.к. даже при проверке пароля нужно опасаться атак по времени, используя безопасные, на первый взгляд, инструменты сравнение строк. Ни операторы PHP == и ===, ни функция strcmp() не являются таковыми. Функция password_verify() как раз делает то, что нужно.

Настоятельно рекомендую использовать встроенное API хэширования паролей, если есть такая возможность.


Оцените статью или поделитесь ей в соцсетях:

+ 1 | - 0

Рекомендуемые статьи:


Комментарии

Нет комментариев к данной статье.

Оставьте комментарий!

Поля обозначенные как * требуются обязательно. Перед постингом всегда делайте просмотр своего комментария.