Як Devise захищає паролі додатків Rails

Devise - неймовірне рішення для автентифікації Rails, яке завантажує понад 40 мільйонів. Однак, оскільки він абстрагується від більшості криптографічних операцій, не завжди легко зрозуміти, що відбувається за лаштунками.

Одна з цих абстракцій завершується збереженням encrypted_passwordбезпосередньо в базі даних. Тому мені завжди було цікаво, що це насправді представляє. Ось приклад:

$2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO

Але що означає цей тупік?

Devise використовує Bcrypt для надійного зберігання інформації. На своєму веб-сайті він згадує, що використовує « алгоритм хешування паролів OpenBSD bcrypt (), що дозволяє легко зберігати безпечний хеш паролів користувачів ». Але що саме це за хеш? Як це працює і як захищає збережені паролі?

Це те, що я хочу вам сьогодні показати.

Давайте працюватимемо назад - від збереженого хешу у вашій базі даних до процесу шифрування та дешифрування.

Цей хеш $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yOнасправді складається з декількох компонентів:

  • Bcrypt version ( 2a) - версія алгоритму bcrypt (), що використовується для створення цього хешу (зберігається після першого $знака)
  • Cost ( 11) - коефіцієнт витрат, який використовується для створення хешу (зберігається після другого $знака)
  • Salt ( $2a$11$yMMbLgN9uY6J3LhorfU9iu) - випадковий рядок, який у поєднанні з вашим паролем робить його унікальним (перші 29 символів)
  • Контрольна сума ( LAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO) - фактична хеш-частина збереженого encrypted_password(рядок, що залишився після 29 символів)

Давайте вивчимо останні 3 параметри:

  • При використанні Devise Costзначення встановлюється змінною класу, яка називається stretch, а значення за замовчуванням - 11. Він визначає кількість випадків хешування пароля. ( У вашому ініціалізаторі devise.rb ви можете налаштувати це значення на нижче значення для тестового середовища, щоб ваш пакет тестів працював швидше. ) *
  • Сіль є випадковою рядком , використовуваної для об'єднання з вихідним паролем. Саме це робить один і той же пароль різними значеннями при зберіганні в зашифрованому вигляді. ( Докладніше про те, чому це важливо, і про те, що таке атаки Rainbow Table, див. Нижче .) **
  • Контрольна сума - це фактично генерований хеш пароля після поєднання із випадковою сіллю.

Коли користувач реєструється у вашому додатку, він повинен встановити пароль. Перш ніж цей пароль зберігатиметься в базі даних, за допомогою BCrypt :: Engine.generate_salt (вартість) генерується випадкова сіль, беручи до уваги раніше згаданий фактор витрат. (Примітка: якщо встановлено pepperзначення змінної класу, воно додасть своє значення до пароля перед тим, як солити його.)

З цією сіллю (наприклад $2a$11$yMMbLgN9uY6J3LhorfU9iu, що включає коефіцієнт витрат) він викличе BCrypt :: Engine.hash_secret (пароль, сіль), який обчислює остаточний хеш, який слід зберегти, використовуючи згенеровану сіль і пароль, обраний користувачем. Цей остаточний хеш (наприклад, $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO), у свою чергу, буде збережений у encrypted_passwordстовпці бази даних.

Але якщо цей хеш незворотній і сіль випадково генерується під час BCrypt::Password.createдзвінка BCrypt::Engine.generate_salt(cost), як можна використовувати його для входу в систему?

Ось де ці різні хеш-компоненти корисні. Після знаходження запису, який відповідає електронному листу, наданому користувачем для входу, зашифрований пароль отримується та розбивається на різні компоненти, згадані вище ( версія Bcrypt , вартість , сіль та контрольна сума ).

Після цієї початкової підготовки, ось що буде далі:

  1. Отримати вхідний пароль ( 1234)
  2. Отримати сіль збереженого пароля ( $2a$11$yMMbLgN9uY6J3LhorfU9iu)
  3. Згенеруйте хеш із пароля та солі, використовуючи ту саму версію bcrypt та коефіцієнт вартості ( BCrypt::Engine.hash_secret(“1234”, “$2a$11$yMMbLgN9uY6J3LhorfU9iu”))
  4. Перевірте, чи збережений хеш такий самий, як обчислений на кроці 3 ( $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO)

І ось як Devise надійно зберігає паролі та захищає вас від ряду атак, навіть якщо ваша база даних порушена.

Зв’яжіться у Twitter @alvesjtiago та повідомте мене, якщо вам сподобалась ця стаття! Дякую за читання.

PS: Я ні в якому разі не фахівець з безпеки та криптографії, тому, будь ласка, зверніться, якщо виявите щось не так. Я сподіваюся, що спростивши деякі концепції, буде легше зрозуміти, що відбувається.

Дякуємо @filipepina, @ivobenedito, @jackveiga, @joao_mags та @pedrosmmoreira за огляди та пропозиції. Ця стаття також доступна за адресою //blog.tiagoalves.me/how-does-devise-keep-your-passwords-safe.

Більше інформації про деякі теми.

Фактор витрат *

  • Ризики коефіцієнта вартості bcrypt за замовчуванням
  • Рекомендована кількість раундів для bcrypt

Напади на райдужний стіл **

  • Веселковий стіл - Вікіпедія
  • Що таке райдужні столи і як вони використовуються?