为什么BCrypt.net GenerateSalt(31)会立即回归?

时间:2010-02-08 14:55:32

标签: c# salt bcrypt bcrypt.net

我在阅读Jeff Atwood's post about storing passwords之后偶然发现了BCrypt.net,这导致我向Thomas Ptacek建议use BCrypt存储密码。这最终导致我this C# implementation of BCrypt

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

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

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

我意识到我们可能不需要随机生成的30个字符的盐来创建我们的密码哈希(或irreversible encryption in BCrypt's case)多年。 编辑我应该读一下代码,logRounds与salt长度没有任何关系。谢谢Aaronaught。

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

更新

这是修复:

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

2 个答案:

答案 0 :(得分:25)

我怀疑这个错误在这里:

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

当你为logRounds指定31时,它计算为2 ^ 32,它不能适合int并溢出,所以散列实际上是在......呃,零通过。作者应该使用uint代替。易于修复!


也想对此发表评论:

  

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

请注意,logRounds参数不是指salt中的字符数/字节数,它始终为16.它指的是哈希计算所需的传递次数的对数基数;换句话说,这是一种利用摩尔定律进行密码扩展的方法,如果计算机的速度足以破解现有的哈希值,那么计算这个函数的成本会高出几个数量级。

答案 1 :(得分:10)

如果使用GenerateSalt(31)的散列几乎立即返回,那就是一个错误。你应该报告上游(我有,对于jBCrypt)。 : - )

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

在30轮对话中,你正在进行1073741824轮。这需要很长时间。在31个对数轮,应该完成2147483648轮,但我怀疑你正在使用的特定实现溢出。 : - (