最佳的bcrypt工作因子

时间:2010-12-14 19:46:33

标签: bcrypt

密码散列的理想bcrypt工作因素是什么。

如果我使用系数10,则在笔记本电脑上散列密码大约需要1秒。如果我们最终得到一个非常繁忙的网站,那么只需查看人们的密码即可完成大量工作。

也许最好使用7的工作因子,将每个笔记本电脑登录的总密码哈希工作减少到大约0.01秒?

您如何决定暴力安全与运营成本之间的权衡?

3 个答案:

答案 0 :(得分:99)

请记住,该值存储在密码中:$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的人。

答案 1 :(得分:3)

短版

至少需要250毫秒进行计算的迭代次数

长版

当BCrypt于1999年首次发布时,他们列出了其实现的默认成本因素:

  • 普通用户: 6
  • 超级用户: 8

6 的加密费用意味着64轮(2 6 = 64)。

他们还指出:

当然,应该重新评估人们选择的任何成本 不时

  • 在1976年部署时,crypt每秒可以散列少于4个密码。 (每个密码250毫秒)
  • 在1977年,在VAX-11 / 780上,每秒可评估隐窝(MD5)约3.6次。 (每个密码277毫秒)

这使您感受到原始实现者在编写它们时所考虑的那种延迟:

    普通用户
  • 〜250毫秒
  • 超级用户大约1秒。

但是,当然,您能站立的时间越长越好。我见过的每个BCrypt实现都使用10作为默认成本。 my implementation使用了它。我认为现在是时候将默认费用增加到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 |

enter image description here

未来的证明

它应该是固定的最小值,而不是固定的常数。

而不是使用密码哈希功能:

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库的一部分,因此,不是依靠库的用户来定期增加成本,而是定期自己增加成本。

答案 2 :(得分:0)

该问题与 bcrypt 密码哈希成本因素的最佳和实际确定有关。

在您为服务器计算用户密码哈希值的系统上,您预计用户数量会随着时间的推移而增长,为什么不将用户拥有您的服务帐户的持续时间作为决定因素,也许包括他们的登录频率作为该决定的一部分。

Bcrypt 成本系数 = 6 +(用户会员资格的年数或其某个因素),总成本有一个可选的上限,可能会以某种方式通过该用户的登录频率进行修改。

但请记住,使用这样的系统或任何系统来有效地确定成本因素必须考虑到计算散列的成本可以用作对服务器本身进行 DDOS 攻击的方法增加了他们攻击的成本因素。