Какой тип столбца/длину следует использовать для хранения пароля Bcrypt в базе данных?

Я хочу сохранить хешированный пароль (используя BCrypt) в базе данных. Какой был бы хороший тип для этого, и какая была бы правильная длина? Являются ли пароли хэшированными с BCrypt всегда одинаковой длины?

ИЗМЕНИТЬ

Пример хеша:

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

После хэширования некоторых паролей кажется, что BCrypt всегда генерирует 60 символьных хэшей.

РЕДАКТИРОВАТЬ 2

Извините, что не упоминал о реализации. Я использую jBCrypt.

Ответ 1

Формат модульного склепа для bcrypt состоит из

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

Таким образом, общая длина составляет 59 или 60 байт соответственно.

Как вы используете формат 2a, вам понадобится 60 байт. И поэтому для MySQL Ill рекомендуем использовать CHAR(60) BINARY или BINARY(60) (см. _bin и двоичные сортировки для получения информации о различии).

CHAR не является бинарным безопасным, и равенство не зависит только от значения байта, а от фактического сопоставления; в худшем случае A считается равным A. Подробнее см. _bin и binary Collations.

Ответ 2

Атрибут Bcrypt может храниться в столбце BINARY(40).

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

Хэши Bcrypt следуют структуре, называемой модульным склепом (MCF). Двоичный MCF (BMCF) декодирует эти текстовые представления хеширования в более компактную двоичную структуру. В случае Bcrypt результирующий двоичный хэш составляет 40 байт.

Gumbo отлично справился с объяснением четырех компонентов хэша MCC Bcrypt:

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

Декодирование в BMCF происходит следующим образом:

  • $<id>$ может быть представлен в 3 битах.
  • <cost>$, 04-31, может быть представлена ​​в 5 бит. Поместите их вместе для 1 байт.
  • 22-символьная соль представляет собой (нестандартное) представление base-64 из 128 бит. Базовое 64-битное кодирование дает 16 байт.
  • 31-символьный хэш-дайджест может быть декодирован в base-64 до 23 байтов.
  • Объедините все это в 40 байт: 1 + 16 + 23

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

Ответ 3

Я не думаю, что есть какие-то аккуратные трюки, которые вы можете сохранить, поскольку вы можете сделать это, например, с хешем MD5.

Я думаю, ваш лучший выбор - сохранить его как CHAR(60), поскольку он всегда длиннее 60 символов

Ответ 4

Если вы используете PHP password_hash() с помощью алгоритма PASSWORD_DEFAULT для генерации хэша bcrypt (который я бы предположил, это большой процент людей, читающих этот вопрос ) обязательно помните, что в будущем password_hash() может использовать другой алгоритм по умолчанию, и поэтому это может повлиять на длину хэша (но это может быть не обязательно больше).

На странице руководства:

Обратите внимание, что эта константа предназначена для изменения со временем как новых, так и более сильные алгоритмы добавляются в PHP. По этой причине длина результат использования этого идентификатора может меняться со временем. Следовательно, рекомендуется сохранить результат в столбце базы данных, который может разверните более 60 символов (255 символов будут хорошим выбором).

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