Программирование
Как правильно хранить пароли в базе данных
В этой статье я объясню, как хранить пароли просто и правильно.
Сохранение паролей пользователей в базе данных — обычное дело, но не каждый разработчик делает это правильно. Например, в сегодняшнем code review я обнаружил, что пароли хранятся в виде обычного текста. Когда я спросил разработчика, в чем опасность такого сохранения, он быстро осознал проблему и поинтересовался, было бы решением их зашифровать. Я ответил: «Нет».
В этой статье я объясню, как хранить пароли правильно и просто. Давайте начнем.
Сохранение паролей
Хранить пароль в виде обычного текста — ужасная идея, но хранить его в зашифрованном виде с использованием двустороннего алгоритма также плохо.
Почему? Потому что, если мы зашифруем и сохраним пароль с помощью ключа шифрования и алгоритма, который позволяет нам зашифровать пароль и расшифровать его с помощью этого ключа, любой, у кого есть ключ шифрования, сможет его расшифровать.
Итак, как правильно это сделать?
В большинстве случаев правильным решением является сохранение хеша пароля в базе данных.
Для этого вы должны хешировать пароль, используя различную соль для каждого пользователя, используя односторонний алгоритм, и сохранить результат, удалив исходный пароль. Затем, когда вы хотите проверить пароль, вы снова хешируете пароль из обычного текста, используя тот же алгоритм хеширования и ту же соль, и сравниваете его с хешированным сохраненным значением в базе данных.
Хорошо, но что вы имеете в виду, говоря «используя разные соли для каждого пользователя»?
Соль — это случайные данные, используемые в качестве дополнительных входных данных для одностороннего алгоритма хеширования. Исторически в системе хранилась только криптографическая хеш-функция пароля, но со временем были разработаны дополнительные меры безопасности для защиты от идентифицируемых общих или повторяющихся паролей.
Давайте посмотрим на практику.
Представим, что у нас есть таблица в базе данных для хранения пользователей моего приложения. В этой таблице есть следующие поля, которые мы будем использовать для хранения имени пользователя и пароля:
Следующим шагом является создание уникальной соли для каждого пользователя каждый раз, когда мы создаем пользователя в этой таблице. Для этого я определю класс с методом, который будет генерировать соль. Выполнение этого с использованием любого другого языка программирования аналогично.
- В строке 7 мы определяем длину соли.
- В строке 11 мы создаем экземпляр класса SecureRandom. Этот класс предоставляет криптографически стойкий генератор случайных чисел, предоставляемый JDK (для других языков у нас есть аналогичные библиотеки).
- В строке 16 мы создаем значение соли, а затем возвращаем строку Base64.
Когда у нас есть соль для пользователя, следующим шагом будет хеширование пароля в виде обычного текста с использованием этой соли. Для этого мы собираемся добавить в наш класс метод под названием hashThePlainTextPassword:
- В строке 10 мы указываем итерации и длину PBEKey.
- В строке 13 мы получаем экземпляр SecretKeyFactory.
- В строке 14 мы генерируем секретный ключ.
- В строке 15 мы возвращаем хешированный пароль в строке Base64.
После того, как мы добавили соль к нашему паролю, мы можем сохранить его хеш в таблице пользователя вместе с солью. Обратите внимание, что при использовании одностороннего алгоритма для декодирования пароля мы никогда не узнаем исходное значение пароля в виде обычного текста. Таким образом, даже если вы получите соль пользователя, если вы не знаете исходный пароль в виде открытого текста, вы никогда не сгенерируете тот же хеш.
Итак, как я могу узнать, правильный ли пароль?
Очень просто. Если мы хотим проверить пароль, мы снова хэшируем значение (используя тот же алгоритм хеширования и соль) и сравниваем его с хешированным значением пользователя в базе данных.
Для этого мы собираемся добавить в наш класс метод под названием verifyThePlainTextPassword. Этот метод хеширует открытый текстовый пароль с исходным соленым значением. Теперь, если сохраненное значение в базе данных и сгенерированное хеш-значение идентичны, значит пароль правильный.
Все вместе
Вывод
Как видите, правильно сохранить пароли в базе данных просто, а правильное их хранение позволит избежать многих проблем.
Надеюсь, эта статья оказалась для вас полезной.