@StynuBlizz

Как лучше всего шифровать пароли для сохранения в БД?

Как нужно обработать пароль перед тем как положить его в БД?
  • Вопрос задан
  • 2284 просмотра
Решения вопроса 1
Tyranron
@Tyranron
Чтобы лучше понять "как" и "почему", для начала следует сформулировать задачу и рассмотреть пути решения.

Задача состоит в том, чтобы иметь возможность проверить подлинность секретного параметра пользователя, не храня у себя его, и не давая злоумышленнику возможности узнать этот самый секретный пароль.

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

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

Давайте поставим теперь себя на место злоумышленника. Располагая всем этим, как бы мы взламывали пароль?
1. Радужные таблицы (заранее сгенерированные таблицы "хэш -> значение").
2. Атака по словарю (сначала делается перебор по наиболее вероятным значениям).
3. Полный перебор.
Полный перебор хоть и решит задачу 100%, но это крайняя мера, крайне неэффективная, и, как правило, не рабочая, потому что пусть пароль и можно подобрать за десятки тысяч лет, злоумышленник столько не проживет (как и сама взламываемая система, и сам пользователь). Потому если мы обезопасились от пунктов 1 и 2 кое-как, то задачу, считай, решили.

Если мы просто возьмем какую-то хэш-функцию (например, sha256) и захэшируем пароль, то сделаем очень плохо. Почему? Потому что злоумышленник, видя это, просто возьмет хэш и подставит в радужную таблицу, и, если пользователь не заморачивался с паролем (а как правило так и есть), то пароль будет получен практически сразу.

Что нужно сделать, дабы исключить вариант использования радужных таблиц?
Сделать так, чтобы значения, подаваемые на вход хэш-функции, гарантированно в них отсутствовали. Для этого и придумали соль. В связи с этим к соли есть одно простое требование: соль должна быть сложно угадываемой.
То есть, если у нас есть пароль "password" и соль "111", то вероятность попадания строки "password111" в радужную таблицу все ещё очень высока, а значит подобная соль плохая. А вот соль "t%Lp-,DU4=w],9c7F.N$" хороша, потому что строку "passwordt%Lp-,DU4=w],9c7F.N$" в радужную таблицу никто записывать не будет.
Вывод: нам нужна соль для того, чтобы исключить поиск по хэшу в радужных таблицах.

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

Далее в арсенале злоумышленника остается атака по словарю.
Увы, полностью исключить данный вариант может только пользователь, если будет использовать стойкие и сложные к угадыванию пароли, у которых вероятность попадания в словари "крайне мала"(с).
Но на благоразумие всех пользователей надеятся не стоит, а обезопасить их как-то надо. И здесь у нас остается возможность "вставить палку в колесо" злоумышленнику, увеличив время выполнения алгоритма. То есть просто берем и хэшируем результат повторно надцать раз, пока время выполнения алгоритма не станет достаточно длинным, например, 500ms. Нам при аутентификации пользователя (да и самому пользователю) 500ms ждать не проблема, а вот злоумышленнику делать подбор пароля со скоростью 2 пароля за секунду, уже "ой-какая-головная-боль".
Вывод: повторяем хэширование много раз, дабы увеличить время выполнения алгоритма, что замедлит подбор паролей.

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

Дабы реализовать все вышесказанное, к велосипеду ручонки тянуть не нужно, именно из-за вышеуказанных "заморочек" в деталях алгоритмов. Криптография дилетанства не прощает. Тем более, что уже есть де-факто промышленные стандарты.
Например, bcrypt алгоритм (спасибо kpa6uu за упоминание). В PHP он реализован посредством стандартной password_hash() функции. В других языках тоже хватает реализаций.

Ну и наконец-то отвечая на Ваш вопрос "как лучше всего?", то на данный момент это алгоритм Argon2, победитель последнего Password Hashing Competition. С реализациями в языках, к сожалению, пока что не так все радужно как у bcrypt.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
kpa6uu
@kpa6uu
Программист Талибана [Пыхерский Алибаба]
Юзайте bcrypt.
Ответ написан
Комментировать
Godless
@Godless
В каждом случае свое. Смысл в том, чтоб не могли получить пароль, зная то, что в бд.
Я думаю, что соль + шифрование по RSA с хэшем вас спасет. Ключи RSA ессно хранить бережно...
Ответ написан
dom1n1k
@dom1n1k
Пароли не шифруются, пароли хэшируются. Очень желательно с солью.
Соль может быть одинаковой для всех (даже в таком виде это гораздо лучше, чем без соли совсем) или переменной (зависящая, например, от даты регистрации).
Базово-приемлемый уровень хэша - SHA-256, бОльшая длина приветствуется.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы