盐值哈希和密码历史记录

4

想知道在每次更改密码时,盐是否对于单个用户是唯一的很重要,还是重复使用相同的盐不会有太大影响。

我目前为每个给定用户更新密码时生成一个新的随机字符串作为盐。这样,每次用户有新密码时也会更换盐。这很容易实现,所以为什么不呢。

嗯...原因就在这里。我需要存储先前的X个密码以确保不重复使用密码。在旧日子里(我上次编写此代码时),我可以只存储以前的MD5哈希,并将新哈希与该列表进行比较。好吧,现在我正在使用盐散列,其中盐每次都是唯一的,因此不再知道先前的盐,这些比较也不再可能。

为了使该系统正常工作,我有两个选择:除了最终哈希之外,还要存储盐的历史记录,或者每次更新密码时为任何一个给定用户重复使用相同的盐。这两者都可以让我构建可与历史记录进行比较的值。

后者工作量较少,但它会失去任何强度吗?从实际角度来看,我认为没有。我想在这里得到第二个意见。谢谢。

为了使问题“可回答”-是否为任何一个用户重复使用相同的盐,以保持可搜索的密码历史记录(以防止密码回收)会有可接受的最小保护减少?

4个回答

6
重复使用相同的盐意味着,如果用户受到黑客的有针对性攻击,他们可以使用“用户的盐”生成一个“密码哈希字典”,因此即使用户更改其密码,黑客也会立即知道新密码而无需进行任何额外的工作。
每次都使用不同的盐。
至于存储MD5哈希值加盐 - 假设您已经存储了盐+哈希值,以验证用户的当前密码。为什么不能仅为历史检查保留完全相同的信息?这样,您可以使用一段代码来执行密码检查,而不是将当前和历史路径分开。它们正在做同样的事情,因此使用相同的代码是有意义的。
编辑:为了解释我的意思,请考虑一个4个字符的盐,附加到密码上...出于论证的目的,想象一下有人只在密码(和盐)中使用A-Z、a-z和0-9。
如果您不提前知道盐(在准备字典攻击时),则为了准备所有8个字符的“人类”密码的字典,您需要哈希62^12个连接的密码。但是,如果您始终知道连接密码的前4个字符将是什么(因为您提前知道盐),则只需哈希62^8个值 - 所有以盐开头的值。它使盐在该特定攻击下无用。
当然,这仅适用于有针对性的用户 - 仅当攻击者可以在密码更改之前和之后都接触到哈希列表时才能使用。它基本上使更改密码作为安全措施的效果降低了。

我不明白“攻击者”如何知道新密码。如果我有一个哈希值,即H(A+S),然后我得到了新的哈希值:H(B+S),我怎么能立即确定B? - Noon Silk
@silky:如果您事先知道S,可以使用该盐预先准备字典攻击。它可以减少需要考虑的可能(B+S)值的数量。 - Jon Skeet
Jon: 显然啊。但攻击者是怎么得到 S 的,而不是新的 S 呢?如果他拿不到新的 S,那他是怎么得到哈希密码的呢?我觉得这不是一个现实的情况。 - Noon Silk
他可以得到新的S,但只有在密码被更改后才能获得。这意味着他必须在密码再次更改之前解决哈希问题。如果盐被重复使用,他可以在密码被更改之前为未来的密码解决哈希问题。 - Jon Skeet
@Jon -- 这差不多就是我想的,但它只涵盖了一个相当狭窄的情况,即某人获得了用户数据表,专注于一个用户,然后频繁地获取用户数据表,或者以刚好的时间再次进行操作。看起来可能性很小。然而,我还是构建了代码,用所有先前的盐来哈希新密码,并将其与所有先前的哈希值进行比较。 - gw

1

在密码哈希中使用盐的另一个原因是为了隐藏两个用户使用相同密码的事实(这并不罕见)。使用不同的哈希,攻击者将无法看到这一点。


1
问题是关于同一用户的历史哈希值,而不是所有用户共享的。 - Kobi

0
首先,停止使用 MD5(如果您在使用它),而改用 SHA-2。MD5、SHA-0 和 SHA-1 都已经过时了。
-- 编辑:
我现在同意 Jon Skeet 的看法,并建议您在每次密码更改时考虑生成新的 salt。这可以涵盖一个小的情况,即攻击者可能会获得 salt+hash,但无法再次访问系统,但仍然可以通过猜测如何将它们组合来计算未来所有密码的哈希值。这个问题很小,并不是那么重要,因为即使离线计算它们,密码长度也需要非常小(比如 8 个字符)才能实用。
其次,我们需要考虑盐的目的,看看是否重要。盐的目的是防止针对仅有密码列表的离线攻击。
基于此,如果在密码更改前后,获取盐的难度是相等的,我认为没有必要使用新的盐(它的风险和以前一样)。这会增加额外的复杂性,而在实施复杂性时,大多数安全问题都会出现。

1
嗯,“停止使用MD5……并使用……MD5……”;-)是的,我的对MD5的提及是指“旧时代”,也就是很久以前它还是安全的时候。现在我们使用更好的东西,而且盐值也相当长。攻击者几乎总是可以获得完整的盐值列表——不仅仅是密码。每次更改盐值都会使攻击者必须重新生成特定用户的彩虹表,而不是重复使用它,所以这就是为什么它很有用。 - gw

0

我可能在这里非常愚蠢,但是,你会把盐存储在哪里,以使得那些有足够权限获取哈希密码的人无法访问。


盐值存储在哈希密码旁边(可能在同一行),攻击者也会获取到它们,但需要花费大量时间来尝试找到匹配项(对于任何用户或特定用户)。 - Kobi
1
理论上,将它们分开并没有太多实际的附加价值。盐的存在使预先计算的彩虹表变得无用。因此,现在有人必须从头开始计算一个新的彩虹表,并增加盐的深度(以及使用盐的各种方式:前缀、后缀、拆分、交错等)。即使你知道盐的内容,计算这个新表所需的时间和资源成本也太高了,不值得去尝试。总有一天,SkyNet会开始计算和存储所有排列组合,但在它完成之前,它或者我们都将灭绝,这就不重要了。;-) - gw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接