Coda Hale的文章“如何安全存储密码”声称:
Bcrypt内置盐,以防止彩虹表攻击。
他引用了这篇论文,其中说在OpenBSD的bcrypt实现中:
OpenBSD从arcfour生成128位bcrypt盐
(arc4random(3))密钥流,在内核中播种随机数据
从设备计时收集。
我不明白这是怎么回事。在我对盐的概念中:
对于每个存储的密码,它都需要是不同的,这样就必须为每个密码生成一个单独的彩虹表
它需要存储在某个地方,以便它是可重复的:当用户试图登录时,我们获取他们的密码尝试,重复与最初存储密码时相同的盐和哈希过程,并进行比较
当我使用bcrypt的设计(Rails登录管理器)时,数据库中没有盐列,所以我很困惑。如果盐是随机的,并且没有存储在任何地方,我们如何可靠地重复哈希过程?
简而言之,bcrypt如何具有内置盐?
这是bcrypt:
生成一个随机的盐。“成本”因素已预先配置。收集密码。
使用盐和成本因子从密码派生加密密钥。使用它来加密一个众所周知的字符串。存储成本、盐和密文。因为这三个元素有一个已知的长度,所以很容易将它们连接起来并存储在一个字段中,但之后还可以将它们分开。
当有人尝试验证时,检索存储的成本和盐。从输入的密码、成本和盐派生一个密钥。加密相同的知名字符串。如果生成的密文与存储的密文相匹配,则表示密码匹配。
Bcrypt的操作方式与基于PBKDF2等算法的更传统的方案非常相似。主要区别是它使用派生密钥来加密已知的纯文本;其他方案(合理地)假定密钥派生函数是不可逆的,并直接存储派生的密钥。
存储在数据库中的bcrypt“哈希”可能是这样的:
2美元$ vI8aWBnW3fID.ZQ4 / zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa 10美元
这实际上是三个字段,用“$”分隔:
2a标识使用的bcrypt算法版本。
10是成本因子;使用了210次密钥推导函数迭代(顺便说一下,这是不够的。我建议12美元或更多。)
vI8aWBnW3fID.ZQ4 / zo1G.q1lRps。9cGLcZEiGDMVr5yUP1KUOYTa是盐和密文,在修改的Base-64中连接和编码。前22个字符解码为盐的16字节值。其余字符为密文,用于比较验证。
这个例子摘自Coda Hale ruby实现的文档。
这是bcrypt:
生成一个随机的盐。“成本”因素已预先配置。收集密码。
使用盐和成本因子从密码派生加密密钥。使用它来加密一个众所周知的字符串。存储成本、盐和密文。因为这三个元素有一个已知的长度,所以很容易将它们连接起来并存储在一个字段中,但之后还可以将它们分开。
当有人尝试验证时,检索存储的成本和盐。从输入的密码、成本和盐派生一个密钥。加密相同的知名字符串。如果生成的密文与存储的密文相匹配,则表示密码匹配。
Bcrypt的操作方式与基于PBKDF2等算法的更传统的方案非常相似。主要区别是它使用派生密钥来加密已知的纯文本;其他方案(合理地)假定密钥派生函数是不可逆的,并直接存储派生的密钥。
存储在数据库中的bcrypt“哈希”可能是这样的:
2美元$ vI8aWBnW3fID.ZQ4 / zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa 10美元
这实际上是三个字段,用“$”分隔:
2a标识使用的bcrypt算法版本。
10是成本因子;使用了210次密钥推导函数迭代(顺便说一下,这是不够的。我建议12美元或更多。)
vI8aWBnW3fID.ZQ4 / zo1G.q1lRps。9cGLcZEiGDMVr5yUP1KUOYTa是盐和密文,在修改的Base-64中连接和编码。前22个字符解码为盐的16字节值。其余字符为密文,用于比较验证。
这个例子摘自Coda Hale ruby实现的文档。