Який тип / довжину стовпця я повинен використовувати для зберігання хешованого пароля Bcrypt у базі даних?


317

Я хочу зберігати хешований пароль (за допомогою BCrypt) у базі даних. Який був би хороший тип для цього, а яка була б правильна довжина? Чи завжди хешовані паролі з BCrypt завжди однакової довжини?

EDIT

Приклад хешу:

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

Після хешування деяких паролів, здається, що BCrypt завжди генерує 60 хешів символів.

EDIT 2

Вибачте, що не згадуєте про реалізацію. Я використовую jBCrypt .


Також дивіться рамку хешування паролів PHP Openwall (PHPass). Його портативний та загартований проти низки поширених атак на паролі користувачів. Хлопець, який написав рамки (SolarDesigner) - той самий хлопець, який написав Джона The Ripper і сидить як суддя у змаганнях з пароля . Тож він знає річ чи дві про атаки на паролі.
jww

1
Якщо хтось потрапляє на це, шукаючи рішення для скрипту : відповідь Gumbo також стосується scrypt. Я особисто застосував BINARY (64) в MySQL, і це дозволило мені перевірити рівність байтів під Python пізніше.
Філіп Геберт

Відповіді:


368

Модульний формат крипт для bcrypt складається з

  • $2$, $2a$Або $2y$ідентифікації алгоритму хешування і формат
  • двозначне значення, що позначає параметр вартості, за яким слідує $
  • 53 - символів базового 64-кодоване значення (вони використовують алфавіт ., /, 0- 9,A - Z, a- , zщо відрізняється від стандартної бази 64 кодування алфавіту) , що складається з:
    • 22 символи солі (фактично лише 128 біт із 132 розшифрованих шматочків)
    • 31 символ зашифрованого виводу (фактично лише 184 біти з 186 розшифрованих бітів)

Таким чином, загальна довжина становить 59 або 60 байт відповідно.

Під час використання формату 2a вам знадобиться 60 байт. Таким чином, для MySQL я рекомендую використовувати CHAR(60) BINARYабоBINARY(60) ( для інформації про різницю див . _Bin та бінарні Collations ).

CHARне є бінарним безпечним і рівність не залежить тільки від байтового значення, але і від фактичного зіставлення; в гіршому випадку Aтрактується як рівний a. Див і Collations для отримання додаткової інформації._binbinary


28
Будьте в курсі - зберігання як бінарного (60) може спричинити несподівану поведінку для рівності рядків (серед іншого). У .NET це можна подолати, використовуючи String.Equals (відDataBaseBinary60string, typishString, StringComppare.InvariantCulture)
JHubbard80

8
Якщо ви визначите стовпець як CHAR (60) CHARACTER SET latin1 COLLATE latin1_bin, тепер ви отримаєте переваги точного порівняння рядків без необхідності двійкового стовпця.
Бен

2
@AndreFigueiredo SQL_Latin1_General_CP1_CS_ASневідомий у MySQL. Що відомо - це latin1_general_cs.
Гумбо

1
Я хотів би мати визначення тут для того, що 2, 2aі 2yсереднього значення для алгоритму хешування і формату. Я не міг знайти просту відповідь при пошуку.
jocull

2
@Neon Проблема полягає в тому, що ви можете порівняти різні хеші, щоб бути рівними. Якщо ви чітко вказуєте, що це двійковий стовпець (або VARCHAR з правильним порівнянням), ви не ризикуєте десь іншим чином змінити налаштування, що робить його порівняльним з урахуванням регістру. Це також робить ваш намір більш зрозумілим, що, як правило, добре - ви зберігаєте бінарні дані; ви повинні зберігати його як двійкові дані.
Фонд позову Моніки

51

Хеш-код Bcrypt може зберігатися у BINARY(40)стовпці.

BINARY(60), як підказують інші відповіді, - це найпростіший і найприродніший вибір, але якщо ви хочете досягти максимальної ефективності зберігання, ви можете заощадити 20 байт, без втрат деконструюючи хеш. Я детальніше це задокументував у GitHub: https://github.com/ademarre/binary-mcf

Хеши криптовалют слідують за структурою, що називається модульним форматом крипт (MCF). Двійкові MCF (BMCF) декодує ці текстові хеш-подання до більш компактної бінарної структури. У випадку Bcrypt отриманий бінарний хеш становить 40 байт.

Gumbo зробив гарну роботу, пояснивши чотири компоненти хеша Bcrypt MCF:

$<id>$<cost>$<salt><digest>

Розшифровка до BMCF відбувається так:

  1. $<id>$ може бути представлений у 3 бітах.
  2. <cost>$, 04-31, можна представити у 5 бітах. Складіть їх разом на 1 байт.
  3. Сіль з 22 символами є (нестандартним) базовим 64-представленням 128 біт. Розшифровка Base-64 дає 16 байт.
  4. 31-символьний хеш-дайджест може бути базовим - 64 декодовані до 23 байтів.
  5. Зберіть все це на 40 байт: 1 + 16 + 23

Ви можете прочитати більше за посиланням вище або переглянути мою реалізацію PHP , також на GitHub.


49
Вартість більш тривалого поля: 20 байт - це навіть мільйон + записів: 20 МБ, як тільки ви досягнете мільйона записів +. Витрати на неналежне впровадження скороченої довжини поля у надзвичайно складній галузі безпеки та техніки: $$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$ Ви зробите математику.
Kzqai

6
@Kzqai, як я вже сказав, більший 60-байтовий стовпчик - це найприродніший вибір, але наскільки агресивно досягати ефективності зберігання залежить проект. Наприклад, прийнято намагатися помістити всю базу даних в пам'ять, і 20 МБ тут і ще 20 там можуть швидко додаватися в обмеженому пам'яті середовищі.
Андре Д

10
Ваш приклад пояснює мою думку. --- Якщо ви хочете помістити свою базу даних у пам'ять, оптимізуйте кожен інший стовпець, перш ніж торкатися стовпця накопичувача bcrypt. --- Якщо ви оптимізували кожен інший стовпець до божевільних градусів, а залишився лише хеш-колона bcrypt, отримайте ще один гіг пам'яті лише для bcrypt. --- Якщо ви зробили обидва вище ... це з більш складною системою, вирощеною в домашніх умовах, імовірність невдачі в реалізації
Kzqai

11
@Kzqai Тут немає ризику послабити безпеку вашої бібліотеки Bcrypt. Це кодування даних, яке скасовується при отриманні зі сховища до перевірки пароля. Це не "не котиться власна криптовалюта" територія.
Андре Д

1
Приємне пояснення. :) Хоча ваше пояснення дало чудову ідею, я просто хочу пройти з 60 символами, навіть 100 символами, просто щоб бути в безпеці. Приємна дискусія також @Kzqai та AndreD
Naveen Kumar V

23

Якщо ви використовуєте PHP password_hash()з PASSWORD_DEFAULTалгоритмом для генерування хеш-файлів bcrypt (я вважаю, що це великий відсоток людей, які читають це запитання), не забудьте пам’ятати, що в майбутньому password_hash()може використовуватися інший алгоритм як за замовчуванням, і це може тому впливають на довжину хешу (але це може бути не обов'язково довше).

З сторінки керівництва:

Зауважте, що ця константа призначена для того, щоб змінюватись з часом, оскільки до PHP додаються нові і сильніші алгоритми. З цієї причини тривалість результату від використання цього ідентифікатора може змінюватися з часом. Тому рекомендується зберігати результат у стовпці бази даних, яка може розширюватися за рамки 60 символів (255 символів було б хорошим вибором).

Використовуючи bcrypt, навіть якщо у вас є 1 мільярд користувачів (тобто ви зараз змагаєтесь з facebook) для зберігання 255 байтових хешей паролів, це буде лише ~ 255 ГБ даних - приблизно розміром невеликого жорсткого диска SSD. Надзвичайно малоймовірно, що зберігання хеша пароля буде вузьким місцем у вашій програмі. Однак, з випадковою можливістю, що місце для зберігання дійсно є проблемою з якихось причин, ви можете PASSWORD_BCRYPTзмусити password_hash()використовувати bcrypt, навіть якщо це не за замовчуванням. Просто не забудьте бути в курсі будь-яких уразливостей, виявлених у bcrypt, та переглядайте нотатки до випуску щоразу, коли виходить нова версія PHP. Якщо алгоритм за замовчуванням колись змінюється, було б добре переглянути, чому і прийняти обгрунтоване рішення, використовувати новий алгоритм чи ні.


20

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

Я думаю, що найкраще зробити це - зберігати його так, CHAR(60)як це завжди 60 символів


Хоча, в документації PHP зазначається, що стовпці повинні мати можливість зберігати більше даних для майбутніх випусків ...
Julian F. Weinert

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