Почему BCrypt.net GenerateSalt(31) сразу возвращается?

Я наткнулся на BCrypt.net после прочтения поста Джеффа Этвуда о хранении паролей, который привел меня к рекомендации Томаса Птачека использовать BCrypt для хранения паролей. Который, наконец, привел меня к этой C# реализации BCrypt

В комментариях к последней ссылке выше кто-то спросил: "Почему GenerateSalt(30) работает вечно, а GenerateSalt(31), похоже, совсем не занимает время?"

Я запустил BCrypt.HashPassword(пароль, BCrypt.GenerateSalt(31)) и получил свой результат за 0 миллисекунд.

Я запускаю BCrypt.HashPassword("пароль", BCrypt.GenerateSalt(30)) уже более 5 минут и до сих пор не получил результата.

Я понимаю, что нам, вероятно, не понадобится случайно сгенерированная 30-символьная соль для создания наших хэшей паролей (или необратимого шифрования в случае BCrypt) в течение многих лет. РЕДАКТИРОВАТЬ Я должен был прочитать код немного, logRounds не имеет никакого отношения к длине соли. Спасибо Аарона.

Итак, почему GenerateSalt(31) возвращает значение практически мгновенно (тогда как это должно занять примерно вдвое больше времени, чем GenerateSalt(30)?

ОБНОВИТЬ

вот исправление:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) {
    // ... snip ...
    uint rounds = 1U << logRounds;
    // ... snip
}

2 ответа

Решение

Я подозреваю, что ошибка здесь:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) {
    // ... snip ...
    int rounds = 1 << logRounds;
    // ... snip
}

Когда вы указываете 31 для logRounds, он вычисляет это как 2^32, который не может вписаться в int и переполняется, поэтому хеш фактически выполняется в... ээ, нулевых проходах. Автор должен был использовать uint вместо. Легко исправить!


Также хотел бы прокомментировать это:

Я понимаю, что нам, вероятно, не понадобится случайно сгенерированная соль из 30 символов для создания наших хэшей паролей...

Обратите внимание, что logRounds параметр не относится к числу символов / байтов в соли, которое всегда равно 16. Он относится к логарифмической базе числа проходов, которые хеш будет вычислять; другими словами, это способ масштабирования bcrypt с помощью закона Мура, что делает вычисление функции на несколько порядков дороже, если компьютеры когда-либо становятся достаточно быстрыми для взлома существующих хешей.

Если перемешивание с GenerateSalt(31) возвращается почти мгновенно, это ошибка. Вы должны сообщить об этом вверх по течению (у меня есть, для jBCrypt).:-)

По умолчанию количество раундов составляет 10. Это означает, что (если я правильно помню) используется 1024 раунда. Каждый раз, когда вы увеличиваете количество раундов, количество раундов удваивается.

На 30 раундах вы выполняете 1073741824 раундов. Это по праву занимает много времени. При 31 цикле регистрации необходимо выполнить 2147483648 циклов, но я подозреваю, что конкретная реализация, которую вы используете вместо этого, переполняется.:-(

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