Coda Hale 的文章“如何安全地存储密码”声称:
bcrypt 内置了盐以防止彩虹表攻击。
他引用了这篇论文,其中说在 OpenBSD 的实现中bcrypt:
bcrypt
OpenBSD 从一个 arcfour (arc4random(3)) 密钥流生成 128 位 bcrypt salt,并使用内核从设备计时收集的随机数据播种。
我不明白这是怎么回事。在我对盐的概念中:
当我使用带有 bcrypt 的 Devise(Rails 登录管理器)时,数据库中没有 salt 列,所以我很困惑。如果盐是随机的并且没有存储在任何地方,我们如何可靠地重复散列过程?
简而言之, bcrypt 怎么能有内置的 salts 呢?
这是 bcrypt:
生成随机盐。“成本”因素已预先配置。收集密码。
使用盐和成本因子从密码中派生加密密钥。用它来加密一个众所周知的字符串。 存储 成本、 盐 和密文。因为这三个元素的长度是已知的,所以很容易将它们连接起来并将它们存储在一个字段中,然后可以将它们分开。
当有人尝试进行身份验证时,检索存储的成本和盐。从输入的密码、成本和盐中派生出一个密钥。加密相同的众所周知的字符串。如果生成的密文与存储的密文匹配,则密码匹配。
Bcrypt 的运行方式与基于 PBKDF2 等算法的更传统方案非常相似。主要区别在于它使用派生密钥来加密已知的纯文本。其他方案(合理地)假设密钥派生函数是不可逆的,并直接存储派生密钥。
存储在数据库中的bcrypt“哈希”可能如下所示:
$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
这实际上是三个字段,由“$”分隔:
2a
10
vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
此示例取自Coda Hale 的 ruby 实现的文档。