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 хэширования паролей, если есть такая возможность.
Оцените статью или поделитесь ей в соцсетях:
Рекомендуемые статьи:
Комментарии
Нет комментариев к данной статье.