Хэш BCrypt string выглядит следующим образом:
$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm
\__/\/ \____________________/\_____________________________/
| | Salt Hash
| Cost
Version
Где
2a
: Идентификатор алгоритма (BCrypt, пароль в кодировке UTF8, завершенный нулем)
10
: коэффициент стоимости (210
= 1024 раунда)
Ro0CUfOqk6cXEKf3dyaM7O
: Соль в кодировке OpenBSD-Base64 (22 символа, 16 байт)
hSCvnwM9s4wIX9JeLapehKK5YdLxKcm
: Хэш в кодировке OpenBSD-Base64 (31 символ, 24 байта)
Изменить: я только что заметил, что эти слова точно подходят. я должен был поделиться:
$2a$10$TwentytwocharactersaltThirtyonecharacterspasswordhash
$==$==$======================-------------------------------
BCrypt действительно создает 24-байтовый двоичный хеш, используя 16-байтовую соль. Вы можете хранить двоичный хэш и соль как хотите; ничто не говорит о том, что вы должны кодировать его в base-64 в строку.
Но BCrypt был создан ребятами, которые работали над OpenBSD. OpenBSD уже определяет формат своего файла паролей:
$[HashAlgorithmIdentifier]
$[AlgorithmSpecificData]
Это означает, что спецификация bcrypt неразрывно связана с форматом файла паролей OpenBSD. И всякий раз, когда кто-либо создает хэш bcrypt, он всегда преобразует его в строку формата ISO-8859-1:
$2a
$[Cost]
$[Base64Salt][Base64Hash]
Несколько важных моментов:
2a
— идентификатор алгоритма
- 1: MD5
- 2: ранний bcrypt, у которого была путаница в том, в какой кодировке находятся пароли (устарело)
- 2a: текущий bcrypt, который указывает пароли в кодировке UTF-8.
Стоимость — фактор стоимости, используемый при вычислении хэша. Текущее значение равно 10, что означает, что настройка внутреннего ключа проходит через 1024 раунда.
- 10: 210 = 1,024 iterations
- 11: 211 = 2048 итераций.
- 12: 212 = 4096 итераций.
алгоритм base64, используемый файлом паролей OpenBSD, не является той же кодировкой Base64, которую используют все остальные; у них свои:
Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
Таким образом, любые реализации bcrypt не могут использовать встроенную или стандартную библиотеку base64.
Вооружившись этими знаниями, теперь вы можете проверить пароль correctbatteryhorsestapler
по сохраненному хешу:
$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km
Варианты BCrypt
Существует много путаницы вокруг версий bcrypt.
$2$
BCrypt был разработан людьми OpenBSD. Он был разработан для хеширования паролей для хранения в файле паролей OpenBSD. Хешированные пароли хранятся с префиксом для идентификации используемого алгоритма. BCrypt получил префикс $2$
.
Это было в отличие от других префиксов алгоритма:
$1$
: MD5
$5$
: SHA-256
$6$
: SHA-512
$2$
Первоначальная спецификация BCrypt не определяла, как обрабатывать символы, отличные от ASCII, или как обрабатывать нулевой терминатор. Спецификация была пересмотрена, чтобы указать, что при хешировании строк:
- строка должна быть в кодировке UTF-8
- нулевой терминатор должен быть включен
$2x$, $2y$ (июнь 2011 г.)
В crypt_blowfish????, PHP-реализация BCrypt. Это была неправильная обработка символов с установленным 8-м битом.
Они предложили системным администраторам обновить свою существующую базу паролей, заменив $2a$
на $2x$
, чтобы указать, что эти хэши неверны (и нужно использовать старый сломанный алгоритм). Они также предложили, чтобы crypt_blowfish выдавал $2y$
для хэшей, сгенерированных фиксированным алгоритмом. Никто другой, включая каноническую OpenBSD, не принял идею 2x
/2y
. Этот маркер версии был ограничен crypt_blowfish????.
Версии $2x$ и $2y$ не лучше и не сильнее, чем $2a$. Это остатки одной конкретной реализации BCrypt с ошибками.
2 млрд долларов США (февраль 2014 г.)
В реализации BCrypt для OpenBSD обнаружена ошибка. Они написали свою реализацию на языке, который не поддерживает строки, поэтому они подделывали ее с префиксом длины, указателем на символ, а затем индексировали этот указатель с помощью []
. К сожалению, они сохраняли длину своих строк в файле unsigned char
. Если пароль был длиннее 255 символов, он переполнялся и переносился на 255 символов. BCrypt был создан для OpenBSD. Когда у них возникла ошибка в их библиотеке, они решили, что можно обновить версию. Это означает, что все остальные должны последовать их примеру, если вы хотите соответствовать их спецификациям.
Нет никакой разницы между 2a, 2x, 2y и 2b. Если вы правильно написали свою реализацию, все они выведут один и тот же результат.
- Если вы с самого начала поступали правильно (сохраняли строки в utf8, а также хэшировали нулевой терминатор), то: нет никакой разницы между 2, 2a, 2x, 2y и 2b. Если вы правильно написали свою реализацию, все они выведут один и тот же результат.
- Версия $2b$ не лучше и не сильнее, чем $2a$. Это остаток одной конкретной реализации BCrypt с ошибками. Но поскольку BCrypt канонически принадлежит OpenBSD, они могут изменить маркер версии на любой, какой захотят.
- Версии $2x$ и $2y$ ничем не лучше и даже не предпочтительнее. Это остатки глючной реализации, о которых следует забыть.
О 2x и 2y должны заботиться только те, кто использовал crypt_blowfish еще в 2011 году. А о 2b должны заботиться только те, кто возможно, работал под управлением OpenBSD.
Все остальные правильные реализации идентичны и правильны.
person
Ian Boyd
schedule
07.06.2012