Раздел объясняет, почему пароли защищают функциями хеширования, и как захешировать пароль так, чтобы его было трудно раскрыть.
Почему требуется хешировать пароли пользователей?
Хеширование паролей — приоритетный фактор безопасности, который учитывают при разработке приложения или службы, которые принимают пароли пользователей. Без хеширования пароли, которые хранятся, украдут, если хранилище данных скомпрометируют, а затем немедленно применят для компрометации и приложения или службы, и учётных записей пользователей в других службах, если пользователи других служб не установили уникальные пароли.
Алгоритм, который применяют для хеширования паролей пользователей перед сохранением, серьёзно затрудняет раскрытие исходного пароля злоумышленником, при этом доступ к сравнению хеша с исходным паролем в будущем сохраняется.
Важно: хеширование защищает пароли только от компрометации в хранилище данных, но не защищает пароли от перехвата вредоносным кодом, который внедрили в само приложение или службу.
Почему стандартные функции хеширования наподобие md5() и sha1() нельзя использовать для защиты паролей?
Алгоритмы хеширования наподобие MD5, SHA1 и SHA256 спроектировали
быстрыми и эффективными, а данные, которые эти алгоритмы давали на выходе, затрудняли раскрытие паролей.
Но текущие техники и компьютерное оборудование сделали тривиальным перебор вывода этих алгоритмов
методом brute force
(англ. букв. «грубой силы») для определения исходных входных данных.
Из-за скорости, с которой компьютеры научились обращать
эти алгоритмы хеширования, аналитики в области компьютерной безопасности
рекомендуют не использовать эти алгоритмы для хеширования паролей.
Как хешировать пароли, если нельзя использовать стандартные функции?
В хешировании паролей выделяются два самых важных фактора: цена вычисления и соль. Повышение вычислительной сложности алгоритма хеширования увеличивает время, которое потребуется для перебора вывода алгоритма методом «грубой силы».
PHP поддерживает встроенный API-интерфейс хеширования паролей, который безопасно обрабатывает как хеширование, так и проверку паролей.
Пароли рекомендуют хешировать алгоритмом Blowfish, который также применяют по умолчанию в API-интерфейсе хеширования паролей, поскольку этот алгоритм намного затратнее с точки зрения вычислительной сложности, чем алгоритм MD5 или SHA1, но при этом по-прежнему масштабируем.
Функция crypt() также доступна для хеширования паролей, но её рекомендуют только для взаимодействия с другими системами. Вместо этой функции рекомендуют хешировать пароли через встроенный API-интерфейс хеширования паролей, когда возможно.
Что такое соль?
Криптографическая соль — данные, которые участвуют в хешировании и которые исключают поиск вывода, который сгенерировало хеширование, в списке предварительно вычисленных пар хешей и их входных данных, который знают как «радужную» таблицу.
В упрощённой терминологии, соль — фрагмент дополнительных данных, которые серьёзно затрудняют взлом хешей. Интернет наполняют службы, которые содержат открытые списки исходных паролей и хешей, которые заранее вычислили для этих паролей. Соли делает маловероятным или невозможным поиск хеша в таких списках.
Функция password_hash() создаст случайную соль, если её не передали, и часто это доступная и одновременно безопасная защита паролей.
Как хранится соль?
При хешировании паролей функцией password_hash() или других строк функцией crypt() значение, которые возвращают функции, уже содержит соль как часть хеша, который сгенерировали функции. Значение возврата сохраняют как есть, поскольку хеш включает информацию о функции хеширования, а затем без посредников передают в функцию password_verify() при проверке пароля.
Вместо перехеширования и сравнения результата с хешем в хранилище, вызывают функцию password_verify(), чтобы избежать атак по времени.
Следующая диаграмма показывает формат значения, которое возвращают функции crypt() и password_hash(). На диаграмме видно, что значения содержат внутри себя информацию об алгоритме и соли, которая требуется для будущей проверки пароля.