为什么 BCrypt.netGenerateSalt(31) 立即返回?

发布于 2024-08-20 11:30:58 字数 1274 浏览 11 评论 0原文

在阅读 Jeff Atwood 关于存储密码的帖子后,我偶然发现了 BCrypt.net我向 Thomas Ptacek 的推荐 使用BCrypt来存储密码。这最终导致我 BCrypt 的这个 C# 实现

在上面最后一个链接的评论中,有人问“为什么GenerateSalt(30) 永远需要时间,但GenerateSalt(31) 似乎根本不需要时间?”

我运行了 BCrypt.HashPassword(password, BCrypt.GenerateSalt(31)) 并在 0 毫秒内得到了结果。

我已经运行 BCrypt.HashPassword("password", BCrypt.GenerateSalt(30)) 超过 5 分钟,但仍然没有结果。

我意识到我们可能不需要随机生成的 30 个字符的盐来创建我们的密码哈希(或 BCrypt 的情况是不可逆加密)多年。 编辑 我应该读一下代码,logRounds 与盐长度没有任何关系。谢谢阿罗诺特。

那么,为什么GenerateSalt(31)几乎立即返回一个值(当它需要大约两倍于GenerateSalt(30)的时间时?

更新

这里是修复:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) {
    // ... snip ...
    uint rounds = 1U << logRounds;
    // ... snip
}

I stumbled across BCrypt.net after reading Jeff Atwood's post about storing passwords which led me to Thomas Ptacek's recommendation to use BCrypt to store passwords. Which finally led me to this C# implementation of BCrypt

In the comments on the last link above someone asked "Why do GenerateSalt(30) take for ever, but GenerateSalt(31) seems to take no time at all?"

I ran BCrypt.HashPassword(password, BCrypt.GenerateSalt(31)) and got my result in 0 milliseconds.

I've been running BCrypt.HashPassword("password", BCrypt.GenerateSalt(30)) for over 5 minutes now and still do not have a result.

I realize we'll probably not need a randomly generated 30 character salt to create our password hashes (or irreversible encryption in BCrypt's case) for years. EDIT I should have read the code a bit, logRounds doesn't have anything to do with the salt length. Thanks Aaronaught.

So, why does GenerateSalt(31) return a value almost instantly (when it should take about twice as long as GenerateSalt(30)?

UPDATE

here is the fix:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) {
    // ... snip ...
    uint rounds = 1U << logRounds;
    // ... snip
}

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

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

发布评论

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

评论(2

二货你真萌 2024-08-27 11:30:58

我怀疑错误就在这里:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) {
    // ... snip ...
    int rounds = 1 << logRounds;
    // ... snip
}

当您为 logRounds 指定 31 时,它会将其计算为 2^32,它无法放入 int 中并溢出,因此哈希实际上是在...呃,零通过中完成的。作者应该使用 uint 来代替。很容易修复!


也想对此发表评论:

我意识到我们可能不需要随机生成的 30 个字符的盐来创建我们的密码哈希......

请注意,logRounds 参数并不指盐中的字符/字节数,它是始终为 16。它指的是哈希计算所需的传递次数的对数底;换句话说,这是一种利用摩尔定律使 bcrypt 规模化的方法,如果计算机的速度足够快来破解现有的哈希值,那么该函数的计算成本就会提高几个数量级。

I suspect that the bug is here:

private byte[] CryptRaw(byte[] password, byte[] salt, int logRounds) {
    // ... snip ...
    int rounds = 1 << logRounds;
    // ... snip
}

When you specify 31 for the logRounds, it computes that as 2^32, which can't fit in an int and overflows, so the hash is actually done in... er, zero passes. The author should have used uint instead. Easy to fix!


Also wanted to comment on this:

I realize we'll probably not need a randomly generated 30 characters salt to create our password hashes...

Note that the logRounds parameter does not refer to the number of characters/bytes in the salt, which is always 16. It refers to the logarithmic base of the number of passes that the hash will take to compute; in other words it's a way to make bcrypt scale with Moore's Law, making the function several orders of magnitude more expensive to compute if computers ever get fast enough to crack existing hashes.

执手闯天涯 2024-08-27 11:30:58

如果使用 GenerateSalt(31) 进行哈希处理几乎立即返回,则这是一个错误。你应该向上游报告(我已经报告了,对于jBCrypt)。 :-)

默认情况下,对数轮数为 10。这意味着(如果我没记错的话)使用了 1024 轮。每次增加对数轮数,轮数就会加倍。

在 30 个对数轮次中,您将进行 1073741824 轮。这理所当然地需要很长时间。在 31 个日志轮次中,应该完成 2147483648 轮,但我怀疑您使用的特定实现会溢出。 :-(

If hashing with GenerateSalt(31) returns almost instantly, that's a bug. You should report that upstream (I have, for jBCrypt). :-)

By default, the log-rounds is 10. This means that (if I remember correctly), 1024 rounds is used. Each time you increment the log-rounds, the number of rounds is doubled.

At 30 log-rounds, you're doing 1073741824 rounds. That rightfully takes a long time. At 31 log-rounds, 2147483648 rounds should be being done, but I suspect that the particular implementation you're using overflows instead. :-(

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