Может кто-нибудь объяснить, как BCrypt проверяет хеш?
Я использую C# и BCrypt.Net для хэширования моих паролей.
Например:
string salt = BCrypt.Net.BCrypt.GenerateSalt(6);
var hashedPassword = BCrypt.Net.BCrypt.HashPassword("password", salt);
//This evaluates to True. How? I'm not telling it the salt anywhere, nor
//is it a member of a BCrypt instance because there IS NO BCRYPT INSTANCE.
Console.WriteLine(BCrypt.Net.BCrypt.Verify("password", hashedPassword));
Console.WriteLine(hashedPassword);
Как BCrypt проверяет пароль с помощью хеша, если соль нигде не сохраняется. Единственная идея, которая у меня есть, это то, что она как-то добавляет соль в конце хэша.
Это правильное предположение?
2 ответа
Как BCrypt проверяет пароль с помощью хэша, если соль нигде не сохраняется?
Очевидно, что он не делает ничего подобного. Соль должна быть где-то сохранена.
Давайте посмотрим схемы шифрования паролей в Википедии. С http://en.wikipedia.org/wiki/Crypt_%28Unix%29:
Выходные данные функции - это не просто хеш: это текстовая строка, которая также кодирует соль и определяет используемый алгоритм хеширования.
Кроме того, ответ на ваш предыдущий вопрос по этой теме включал ссылку на исходный код. Вместо того, чтобы просить Интернет прочитать исходный код для вас, вы всегда можете прочитать его самостоятельно. Это, вероятно, получит ваш ответ быстрее. Соответствующий раздел исходного кода:
StringBuilder rs = new StringBuilder();
rs.Append("$2");
if (minor >= 'a') {
rs.Append(minor);
}
rs.Append('$');
if (rounds < 10) {
rs.Append('0');
}
rs.Append(rounds);
rs.Append('$');
rs.Append(EncodeBase64(saltBytes, saltBytes.Length));
rs.Append(EncodeBase64(hashed,(bf_crypt_ciphertext.Length * 4) - 1));
return rs.ToString();
Ясно, что возвращаемая строка является информацией о версии, за которой следует количество использованных раундов, за которым следует соль, закодированная как base64, а затем хеш, закодированный как base64.
Хеш- строка BCrypt выглядит так:
$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm
$==$==$======================-------------------------------
куда
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: 2 = 1024 итерации
- 11: 21 = 2048 итераций
- 12:12 = 4096 итераций
алгоритм base64, используемый файлом паролей OpenBSD, не является той же кодировкой Base64, которую используют все остальные; у них свои
Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
Таким образом, любые реализации bcrypt не могут использовать какую-либо встроенную или стандартную библиотеку base64.
Вооружившись этими знаниями, теперь вы можете проверить пароль correctbatteryhorsestapler
против сохраненного хеша:
$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km