最佳 bcrypt 工作因子

发布于 2024-10-07 07:12:23 字数 199 浏览 0 评论 0原文

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

如果我使用因子 10,则在我的笔记本电脑上散列密码大约需要 0.1 秒。如果我们最终得到一个非常繁忙的网站,那么仅仅检查人们的密码就会变成大量的工作。

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

您如何决定强力安全性和运营成本之间的权衡?

What would be an ideal bcrypt work factor for password hashing.

If I use a factor of 10, it takes approx .1s to hash a password on my laptop. If we end up with a very busy site, that turns into a good deal of work just checking people's passwords.

Perhaps it would be better to use a work factor of 7, reducing the total password hash work to about .01s per laptop-login?

How do you decide the tradeoff between brute force safety and operational cost?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梓梦 2024-10-14 07:12:23

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

Remember that the value is stored in the password: $2a$(2 chars work)$(22 chars salt)(31 chars hash). It is not a fixed value.

If you find the load is too high, just make it so the next time they log in, you crypt to something faster to compute. Similarly, as time goes on and you get better servers, if load isn't an issue, you can upgrade the strength of their hash when they log in.

The trick is to keep it taking roughly the same amount of time forever into the future along with Moore's Law. The number is log2, so every time computers double in speed, add 1 to the default number.

Decide how long you want it to take to brute force a user's password. For some common dictionary word, for instance, your account creation probably already warned them their password was weak. If it's one of 1000 common words, say, and it takes an attacker 0.1s to test each, that buys them 100s (well, some words are more common...). If a user chose 'common dictionary word' + 2 numbers, that's over two hours. If your password database is compromised, and the attacker can only get a few hundred passwords a day, you've bought most of your users hours or days to safely change their passwords. It's a matter of buying them time.

http://www.postgresql.org/docs/8.3/static/pgcrypto.html has some times for cracking passwords for you to consider. Of course, the passwords they list there are random letters. Dictionary words... Practically speaking you can't save the guy whose password is 12345.

枫林﹌晚霞¤ 2024-10-14 07:12:23

短版本

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

长版本

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

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

bcrypt 成本为 6 意味着 64 轮(26 = 64)。

他们还指出:

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

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

这让您感受到原始实现者在编写密码时所考虑的延迟:

  • 普通用户约为 250 毫秒
  • ,超级用户约为 1 秒。

但是,当然,你能坚持的时间越长越好。我见过的每个 BCrypt 实现都使用 10 作为默认成本。 我的实现使用了它。我相信现在是时候将默认成本增加到 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 库的一部分,因此与其依赖库的用户定期增加成本,不如让成本定期增加本身。

Short Version

The number of iterations that gives at least 250 ms to compute

Long Version

When BCrypt was first published, in 1999, they listed their implementation's default cost factors:

  • normal user: 6
  • super user: 8

A bcrypt cost of 6 means 64 rounds (26 = 64).

They also note:

Of course, whatever cost people choose should be reevaluated
from time to time

  • At the time of deployment in 1976, crypt could hash fewer than 4 passwords per second. (250 ms per password)
  • In 1977, on a VAX-11/780, crypt (MD5) could be evaluated about 3.6 times per second. (277 ms per password)

That gives you a flavor of the kind of delays that the original implementers were considering when they wrote it:

  • ~250 ms for normal users
  • ~1 second for super users.

But, of course, the longer you can stand, the better. Every BCrypt implementation I've seen used 10 as the default cost. And my implementation used that. I believe it is time for me to to increase the default cost to 12.

We've decided we want to target no less than 250ms per hash.

My desktop PC is an Intel Core i7-2700K CPU @ 3.50 GHz. I originally benchmarked a BCrypt implementation on 1/23/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 |

enter image description here

Future Proofing

Rather than having a fixed constant, it should be a fixed minimum.

Rather than having your password hash function be:

String HashPassword(String password)
{
   return BCrypt.HashPassword(password, BCRYPT_DEFAULT_COST);
}

it should be something like:

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;
}

And ideally this would be part of everyone's BCrypt library, so rather than relying on users of the library to periodically increase the cost, the cost periodically increases itself.

情绪 2024-10-14 07:12:23

我一直在尝试确定 bcrypt salting 轮次的最佳数量,并想发布我的发现。正如其他人指出的那样,理想的轮数取决于您的硬件、用户的耐心以及潜在攻击者的硬件。

2023 年,在基本的 Heroku dyno 上运行,然后再次在我的本地计算机上运行,​​我对一系列不同的 salt 轮次执行哈希操作所需的时间进行了基准测试:

salt roundsheroku 哈希时间5600x 哈希时间破解弱 pw ( 28 位)破解中等 PW (37 位)
713 ms8 ms12 天17 年
824 ms15 ms23 天32 年
947 ms29 ms1.5 个月63 年
1090 ms58 ms3 个月126 年
11181 ms118 ms6 个月256 年
12367 ms233 ms1 年长期
13735 ms461 ms2 年
141422 ms936 ms4 年
152878 ms1863 ms8 年
165969 ms3721 ms16 年

The基于著名的 XKCD 密码漫画的弱密码熵位数

