
Тьяго Алвес

Devise – это невероятное решение для аутентификации для Rails с более чем 40 миллионами загрузок. Однако, поскольку он абстрагирует большинство криптографических операций, не всегда легко понять, что происходит за кулисами.
Одна из этих абстракций завершается устойчивостью. encrypted_password
непосредственно в базе данных Поэтому мне всегда было интересно, что это действительно означает. Вот пример:
$2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO
Но что значит эта ложь?
Devise использует Bcrypt для безопасного хранения информации. На своем веб-сайте он упоминает, что используетАлгоритм хеширования паролей OpenBSD bcrypt(), позволяющий легко сохранять безопасный хеш паролей ваших пользователей”. Но что это за хэш? Как это работает и как обеспечивает безопасность хранимых паролей?
Вот что я хочу вам сегодня показать.
Давайте поработаем назад – от сохраненного хеша в вашей базе данных до процесса шифрования и дешифрования.
Этот хэш $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO
на самом деле состоит из нескольких компонентов:
- Версия Bcrypt (
2a
) — версия алгоритма bcrypt(), используемого для создания этого хеша (хранится после первого$
знак) - Стоимость (
11
) – коэффициент стоимости, использованный для создания хэша (хранится после второго$
знак) - соль (
$2a$11$yMMbLgN9uY6J3LhorfU9iu
) — случайная строка, которая в сочетании с вашим паролем делает его уникальной (первые 29 символов) - контрольная сумма (
LAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO
) – фактическая часть сохраненного хэшаencrypted_password
(строка, оставшаяся после 29 символов)

Давайте исследуем последние 3 параметра:
- При использовании Devise,
Cost
значение устанавливается переменной класса, которая называется stretches, а значение по умолчанию – это11
. Он определяет количество раз хеширования пароля. (В вашем инициализаторе devise.rb вы можете настроить это на ниже значение для тестовой среды, чтобы сделать ваш набор тестов более быстрым.) * - The соль это случайная строка, используемая для сочетания с оригинальным паролем. Именно поэтому один и тот же пароль имеет разные значения при хранении в зашифрованном виде. (Смотрите ниже о том, почему это важно и что такое Rainbow Table Attackс.) **
- The контрольная сумма – это фактически сгенерированный хэш пароля после сочетания со случайной солью.
Когда пользователь регистрируется в вашем приложении, он должен установить пароль. Прежде чем этот пароль будет сохранен в базе данных, случайная соль генерируется через BCrypt::Engine.generate_salt(cost) с учетом вышеупомянутого фактора стоимости. (Примечание: если pepper
значение переменной класса установлено, оно прибавит свое значение к паролю, прежде чем его подсаливать.)
С этой солью (напр. $2a$11$yMMbLgN9uY6J3LhorfU9iu
, который включает коэффициент стоимости), он вызовет BCrypt::Engine.hash_secret(password, salt), который вычисляет окончательный хэш, который будет сохранен с помощью сгенерированной соли и пароля, выбранного пользователем. Этот окончательный хэш (например, $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO
) в свою очередь будет храниться в encrypted_password
столбец базы данных.

Но если этот хеш необратим и соль генерируется случайным образом на BCrypt::Password.create
позвонить BCrypt::Engine.generate_salt(cost)
, как его можно использовать для пользовательского входа?
Вот где полезны разные хэш-компоненты. После нахождения записи, соответствующей электронной почте, предоставленной пользователем для входа, зашифрованный пароль извлекается и разбивается на различные компоненты, упомянутые выше (Версия Bcrypt, Стоимость, соль и контрольная сумма).
После этой начальной подготовки следующее:
- Убрать введите пароль (
1234
) - Убрать соль сохраненного пароля (
$2a$11$yMMbLgN9uY6J3LhorfU9iu
) - Сгенерировать хеш с пароля и соли, используя ту же версию bcrypt и коэффициент стоимости (
BCrypt::Engine.hash_secret(“1234”, “$2a$11$yMMbLgN9uY6J3LhorfU9iu”)
) - Убедитесь, что сохраненный хэш является таким же, как и вычисленное на шаге 3 (
$2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO
)

И именно так Devise надежно хранит пароли и защищает вас от ряда атак даже если ваша база данных сломана.
Свяжитесь с нами в Twitter @alvesjtiago и сообщите мне, была ли вам интересна эта статья! Спасибо, что читаете.

PS: Я отнюдь не эксперт по безопасности или криптографии, поэтому, пожалуйста, свяжитесь с нами, если вы обнаружите что-нибудь не так. Я надеюсь, что упростив некоторые понятия, будет легче понять, что происходит.
Спасибо @filipepina, @ivobenedito, @jackveiga, @joao_mags и @pedrosmmoreira за отзывы и предложения. Эта статья также доступна на сайте http://blog.tiagoalves.me/how-does-devise-keep-your-passwords-safe.
Больше информации о некоторых темах.
Фактор затрат*
Атаки Rainbow Table **