有人不储存盐吗?

信息安全 验证 哈希
2021-08-25 03:49:07

我们今天在课堂上讨论了密码哈希和加盐。我们的教授对我的盐的用例有非常不同的理解,并说您可能根本不存储盐,只需检查所有可能的盐的每次登录尝试并授权是否匹配。

我真的没有看到任何意义,因为现在我的服务更容易受到暴力攻击(发送一个密码,服务器检查很多),但我想对散列密码的纯字典攻击更安全一些.

那么有没有人们真正会这样做的用例呢?

4个回答

不储存盐是个坏建议。

盐的主要目的是每个用户密码都必须被单独攻击。

如果您不存储盐,那么正如您所说,您需要尝试每个盐组合以验证密码。如果您需要检查每个盐组合,这意味着盐不能太长(您在评论中提到了 12 位)。如果盐不长,则意味着盐会为许多用户重复。如果对多个用户重复,则意味着攻击者将能够同时攻击多个用户,这将节省攻击者的时间。

通过这样做,您几乎完全违背了使用盐的目的。

一种“秘密”盐被称为胡椒

来自维基百科:

除了盐值之外,还可以将胡椒添加到密码中。胡椒与盐的作用相似,但是盐通常与被散列的值一起存储,对于要定义为胡椒的东西,它应该满足以下标准之一,将其定义为更仔细隐藏的“秘密”比盐值:

  • 辣椒与要散列的值分开保存
  • 辣椒是为每个要散列的值随机生成的(在一组有限的值内),并且永远不会存储。当针对匹配的哈希值测试数据时,这是通过迭代对辣椒有效的一组值来完成的,然后将每个值依次添加到要测试的数据中(通常通过将其添加到数据后缀),在对组合值运行加密哈希函数之前。

辣椒的优点是攻击者现在必须猜测每个明文条目的辣椒值的可能排列数量。

Peppers 会增加特定哈希的攻击长度,而 salt 不会。

请记住,盐是对预先计算的哈希值的有效缓解,它会使攻击者花费很长时间来攻击一组哈希值。但是,如果只关注一个散列,并且不使用预先计算的散列,则盐不会增加攻击的长度。然而,Pepper 迫使攻击者对每个明文密码进行多次猜测,即使是单个哈希也是如此。

这样一来,辣椒就类似于按键拉伸

大多数实现更喜欢键拉伸而不是辣椒。

我个人的观察是,大多数实现更喜欢键拉伸而不是辣椒。我没有这方面的参考资料,因此读者可以在评论中提供支持或反对的参考资料。人们往往更喜欢密钥拉伸,因为它具有已知和预期的性能成本和安全优势。为了计算第 N 轮哈希,必须计算 N 个哈希。然而,对于辣椒,只能计算预期的尝试次数。考虑一个 1 字节的辣椒,攻击者需要 256 次猜测来猜测所有可能的组合,但预期值为128,攻击者可以(平均 1/256 次)在第一次尝试时猜测该值。

Peppers 和 Key Stretching 可以相互对抗。

密钥拉伸是有效的,因为您可以根据您希望计算散列所花费的时间长度来设置轮数。假设您希望在当前硬件上进行一次检查需要半秒钟,您只需增加轮数直到发生这种情况。

使用辣椒,因为您需要为每个密码猜测多个值,所以辣椒的大小必须与轮数成反比,以保持计算时间恒定。

哈希实现的实用建议

密码/哈希实现的最佳建议是使用众所周知的方法和经过测试的库。您应该使用带有独特盐和多轮的bcryptpbkdf2 。这些算法往往在许多语言和框架中都有众所周知的实现。如果您碰巧找到了一个众所周知且经过测试的库,其中包含一个胡椒,除了盐和键拉伸之外,您可能值得花时间使用它,但额外的好处通常超过性能成本。

背景:您应该使用慢速密码哈希。(即 bcrypt)“慢”是指计算成本高昂,使用 DoS 保护需要超过 100 毫秒(在您的硬件上) *来测试单个密码。这是为了增加(在攻击者硬件上)通过蛮力找到密码所需的处理能力,如果哈希被盗。

强烈推荐每个用户唯一的盐。(在 bcrypt 的情况下,它是自动生成的) Salt 应该是高度唯一的(即 long & random),但不是 secret使用唯一的盐意味着攻击者必须为每个用户运行一个单独的暴力作业

如果没有“盐”,攻击者可以立即使用彩虹桌,完全没有蛮力。

如果您只使用“共享盐”,那么攻击者可以通过一个暴力作业破解所有用户的密码(不像彩虹桌那么快,但仍然比每个人单独的蛮力作业要容易得多)


答案:如果您要“不存储”盐(正如您的教授所建议的那样,“在运行时强制哈希”)

  • 可能的盐必须很少
  • 哈希必须快得多

这将完全违背Salt的目的,严重削弱慢散列的好处。这是你教授的一个重大设计错误。基本上,他正在推出自己的密码存储方案,他应该使用经过严格审查的bcrypt算法(或scryptPBKDF2,因为它打算使用


* 正如@Navin评论的那样,这将是一个潜在的 DoS 攻击媒介。一种解决方案是限制每个 IP 和每个用户名的每小时尝试次数。您也可以将散列的“缓慢”减少到仅需要 10 毫秒。从“被盗散列”的角度来看,这还不如 100 毫秒,但仍然比“微秒”好得多。

你的教授不正确。加盐的目的是增加散列密码的熵,以防止对它们进行任何类型的预计算攻击,并防止来自不同用户的相同密码具有相同的散列值。

能够尝试所有可能的盐值意味着盐中的熵必须非常低,这意味着可以通过彩虹表进行预计算。