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

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

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

Пример хэша:

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

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

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

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

5 ответов

Решение

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

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

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

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

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

Хеш Bcrypt может храниться в BINARY(40) колонка.

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

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

Гамбо хорошо объяснил четыре компонента хеша Bcrypt MCF:

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

Декодирование в BMCF происходит так:

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

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

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

Со страницы руководства:

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

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

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

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

Я думаю, что лучший выбор - небинарный тип, потому что по сравнению с ним меньше комбинаций и он должен быть быстрее. Если данные закодированы с помощью base64_encode, то каждая позиция, каждый байт имеют только 64 возможных значения. При кодировании с помощью bin2hex каждый байт имеет только 16 возможных значений, но строка намного длиннее. В двоичном байте по 256 позиций на каждый. Я использую для хэшей в виде столбца encode64 VARCHAR(255) с набором символов ascii и тем же сопоставлением. VARBINARY вызывает проблему сравнения, как описано в документации MySQL. Я не знаю, почему ответы на советы по использованию VARBINARY имеют так много положительных сторон. Я проверил это на своем авторском сайте, где измеряю время (просто обновите, чтобы увидеть).

Другие вопросы по тегам