Какой тип столбца/длину следует использовать для хранения пароля 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. Если алгоритм по умолчанию когда-либо изменен, было бы хорошо проанализировать, почему и принять обоснованное решение о том, использовать ли новый алгоритм или нет.