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

Dav*_*och 22 c# salt bcrypt bcrypt.net

在阅读了Jeff Atwood关于存储密码的帖子后,我偶然发现了BCrypt.net,这让我想到了Thomas Ptacek建议使用BCrypt来存储密码.这最终促成了我对BCrypt的C#实现

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

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

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

我意识到我们可能不需要随机生成的30个字符的盐来创建我们的密码哈希值(或BCrypt案例中的不可逆加密)多年.编辑我应该读一下代码,logRounds与salt长度没有任何关系.谢谢Aaronaught.

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

UPDATE

这是修复:

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

Aar*_*ght 25

我怀疑这个错误在这里:

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

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


还想对此发表评论:

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

注意,logRounds参数不参考字符数/中的盐,这始终是16.它是指数的对数基的经过散列将采取来计算字节; 换句话说,它是一种方法,使摩尔定律bcrypt规模,使得功能幅度来计算,如果计算机永远得到足够快的速度来破解现有哈希更加昂贵几个数量级.


Chr*_*ung 10

如果GenerateSalt(31)几乎立即返回哈希,那就是一个错误.你应该报告上游(我有,对于jBCrypt).:-)

默认情况下,对数轮是10.这意味着(如果我没记错的话),使用1024轮.每次增加对数轮次时,轮数增加一倍.

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