Security bcrypt如何具有内置盐?

Security bcrypt如何具有内置盐?,security,hash,internals,bcrypt,Security,Hash,Internals,Bcrypt,Coda Hale的文章声称: bcrypt内置了盐来防止彩虹表攻击 他引用了OpenBSD实现的bcrypt: OpenBSD从arcfour生成128位bcrypt盐 (arc4random(3))密钥流,在内核中播种随机数据 从设备定时收集数据 我不明白这是怎么回事。在我对盐的概念中: 每个存储的密码都需要不同,因此必须为每个密码生成一个单独的彩虹表 它需要存储在某个地方,以便可以重复:当用户尝试登录时,我们会尝试使用他们的密码,重复最初存储他们密码时的salt和hash过程,并进行比较

Coda Hale的文章声称:

bcrypt内置了盐来防止彩虹表攻击

他引用了OpenBSD实现的
bcrypt

OpenBSD从arcfour生成128位bcrypt盐 (arc4random(3))密钥流,在内核中播种随机数据 从设备定时收集数据

我不明白这是怎么回事。在我对盐的概念中:

  • 每个存储的密码都需要不同,因此必须为每个密码生成一个单独的彩虹表
  • 它需要存储在某个地方,以便可以重复:当用户尝试登录时,我们会尝试使用他们的密码,重复最初存储他们密码时的salt和hash过程,并进行比较
当我将Devise(Rails登录管理器)与bcrypt一起使用时,数据库中没有salt列,所以我感到困惑。如果盐是随机的,没有存储在任何地方,我们如何可靠地重复散列过程


简而言之,bcrypt怎么可能有内置的盐呢?

我认为这个短语应该用如下措辞:

bcrypt在生成的哈希中内置了盐,以防止彩虹表攻击

bcrypt
实用程序本身似乎没有维护盐列表。相反,盐是随机生成的,并附加到函数的输出中,以便稍后记住它们(根据)。换句话说,
bcrypt
生成的“散列”不是只是散列。相反,它是哈希和连接的盐。

这是bcrypt:

生成一个随机的盐。“成本”因素已预先配置。收集密码

使用salt和成本因子从密码派生加密密钥。使用它来加密已知字符串。存储成本、盐和密码文本。因为这三个元素有一个已知的长度,所以很容易将它们连接起来并存储在一个字段中,但以后可以将它们分开

当有人试图进行身份验证时,检索存储的成本和盐。从输入密码、成本和salt派生密钥。加密相同的已知字符串。如果生成的密码文本与存储的密码文本匹配,则密码是匹配的

Bcrypt的运行方式与基于PBKDF2等算法的传统方案非常相似。主要区别在于它使用派生密钥加密已知的纯文本;其他方案(合理地)假设密钥派生函数是不可逆的,并直接存储派生密钥


存储在数据库中的
bcrypt
“哈希”可能如下所示:

$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9CGLCZEIGDMVR5YUP1KOUYTA

这实际上是三个字段,由“$”分隔:

  • 2a
    标识所使用的
    bcrypt
    算法版本
  • 10
    是成本因素;使用了210次密钥派生函数迭代(顺便说一句,这还不够。我建议花费12次或更多)
  • vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
    是salt和密码文本,以修改后的Base-64进行连接和编码。前22个字符解码为salt的16字节值。其余字符是密码文本,用于比较身份验证

此示例取自Spring Security的PasswordEncoder接口文档

 * @param rawPassword the raw password to encode and match
 * @param encodedPassword the encoded password from storage to compare with
 * @return true if the raw password, after encoding, matches the encoded password from
 * storage
 */
boolean matches(CharSequence rawPassword, String encodedPassword);

这意味着,需要匹配用户下次登录时再次输入的密码,并将其与上次登录/注册期间存储在数据库中的Bcrypt编码密码匹配

为了让事情更清楚

注册/登录方向-> password+salt使用由:cost、salt和密码生成的密钥进行加密。我们将该加密值称为
密文
。然后,我们将salt附加到此值,并使用base64对其进行编码。将成本附加到它,这是从
bcrypt
生成的字符串:

$2a$COST$BASE64

最终存储该值


攻击者需要做什么才能找到密码?(其他方向这是一个简单的术语

Bcrypt没有数据库,它存储盐

salt以base64格式添加到哈希中

问题是bcrypt没有数据库时如何验证密码


bcrypt所做的是从密码散列中提取salt…使用提取的salt加密普通密码,并将新散列与旧散列进行比较,看它们是否相同…

OK,因此我注册了一个站点并选择了一个密码“foo”。
bcrypt
添加了一个随机的salt“akd2!*”,结果是“fooakd2!*”,它被散列并存储。稍后,我尝试使用密码“bar”登录。要查看我是否正确,它需要散列“barakd2!*”。如果盐是随机生成的,它如何知道如何在散列和比较之前将其添加回“bar”?@Nathan:
bcrypt
知道如何从生成的输出中提取盐(存储在数据库中)。在进行身份验证时,
bcrypt
将原始输出分为散列和salt组件。salt组件应用于用户键入的传入密码。要回答Nathan Long的评论,一个很好的思路是,salt并不意味着机密。这就是为什么salt包含在输出中的原因正如上面指出的答案之一,salt是用来防止彩虹表的,彩虹表是常用密码的列表,或者只是蛮力,等等不同密码的列表,但是被散列。没有salt,数据库a中密码的散列将与数据库B中密码的散列相同。salt只是在t上更改他散列值