对于密码哈希来说,理想的bcrypt工作因素是什么。
如果我使用10的系数,则在笔记本电脑上哈希密码大约需要0.1秒。如果我们的站点非常繁忙,那么仅检查人们的密码就需要进行大量工作。
也许使用7的工作因子会更好,将每台笔记本电脑登录的总密码哈希工作减少到大约.01s?
您如何确定暴力安全性和运营成本之间的权衡?
对于密码哈希来说,理想的bcrypt工作因素是什么。
如果我使用10的系数,则在笔记本电脑上哈希密码大约需要0.1秒。如果我们的站点非常繁忙,那么仅检查人们的密码就需要进行大量工作。
也许使用7的工作因子会更好,将每台笔记本电脑登录的总密码哈希工作减少到大约.01s?
您如何确定暴力安全性和运营成本之间的权衡?
Answers:
请记住,该值存储在密码:中$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的家伙。
$2y$08$fJS4yx0i8kiOzIBIamZ51OWTMrzyE/4je34Oxhw.5xxp3Es7Ke32W
。我尝试编辑的原因:我不清楚“ 2个字符的工作方式”是数字还是十六进制之类的东西,必须进行测试。这是其他所有人的测试结果,因此您不必自己尝试一下。
至少需要250毫秒进行计算的迭代次数
BCrypt于1999年首次发布时,他们列出了其实现的默认成本因素:
bcrypt成本为6意味着64轮(2 6 = 64)。
他们还指出:
当然,人们选择的成本应该不时重新评估
这使您感受到原始实现者在编写它们时所考虑的那种延迟:
但是,当然,您能站立的时间越长越好。我见过的每个BCrypt实现都用作10
默认成本。而我的实现使用的。我认为现在是时候将默认费用增加到12了。
我们已经决定要针对每个哈希不少于250ms。
我的台式机是@ 3.50 GHz的Intel Core i7-2700K CPU。我最初在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库的一部分,因此,不依赖库的用户来定期增加成本,而是定期自己增加成本。