Як може bcrypt має вбудовані солі?


616

У статті Coda Hale "Як безпечно зберігати пароль" стверджується, що:

bcrypt має вбудовані солі для запобігання атак на веселковий стіл.

Він цитує цей документ , в якому йдеться про те, що у впровадженні OpenBSD bcrypt:

OpenBSD генерує 128-бітну криптовалютну сіль з ключового потоку arcfour (arc4random (3)), засіяний випадковими даними, які ядро ​​збирає під час синхронізації пристрою.

Я не розумію, як це може працювати. У моєму розумінні солі:

  • Він повинен бути різним для кожного збереженого пароля, так що для кожного потрібно було б створити окрему таблицю веселки
  • Його потрібно зберігати десь так, щоб це було повторюваним: коли користувач намагається увійти, ми робимо його спробу пароля, повторюємо ту саму процедуру соління, яку ми робили, коли ми зберігали свій пароль, і порівнюємо

Коли я використовую Devise (менеджер входу в Rails) з bcrypt, в базі даних немає соляного стовпця, тому я плутаюся. Якщо сіль є випадковою і ніде не зберігається, то як можна надійно повторити процес перемішування?

Коротше кажучи, як може bcrypt мати вбудовані солі ?

Відповіді:


789

Це bcrypt:

Утворіть випадкову сіль. Коефіцієнт "вартість" попередньо налаштований. Зберіть пароль.

Отримайте ключ шифрування з пароля, використовуючи коефіцієнт солі та вартості. Використовуйте його для шифрування відомого рядка. Зберігайте текст витрат, солі та шифру. Оскільки ці три елементи мають відому довжину, їх легко з’єднати та зберігати в одному полі, але в подальшому їх можна буде розділити.

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

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


Збережений у базі даних bcrypt"хеш" може виглядати приблизно так:

$ 2a $ 10 $ vI8aWBnW3fID.ZQ4 / zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa

Це фактично три поля, розділені на "$":

  • 2aідентифікує використаний bcryptваріант алгоритму.
  • 10- коефіцієнт витрат; 2 10 ітерацій функції виведення ключів використовуються (що, до речі, недостатньо. Я рекомендував би вартість 12 і більше.)
  • vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa- сіль і текст шифру, з'єднані і закодовані в модифікованій Базі-64. Перші 22 символи декодують до 16-байтного значення для солі. Решта символів - це зашифрований текст для порівняння для аутентифікації.

Цей приклад взято з документації для реалізації рубіну Coda Hale.


7
Чи хотіли б ви дізнатися більше про те, чому коефіцієнт витрат 10 не буде достатньо? У Grails я помітив, що 10 - це значення за замовчуванням для раунду коефіцієнта витрат / журналів для bcrypt, тому його, можливо, варто оновити, враховуючи вашу пропозицію.
pm_labs

57
Коефіцієнт витрат на bcrypt є експоненціальним, а точніше, коефіцієнт витрат 10 означає 2 ^ 10 раундів (1024), коефіцієнт витрат 16 означатиме 2 ^ 16 раундів (65536). Це природно, що це займе 5-10 секунд. Це повинно зайняти приблизно 64 рази, ніж коефіцієнт витрат 10. Для очищення інших дезінформацій, криптофункція PHP використовує бібліотеку крипт Unix, реалізовану в c.
thomasrutter

3
@TJChambers Правильно; якщо ви зможете встановити пароль в обліковому записі, ви зможете пройти автентифікацію. Хешування паролем не призначене для запобігання атаці. Він призначений для запобігання зловмиснику з доступом до читання паролів лише для читання. Наприклад, ви отримуєте резервну стрічку з таблицею на ній.
erickson

8
@LobsterMan Ні, не дуже. Якщо ви могли б зберегти таємницю, ви не використовували б такий підхід, ви просто збережете пароль. Схеми аутентифікації паролів ґрунтуються на припущенні, що зловмисник виявив усе, що вам відомо. Сіль є там, щоб вимагати нападу кожного пароля окремо. Обчислювальні зусилля, необхідні для тестування паролів, регулюються ітераціями. Якщо користувачі виберуть хороші паролі, вони будуть захищені, навіть якщо з’явиться сіль. Приховування солі може допомогти комусь із неправильним паролем у деяких випадках, але я спершу працюю над якістю пароля.
еріксон

