91

更新:我最近从这个问题中了解到,在下面的整个讨论中,我(我相信其他人也这样做)有点令人困惑:我一直称之为彩虹表的东西实际上被称为哈希表。彩虹表是更复杂的生物,实际上是 Hellman Hash Chains 的一种变体。尽管我相信答案仍然是相同的(因为它不归结为密码分析),但某些讨论可能有点歪曲。
问题:“什么是彩虹表,它们是如何使用的?


通常,我总是建议使用加密强度高的随机值作为盐,与散列函数(例如密码)一起使用,例如防止彩虹表攻击。

但是,盐在加密上是否真的有必要是随机的?在这方面是否有任何唯一值(每个用户唯一,例如 userId)就足够了?事实上,它会阻止使用单个彩虹表来破解系统中的所有(或大部分)密码......
但是缺乏熵真的会削弱散列函数的加密强度吗?


注意,我不是在问为什么要使用盐,如何保护它(它不需要),使用单个常量哈希(不要),或者使用什么样的哈希函数。
只是盐是否需要熵。


到目前为止,感谢所有人的回答,但我想专注于我(有点)不太熟悉的领域。主要是对密码分析的影响——如果有人对密码数学 PoV 有一些意见,我将不胜感激。
此外,如果还有其他未考虑的向量,那也是很好的输入(请参阅@Dave Sherohman 关于多个系统的观点)。
除此之外,如果您有任何理论、想法或最佳实践 - 请用证据、攻击场景或经验证据支持这一点。甚至是对可接受的权衡的有效考虑......我熟悉这个主题的最佳实践(资本 B 资本 P),我想证明这实际上提供了什么价值。


编辑:这里有一些非常好的答案,但我认为正如@Dave 所说,它归结为常见用户名的彩虹表......以及可能不太常见的名称。但是,如果我的用户名是全球唯一的怎么办?对于我的系统来说不一定是唯一的,但对于每个用户来说都是独一无二的——例如电子邮件地址。
没有动力为单个用户构建 RT(正如@Dave 强调的那样,盐不是保密的),这仍然会阻止集群。唯一的问题是我可能在不同的站点上拥有相同的电子邮件和密码 - 但无论如何盐不会阻止这种情况。
所以,它回到密码分析——熵是否必要?(我目前的想法是从密码分析的角度来看没有必要,但出于其他实际原因。)

4

9 回答 9

159

Salt 传统上存储为哈希密码的前缀。这已经让任何有权访问密码哈希的攻击者都知道了。是否使用用户名作为盐不会影响该知识,因此,它不会影响单系统安全性。

但是,使用用户名或任何其他用户控制的值作为盐会降低跨系统安全性,因为在使用相同密码散列算法的多个系统上具有相同用户名和密码的用户最终会得到相同的密码散列这些系统中的每一个。我不认为这是一项重大责任,因为作为攻击者,我会先尝试已知目标帐户已在其他系统上使用过的密码,然后再尝试任何其他方式来破坏该帐户。相同的哈希值只会提前告诉我已知密码会起作用,它们不会使实际攻击变得更容易。(但请注意,帐户数据库的快速比较将提供更高优先级目标的列表,因为它会告诉我谁在重用密码,谁没有重用密码。)

这个想法的更大危险是用户名通常会被重复使用——例如,几乎任何你想访问的网站都会有一个名为“Dave”的用户帐户,而“admin”或“root”甚至更常见——这会使构建针对具有这些通用名称的用户的彩虹表更容易和更有效。

这两个缺陷都可以通过在散列密码之前向密码添加第二个盐值(固定和隐藏或像标准盐一样暴露)来有效解决,但是,在这一点上,你也可以使用标准熵盐代替将用户名放入其中。

编辑添加: 很多人都在谈论熵以及盐中的熵是否重要。它是,但不是因为大多数评论似乎认为的原因。

一般的想法似乎是熵很重要,因此攻击者很难猜到盐。这是不正确的,事实上,完全不相关。正如许多人多次指出的那样,受盐影响的攻击只能由拥有密码数据库的人进行,拥有密码数据库的人可以查看每个帐户的盐是什么。当您可以轻松查找它时,它是否可以猜测并不重要。

熵很重要的原因是为了避免盐值的聚类。如果盐是基于用户名的,并且您知道大多数系统都有一个名为“root”或“admin”的帐户,那么您可以为这两种盐制作一个彩虹表,它将破解大多数系统。另一方面,如果使用随机的 16 位盐并且随机值大致均匀分布,那么您需要一个彩虹表来存储所有 2^16 种可能的盐。

这不是要阻止攻击者知道个人帐户的盐是什么,而是要不给他们一个大而肥的目标,这种盐将用于相当大比例的潜在目标。

于 2009-02-11T13:28:13.227 回答
30

使用高熵盐对于安全地存储密码是绝对必要的。

