Подтвердить что ты не робот

Может ли кто-нибудь объяснить, как BCrypt проверяет хэш?

Я использую С# и 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 проверяет пароль с помощью хэша, если он не сохраняет соль в любом месте. Единственная идея, которую я имею, это то, что она каким-то образом добавляет соль в конце хэша.

Это правильное предположение?

4b9b3361

Ответ 1

Как BCrypt проверяет пароль с хешем, если он не сохраняет соль где-нибудь?

Очевидно, что это не так. Соль должна быть где-то сохранена.

Позвольте искать схемы шифрования паролей в Википедии. Из http://en.wikipedia.org/wiki/Crypt_ (Unix):

Вывод функции не просто хеш: это текстовая строка, которая также кодирует соль и идентифицирует используемый хэш-алгоритм.

В качестве альтернативы, ответ на ваш предыдущий вопрос по этому вопросу включал ссылку на источник код. Вместо того, чтобы просить интернет прочитать исходный код для вас, вы всегда можете сами его прочитать. Это, скорее всего, поможет вам быстрее ответить. Соответствующий раздел исходного кода:

    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.

Ответ 2

Символ хэша BCrypt выглядит следующим образом:

$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm
$==$==$======================-------------------------------

Где

  • 2a: Алгоритм Идентификатор (BCrypt, UTF8 закодированный пароль, завершенный нулем)
  • 10: Коэффициент затрат (2 10= 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 - это идентификатор alogithm
    • 1: MD5
    • 2: ранний bcrypt, у которого была путаница, по которой кодируются пароли (устаревшие)
    • 2a: текущий bcrypt, который определяет пароли как кодированные UTF-8
  • Стоимость - это фактор затрат, используемый при вычислении хэша. "Текущее" значение равно 10, что означает, что настройка внутреннего ключа проходит через 1024 раунда
    • 10: 2 10= 1,024 итераций
    • 11: 2 11= 2,048 итераций
    • 12: 2 12= 4,096 итераций
  • алгоритм base64, используемый файлом паролей OpenBSD, - это не то же самое кодирование Base64, что и остальные; они имеют свои собственные:

    Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
        BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
    

    Таким образом, любые реализации bcrypt не могут использовать встроенную или стандартную библиотеку base64


Вооруженный этими знаниями, теперь вы можете проверить пароль correctbatteryhorsestapler на сохраненный хэш:

$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km