短版
至少需要 250 毫秒来计算的迭代次数
加长版
当 BCrypt 在 1999 年首次发布时,他们列出了实现的默认成本因素:
6 的 bcrypt 成本意味着 64 轮(26 = 64)。
他们还注意到:
当然,人们选择的任何成本都应该重新评估
时不时
- 在 1976 年部署时,crypt 每秒可以散列少于 4 个密码。 (每个密码 250 毫秒)
- 在 1977 年,在 VAX-11/780 上,crypt (MD5) 每秒可以评估大约 3.6 次。 (每个密码 277 毫秒)
这让您了解了最初的实现者在编写它时所考虑的那种延迟:
当然,你能站得越久越好。我见过的每个 BCrypt 实现都使用 10 作为默认成本。 my implementation 使用了它。我认为是时候将默认成本提高到 12 了。
我们已经决定,我们希望每个哈希的目标时间不少于 250 毫秒。
我的台式电脑是 Intel Core i7-2700K CPU @ 3.50 GHz。我最初在 2014 年 1 月 23 日对 BCrypt 实现进行了基准测试:
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 库的一部分,因此与其依赖库的用户定期增加成本,不如定期增加成本。