Оптимальный коэффициент работы bcrypt
Что было бы идеальным рабочим фактором bcrypt для хеширования паролей.
Если я использую коэффициент 10, для хэширования пароля на моем ноутбуке требуется около 1 с. Если мы получим очень загруженный сайт, это превращается в большую работу, просто проверяющую пароли людей.
Возможно, было бы лучше использовать коэффициент работы 7, уменьшая общую работу хэша пароля примерно до 0,01 с на вход в систему с ноутбука?
Как вы решаете компромисс между безопасностью перебора и эксплуатационными затратами?
4 ответа
Помните, что значение хранится в пароле: $2a$(2 chars work)$(22 chars salt)(31 chars hash)
, Это не фиксированное значение.
Если вы обнаружите, что нагрузка слишком высока, просто сделайте так, чтобы при следующем входе в систему вы зашифровали что-то более быстрое для вычисления. Точно так же, со временем, и вы получаете лучшие серверы, если загрузка не является проблемой, вы можете повысить надежность их хэша при входе в систему.
Хитрость заключается в том, чтобы держать это в течение примерно одинакового количества времени навсегда в будущем вместе с законом Мура. Это число log2, поэтому каждый раз, когда скорость компьютера увеличивается вдвое, добавьте 1 к номеру по умолчанию.
Решите, сколько времени вы хотите, чтобы перебор пароля пользователя. Например, для некоторых общих слов в словаре создание вашей учетной записи уже предупредило их, что их пароль был слабым. Скажем, если это одно из 1000 распространенных слов, и злоумышленнику требуется 0,1 с, чтобы протестировать каждое, которое покупает их по 100 с (ну, некоторые слова встречаются чаще...). Если пользователь выбрал "общее словарное слово" + 2 цифры, это более двух часов. Если ваша база паролей скомпрометирована, и злоумышленник может получить только несколько сотен паролей в день, вы купили большинство своих пользователей часами или днями, чтобы безопасно сменить их пароли. Это вопрос выигрыша времени.
http://www.postgresql.org/docs/8.3/static/pgcrypto.html есть несколько вариантов взлома паролей, которые вы можете рассмотреть. Конечно, в паролях, которые они перечисляют, есть случайные буквы. Словарные слова... Практически говоря, вы не можете спасти парня с паролем 12345.
Укороченная версия
Количество итераций, дающее не менее 250 мс на вычисление
Длинная версия
Когда BCrypt был впервые опубликован в 1999 году, они перечислили факторы стоимости своей реализации по умолчанию:
- обычный пользователь: 6
- суперпользователь: 8
Стоимость bcrypt, равная 6, означает 64 раунда (26 = 64).
Также они отмечают:
Конечно, какую бы стоимость ни выбирали люди, ее следует время от времени пересматривать.
- На момент развертывания в 1976 году crypt мог хэшировать менее 4 паролей в секунду. (250 мс на пароль)
- В 1977 году на VAX-11/780 крипта (MD5) могла оцениваться примерно 3,6 раза в секунду. (277 мс на пароль)
Это дает вам представление о задержках, которые учитывали первоначальные разработчики, когда писали это:
- ~250 мс для обычных пользователей
- ~1 секунда для суперпользователей.
Но, конечно, чем дольше выдержишь, тем лучше. Каждая реализация BCrypt, которую я видел, использовала10
как стоимость по умолчанию. И моя реализация использовала это. Я считаю, что мне пора увеличить стоимость по умолчанию до 12.
Мы решили, что хотим нацелить не менее 250 мс на хэш.
Мой настольный ПК - это процессор Intel Core i7-2700K @ 3,50 ГГц. Изначально я тестировал реализацию BCrypt 23.01.2014:
1/23/2014 Intel Core i7-2700K CPU @ 3.50 GHz
| Cost | Iterations | Duration |
|------|-------------------|-------------|
| 8 | 256 iterations | 38.2 ms | <-- minimum allowed by BCrypt
| 9 | 512 iterations | 74.8 ms |
| 10 | 1,024 iterations | 152.4 ms | <-- current default (BCRYPT_COST=10)
| 11 | 2,048 iterations | 296.6 ms |
| 12 | 4,096 iterations | 594.3 ms |
| 13 | 8,192 iterations | 1,169.5 ms |
| 14 | 16,384 iterations | 2,338.8 ms |
| 15 | 32,768 iterations | 4,656.0 ms |
| 16 | 65,536 iterations | 9,302.2 ms |
Будущее
Вместо фиксированной константы она должна быть фиксированным минимумом.
Вместо того, чтобы иметь хеш-функцию вашего пароля:
String HashPassword(String password)
{
return BCrypt.HashPassword(password, BCRYPT_DEFAULT_COST);
}
это должно быть примерно так:
String HashPassword(String password)
{
/*
Rather than using a fixed default cost, run a micro-benchmark
to figure out how fast the CPU is.
Use that to make sure that it takes **at least** 250ms to calculate
the hash
*/
Int32 costFactor = this.CalculateIdealCost();
//Never use a cost lower than the default hard-coded cost
if (costFactor < BCRYPT_DEFAULT_COST)
costFactor = BCRYPT_DEFAULT_COST;
return BCrypt.HashPassword(password, costFactor);
}
Int32 CalculateIdealCost()
{
//Benchmark using a cost of 5 (the second-lowest allowed)
Int32 cost = 5;
var sw = new Stopwatch();
sw.Start();
this.HashPassword("microbenchmark", cost);
sw.Stop();
Double durationMS = sw.Elapsed.TotalMilliseconds;
//Increasing cost by 1 would double the run time.
//Keep increasing cost until the estimated duration is over 250 ms
while (durationMS < 250)
{
cost += 1;
durationMS *= 2;
}
return cost;
}
И в идеале это должно быть частью библиотеки BCrypt каждого, поэтому вместо того, чтобы полагаться на то, что пользователи библиотеки периодически увеличивают стоимость, она периодически увеличивается сама.
Я пытался определить оптимальное количество раундов обработки bcrypt и хотел опубликовать свои выводы. Как отмечали другие, идеальное количество раундов зависит от вашего оборудования, терпения вашего пользователя и оборудования потенциальных злоумышленников.
В 2023 году, работая на базовом динамометрическом стенде Heroku, а затем снова на своей локальной машине, я измерил, сколько времени занимает выполнение хэш-операции для ряда различных соляных раундов:
Биты энтропии для слабого пароля на основе знаменитого комикса о паролях XKCD
Факторы, которые следует учитывать:
Время взлома можно разделить на количество компьютеров, к которым у вас есть доступ. Хакеры с бот-сетями или большим количеством средств могут разделить время взлома на порядки.
Время взлома со временем уменьшается. Хешированные пароли, которые стали известны сейчас, могут быть легко взломаны через 10 лет.
5600X далек от вершины современной обработки. 7900X сможет сделать это быстрее.
Это было сделано в однопоточном режиме, многопоточность сделает это быстрее.
Основываясь на этих данных, я бы посоветовал минимум 10 раундов, но настоятельно рекомендую 11. 100–200 мс — это очень короткий период времени для ожидания пользователя, и если одновременные входы в систему вызывают задержку, вам следует учитывать добавив больше мощности в ваш сервер. Максимум, что я бы посоветовал, это 13 раундов. Хотя это будет очень безопасно, 700 мс — это длительный срок для пользователей, чтобы ждать входа в систему. Между 10 и 13 годами вам, как разработчику, придется принять решение.
PS: Я хочу поблагодарить Яна Бойда за очень хороший график и очень хороший код автоматического масштабирования. Это то, о чем должен подумать каждый, читающий это, но я также хотел предоставить некоторые актуальные данные о том, сколько времени на самом деле занимает bcrypt в текущем году на текущем и обычном оборудовании.
Пожалуйста, прокомментируйте, если этот ответ устарел, и я сделаю все возможное, чтобы обновить его.
Примечание. Как рассчитать время взлома?
Чтобы обсудить это, нам сначала нужно обсудить энтропию паролей. Очень кратко: энтропия пароля рассчитывается на основе системы, которую вы используете для подбора пароля. Таким образом, если ваш пароль представляет собой 4-значный PIN-код, вы можете выбрать только 10 000 возможных PIN-кодов. Таким образом, ваш пароль имеет энтропию 10000. Обычно это называют 13 битами энтропии, поскольку 10000 ≈ 2¹³.
Чтобы определить, сколько времени понадобится злоумышленнику, чтобы взломать ваш пароль, все, что вам нужно, это определить, сколько в среднем ему потребуется угадать. Для этого четырехзначного PIN-кода они могли угадать его с первой попытки или потребуется 10 000 попыток. Но в среднем злоумышленнику потребуется 5000 попыток. Таким образом, время, необходимое для проверки одного пароля, умноженное на количество требуемых попыток, и есть время взлома.
Вопрос касался оптимального и практического определения фактора стоимости хэшей паролей bcrypt.
В системе, где вы вычисляете хэши паролей пользователей для сервера, количество пользователей которого, как вы ожидаете, со временем будет расти, почему бы не сделать определяющим фактором продолжительность времени, в течение которого пользователь имеет учетную запись в вашей службе, возможно, включая их вход в систему частота как часть этого определения.
Фактор стоимости Bcrypt = 6 + (количество лет членства пользователя или некоторый его коэффициент) с дополнительным потолком общей стоимости, возможно, каким-то образом измененным частотой входа в систему этого пользователя.
Однако имейте в виду, что использование такой системы или ЛЮБОЙ системы для эффективного определения фактора затрат должно включать рассмотрение того, что стоимость вычисления этого хэша может быть использована в качестве метода DDOS-атаки против самого сервера с учетом любого метода, который увеличивает стоимость фактор в их атаке.