Зачем нужны медленные функции
Обычные хеш-функции считаются очень быстро, поэтому злоумышленник с украденной базой хешей может пробовать миллиарды вариантов в секунду. Специальные функции для паролей замедляют вычисление намеренно и позволяют настраивать нагрузку, чтобы её можно было повышать по мере роста мощности оборудования.
bcrypt и Argon2 — два широко известных представителя. Оба содержат соль и параметры нагрузки, а результат хранится вместе с ними, так что проверка при входе проста.
Как устроен bcrypt
bcrypt существует с конца девяностых и основан на шифре Blowfish. Параметр нагрузки управляет числом итераций: каждое увеличение вдвое удлиняет вычисление. Он хорошо изучен, доступен практически во всех языках и фреймворках, поэтому часто выбирается как надёжный и предсказуемый вариант.
У него есть особенности: ограничение на длину пароля, при превышении которого хвост игнорируется, и небольшое потребление памяти. Последнее делает его менее устойчивым к атакам на специализированном оборудовании с массовым параллелизмом.
Как устроен Argon2
Argon2 победил в конкурсе по хешированию паролей и относится к более новому поколению. Его главное свойство: он требует не только времени, но и заданного объёма памяти, а также позволяет настраивать степень параллелизма. Это усложняет атаки на видеокартах и специализированных чипах, где память ограничена.
Существует несколько вариантов, из которых чаще рекомендуют вариант, сочетающий устойчивость к разным типам атак. Параметры (память, число проходов, параллелизм) нужно подбирать под ваш сервер.
Ограничения и подводные камни
У Argon2 больше настроек, а значит, выше риск ошибки: слишком малые параметры сводят выгоду к нулю, слишком большие создают нагрузку на сервер и открывают путь к отказу в обслуживании при массовых попытках входа. Реализации в разных библиотеках могут отличаться по зрелости.
У bcrypt слабее защита от аппаратного перебора, но он проще и стабильнее. Оба варианта не спасают от слабых паролей и не заменяют ограничения на число попыток и двухфакторную защиту.
Как подобрать параметры для своего сервера
Универсальных чисел не существует, поэтому параметры нужно измерять. Ориентир такой: одна проверка пароля должна занимать заметное, но приемлемое время, обычно доли секунды, и при этом сервер должен выдерживать ожидаемое число одновременных входов. Запустите тест на реальном оборудовании и постепенно увеличивайте нагрузку, пока время не приблизится к выбранной границе.
Для Argon2 настраивают объём памяти, число проходов и степень параллелизма. Сначала выберите объём памяти, который вы можете себе позволить на каждый одновременный вход, затем подберите число проходов. Для bcrypt настраивается единственный параметр, показатель нагрузки, и его подбирают тем же способом.
Учтите пиковые нагрузки. Если в момент массового входа сервер начнёт задыхаться, атакующий получит способ вывести его из строя обычными запросами. Против этого помогают ограничение числа попыток, очередь проверок и отдельные ресурсы на авторизацию.
Сохраняйте параметры вместе с хешем и пересматривайте их раз в год-два. При входе пользователя, у которого хеш создан по устаревшим параметрам, пересчитывайте его заново: пароль в этот момент доступен, а перенос происходит незаметно.
Рекомендация без догм
Для нового проекта, где доступна проверенная библиотека, обычно выбирают Argon2 с параметрами, подобранными под нагрузку, и оставляют возможность повышать их. Если платформа или команда работает с bcrypt и зависимость уже проверена, продолжать использовать его допустимо: он остаётся приемлемым при достаточной нагрузке.
В любом случае не пишите реализацию сами, храните параметры вместе с хешем, чтобы позднее можно было перехешировать пароль при входе пользователя, и периодически пересматривайте параметры.
Резюме: оба алгоритма подходят для хранения паролей, Argon2 надёжнее против аппаратного перебора, bcrypt проще и хорошо проверен. Подбирайте параметры измерением, храните их вместе с хешем, пересчитывайте хеши при входе и дополняйте защиту ограничением попыток и двухфакторной проверкой для учётных записей.
Не забывайте и о защите самой базы: ограничьте сетевой доступ, шифруйте резервные копии, отделите права приложения от прав администратора. Стойкий хеш замедляет злоумышленника, но не должен быть единственным барьером.