获取我的用户名“gs”并将其添加到我的密码“MyPassword”中会得到 gsMyPassword。使用彩虹表很容易打破这一点,因为如果用户名没有足够的熵,则可能是该值已经存储在彩虹表中,尤其是在用户名很短的情况下。

另一个问题是您知道用户参与了两个或多个服务的攻击。有很多常见的用户名,可能最重要的用户名是 admin 和 root。如果有人创建了一个彩虹表,其中包含最常见用户名的盐,他可以使用它们来破坏帐户。

他们曾经有一个 12-bit salt。12 位是 4096 种不同的组合。这还不够安全,因为现在可以轻松存储这么多信息。这同样适用于 4096 个最常用的用户名。您的一些用户可能会选择属于最常见用户名的用户名。

我找到了这个密码检查器,它可以计算出你密码的熵。在密码中具有较小的熵(例如通过使用用户名)使得彩虹表更容易,因为它们试图覆盖至少所有具有低熵的密码,因为它们更有可能发生。

于 2009-02-11T13:40:13.573 回答
8

确实,单独的用户名可能是有问题的,因为人们可能会在不同的网站之间共享用户名。但是,如果用户在每个网站上使用不同的名称,这应该是没有问题的。那么为什么不让它在每个网站上都是独一无二的呢。哈希密码有点像这样

hashfunction("www.yourpage.com/"+username+"/"+password)

This should solve the problem. I'm not a master of cryptanalysis, but I sure doubt that the fact that we don't use high entropy would make the hash any weaker.

于 2010-10-26T17:18:18.847 回答
7

我喜欢同时使用这两种方法:每条记录的高熵随机盐,以及记录本身的唯一 ID。

尽管这并没有增加对字典攻击等的安全性,但它确实消除了有人将他们的盐和哈希复制到另一条记录以用他们自己的密码替换密码的边缘情况。

(诚​​然,很难想到这种情况适用,但在安全方面,我认为安全带和背带没有任何危害。)

于 2009-02-11T13:34:18.987 回答
3

散列函数的强度不是由它的输入决定的!

使用攻击者已知的盐显然会使构建彩虹表(特别是对于像root这样的硬编码用户名)更具吸引力,但它不会削弱hash。使用攻击者未知的盐将使系统更难攻击。

用户名和密码的连接可能仍然为智能彩虹表提供一个条目,因此使用一系列伪随机字符的盐,与散列密码一起存储可能是一个更好的主意。例如,如果我有用户名“potato”和密码“beer”,则您的哈希的串联输入是“potatobeer”,这是彩虹表的合理条目。

每次用户更改密码时更改盐值可能有助于抵御长时间的攻击,实施合理的密码策略(例如混合大小写、标点符号、最小长度、n周后更改)也将有助于抵御长期攻击。

但是,我想说您选择的摘要算法更重要。例如,对于生成彩虹表的人来说,使用 SHA-512 比使用 MD5 更痛苦。

于 2009-02-11T12:44:43.583 回答
3

如果盐是已知的或容易猜到的,那么您并没有增加字典攻击的难度。甚至可以创建一个修改后的彩虹表,将“恒定”盐考虑在内。

使用独特的盐增加了 BULK 字典攻击的难度。

具有独特的、加密的强盐值将是理想的。

于 2009-02-11T13:21:57.893 回答
3

我会说,只要每个密码的盐不同,你就可以了。加盐的要点是,您不能使用标准的彩虹表来解决数据库中的每个密码。因此,如果您对每个密码应用不同的盐(即使它不是随机的),攻击者基本上必须为每个密码计算一个新的彩虹表,因为每个密码使用不同的盐。

使用具有更多熵的盐并没有多大帮助,因为在这种情况下假定攻击者已经拥有数据库。由于您需要能够重新创建哈希,因此您必须已经知道盐是什么。因此,无论如何,您都必须将盐或构成盐的值存储在文件中。在像 Linux 这样的系统中,获取盐的方法是已知的,因此拥有秘密盐是没有用的。您必须假设拥有您的哈希值的攻击者也可能知道您的盐值。

于 2009-02-11T13:51:40.613 回答
1

Salt应该具有尽可能多的熵,以确保如果给定的输入值被多次散列,则生成的散列值将尽可能接近,总是不同的。

在盐中使用尽可能多的熵的不断变化的盐值将确保散列的可能性(例如,密码+盐)将产生完全不同的散列值。

盐中的熵越少,生成相同盐值的机会就越大,因此生成相同哈希值的机会就越大。

当输入已知且“恒定”时,哈希值的本质是“恒定”的,这使得字典攻击或彩虹表如此有效。通过尽可能多地改变生成的哈希值(通过使用高熵盐值)确保对相同的输入+随机盐进行哈希处理会产生许多不同的哈希值结果,从而击败(或至少大大降低)彩虹表的有效性攻击。

于 2009-02-11T13:06:36.900 回答
-1

熵是盐值的点。

如果盐背后有一些简单且可重复的“数学”,那么它与盐不存在相同。只需添加时间价值就可以了。

于 2009-02-11T12:40:59.207 回答