1
@NLV Це рядок, визначений у специфікації bcrypt:"OrpheanBeholderScryDoubt"
erickson

181

Я вважаю, що ця фраза повинна бути сформульована так:

bcrypt містить солі, вбудовані в генеровані хеші, щоб запобігти атакам райдужної таблиці.

Сама bcryptпрограма не підтримує список солей. Скоріше солі генеруються випадковим чином і додаються до виходу функції, щоб вони запам'яталися згодом (відповідно до реалізації Javabcrypt ). По-іншому, "хеш", що генерується, bcrypt- це не просто хеш. Скоріше, це хеш і сіль з’єднані.


20
Гаразд, тому я підписуюся на сайт і вибираю пароль "foo". Bcryptдодає довільну сіль "akd2! *", в результаті чого "fooakd2! *", яка хешируется і зберігається. Пізніше я намагаюся увійти з паролем "bar". Щоб побачити, чи я прав, потрібно хеш "barakd2! *". Якщо сіль була створена випадковим чином для початку, то як вона знає, як додати її до "бар" перед хешированием і порівнянням?
Натан Лонг

46
@Nathan: bcryptзнає, як витягти сіль назад із створеного результату (який зберігається в базі даних). Коли настає час аутентифікувати, bcryptвідокремлює вихідний вихід на його хеш-сольові компоненти. Компонент солі застосовується до вхідного пароля, введеного користувачем.
Адам Пейнтер

22
Щоб відповісти на коментар Натана Лонга, хороший спосіб думати про це полягає в тому, що солі не повинні бути секретними. Ось чому сіль включена у висновок функції bcrypt як одна з відповідей, зазначених вище. Сіль є для запобігання веселкових таблиць, що містять переліки загальних паролів, або просто грубу силу, тощо ... різних паролів, але хешованих. Без солі хеш для пароля в базі даних A був би таким же, як хеш для пароля в базі даних B. Сіль лише змінює значення хешу, ускладнюючи той, хто вкрав базу даних, щоб розшифрувати (видалити) паролі.
Йосиф Астрахан

11
@Nathan, але чи може зловмисник просто видалити відомі солі з усіх паролів, а потім створити таблицю з ними?
Оскар

3
Ось як я це розумію: ідея полягає в тому, що кожен пароль має унікальну сіль. Сіль, включена в хеш паролів, тому хакер повинен створити таблицю веселки для кожного пароля. Це потребує величезної кількості часу для помірної бази даних. Вся справа в уповільненні зловмисника і, таким чином, безглузді форсування безглуздо.
PVermeer

0

Щоб зробити речі ще більш зрозумілими,

Напрям реєстрації / входу ->

Пароль + сіль шифрується ключем, згенерованим із: вартість, сіль та пароль. ми називаємо це зашифроване значення cipher text. тоді ми додаємо сіль до цього значення і кодуємо її за допомогою base64. прив’язання вартості до нього, і це створена рядок з bcrypt:

$2a$COST$BASE64

Це значення зберігається з часом.

Що потрібно зробити зловмиснику, щоб знайти пароль? (інший напрямок <-)

Якщо зловмисник отримав контроль над БД, зловмисник легко декодує значення base64, і тоді він зможе побачити сіль. сіль не є секретом. хоча це випадково. Тоді йому потрібно буде розшифрувати cipher text.

Що важливіше: у цьому процесі немає хешування, скоріше дороге шифрування процесора - дешифрування. таким чином, таблиці веселки тут менш актуальні.


-2

Це з документації щодо інтерфейсу PasswordEncoder від Spring Security,

 * @param rawPassword the raw password to encode and match
 * @param encodedPassword the encoded password from storage to compare with
 * @return true if the raw password, after encoding, matches the encoded password from
 * storage
 */
boolean matches(CharSequence rawPassword, String encodedPassword);

Це означає, що потрібно буде відповідати rawPassword, який користувач введе знову при наступному вході в систему і співставить його з кодованим паролем Bcrypt, який зберігається в базі даних під час попереднього входу / реєстрації.


Це взагалі не відповідає на питання ... Це нічого не говорить про те, як bcrypt може мати вбудовані солі
spencer.sm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.