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

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

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

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

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

Я понимаю, что нам, вероятно, не понадобится беспорядочно сформированная соль из 30 символов для создания хэшей паролей (или необратимого шифрования в случае BCrypt) в течение многих лет. EDIT Мне нужно немного прочитать код, logRounds не имеет ничего общего с длиной соли. Спасибо Aaronaught.

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

UPDATE

здесь есть исправление:

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

Ответ 1

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

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

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


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

Я понимаю, что нам, вероятно, не понадобится беспорядочно сформированная соль из 30 символов, чтобы создать хэш-коды...

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

Ответ 2

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

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

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