需要记住的因素:

  • 破解时间可以除以您可以访问的计算机数量。拥有僵尸网络或大量资金的黑客可以将这些破解时间划分为几个数量级

  • 破解时间随着时间的推移而减少。现在泄露的哈希密码可能在 10 年后很容易被破解。

  • 5600X 距离现代处理的顶峰还很远。 7900X能够更快地完成此操作。

  • 这是单线程完成的,多线程会使它更快。

根据此数据,我建议至少 10 轮,但强烈建议 11 轮。100-200 毫秒对于用户来说等待的时间非常短,如果并发登录导致延迟,您应该考虑为您的后端添加更多马力。我最多建议是13轮。虽然它非常安全,但 700 毫秒对于用户等待登录来说是很长的时间。在 10 到 13 毫秒之间,这将是您作为开发人员需要做出的判断。

PS:我想赞扬 Ian Boyds 非常好的图表和非常好的自动缩放代码。这是每个阅读本文的人都应该考虑的事情,但我也想提供一些最新数据,说明 bcrypt 在当前和常见硬件上今年实际需要多长时间。

如果这个答案已经过时,请发表评论,我会尽力抽出时间来更新它。

注意:如何计算破解时间?

要讨论这个问题,我们首先必须讨论密码熵。非常简单:密码熵是根据您用来选择密码的系统计算的。因此,如果您的密码是 4 位 PIN 码,则您只能选择 10,000 个可能的 PIN 码。因此,您的密码的熵为 10,000。这通常被称为 13 位熵,因为 10,000 ≈ 2^3。

要确定攻击者破解您的密码需要多长时间,您需要确定的是他们平均需要猜测多少次。对于那个 4 位数字的 PIN 码,他们可以在第一次尝试时猜出,或者需要 10,000 次尝试。但攻击者平均需要尝试 5,000 次。所以检查单个密码所需的时间乘以所需猜测的次数就是破解时间。

I've been trying to determine my optimal number of bcrypt salting rounds and wanted to post my findings. As others have pointed out, the ideal number of rounds depends on your hardware, your user's patience, and the hardware of potential attackers.

In the year 2023, running on a basic heroku dyno and then again on my local machine, I benchmarked how long it takes to do a hash operation for a range of different salt rounds:

salt roundsheroku hash time5600x hash timecrack weak pw (28 bits)crack medium pw (37 bits)
713 ms8 ms12 days17 years
824 ms15 ms23 days32 years
947 ms29 ms1.5 months63 years
1090 ms58 ms3 months126 years
11181 ms118 ms6 months256 years
12367 ms233 ms1 yearslong time
13735 ms461 ms2 years"
141422 ms936 ms4 years"
152878 ms1863 ms8 years"
165969 ms3721 ms16 years"

The bits of entropy for the weak password based on the famous XKCD password comic

Factors to keep in mind:

  • The crack time can be divided by the number of computers you have access to. Hackers with bot-nets or lots of funds can divide these crack times by orders of magnitude

  • Crack time decreases over time. Hashed passwords that are leaked now might be able to be cracked very easily in 10 years time.

  • A 5600X is far from the pinnacle of modern processing. A 7900X will be able to do this faster.

  • This was done single-threaded, multithreading will make it faster.

Based on this data, I would advise a minimum of at least 10 rounds but would strongly suggest 11. 100-200 ms is a very short period of time for a user to wait, and if concurrent sign ins are causing lag, you should consider adding more horsepower to your backend. The most I would advise is 13 rounds. While it will be very secure, 700ms is a long time for users to wait to sign in. Between 10 and 13, it's going to be a judgement call that you, as a developer, need to make.

PS: I want to credit Ian Boyds very nice graph and very nice auto-scaling code. It is something everyone reading this should give consideration, but I also wanted to provide some up-to-date data on how long bcrypt actually takes in the current year, on current and common hardware.

Please comment if this answer goes out of date and I will try my best to get around to updating it.

Note: How do you calculate crack times?

To discuss this we first have to discuss password entropy. Very briefly: password entropy is calculated based on the system you use to pick a password. So if your password is a 4 digit pin, then there are only 10,000 possible PIN numbers you could choose. Your password therefore has an entropy of 10,000. This would typically be called 13 bits of entropy, since 10,000 ≈ 2¹³.

To determine how long an attacker would take to crack your password, all you need to determine is how many guesses they would take on average. For that 4 digit pin, they could guess it on the first try, or need 10,000 tries. But on average it will take an attacker 5,000 tries. So the time required to check a single password multiplied by the number of guesses required is the crack time.

逆光飞翔i 2024-10-14 07:12:23

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

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

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

请记住,使用此类系统或任何系统来有效确定成本因素必须考虑到计算哈希值的成本可以用作针对服务器本身的 DDOS 攻击方法,方法是考虑任何增加成本的方法影响他们攻击的因素。

The question was related to optimal and practical determination of cost factor for bcrypt password hashes.

On a system where you're calculating user password hashes for a server that you expect will grow in user population over time, why not make the duration of time that a user has had an account with your service the determining factor, perhaps including their login frequency as part of that determination.

Bcrypt Cost Factor = 6 + (Number years of user membership or some factor thereof) with an optional ceiling for total cost, perhaps modified in some way by the login frequency of that user.

Keep in mind though that using such a system or ANY system for determining cost factor effectively must include the consideration that the cost of calculating that hash could be used as a method of DDOS attack against the server itself by factoring in any method that increases the cost factor into their attack.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文