Безопасное и надежное хеширование паролей

Раздел объясняет, почему пароли защищают функциями хеширования, и как захешировать пароль так, чтобы его было трудно раскрыть.

Почему требуется хешировать пароли пользователей?

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

Алгоритм, который применяют для хеширования паролей пользователей перед сохранением, серьёзно затрудняет раскрытие исходного пароля злоумышленником, при этом доступ к сравнению хеша с исходным паролем в будущем сохраняется.

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

Почему стандартные функции хеширования наподобие 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(). На диаграмме видно, что значения содержат внутри себя информацию об алгоритме и соли, которая требуется для будущей проверки пароля.


        Компоненты значения, которое возвращают функции password_hash и crypt, идут в следующем порядке:
        алгоритм хеширования, опции алгоритма, соль и хеш пароля.