哈希密码时,可以使用哈希密码作为盐吗?

信息安全 密码 哈希
2021-08-15 08:48:11

我不喜欢这个主意。但我无法提出反对它的技术论据。有人可以向我解释吗?基本思想是:

$passwd = 'foo';
$salt = hash($passwd);
$finalHash = hash($passwd . $salt);

$finalHash 将存储在数据库中。我确实理解具有相同密码“foo”的两个用户将具有相同的哈希值。但这只是该计划的一个弱点。这种碰撞虽然很危险,但并不是我们使用带哈希的盐的主要原因。但到目前为止,这是我提出的唯一技术反对意见来反对这一点。

我的理解是盐应该是随机的,并且对于哈希的每次使用都应该是唯一的。而且这个方案似乎违反了这两个要求。但我无法弄清楚攻击者如何从这种看似有缺陷的加盐哈希使用中受益。

4个回答

要回答这个问题,首先必须了解为什么需要盐。如何安全地散列密码; 这是已接受答案的摘录:


Salts:攻击者相对于防御者的优势之一是并行性攻击者通常会获取完整的哈希密码列表,并有兴趣破解尽可能多的密码。他可能会尝试同时攻击几个。例如,攻击者可能会考虑一个潜在的密码,对其进行哈希处理,然后将该值与 100 个哈希密码进行比较;这意味着攻击者分担对多个受攻击密码进行散列的成本类似的优化是预计算表,包括彩虹表这仍然是平行性,坐标的时空变化。

所有使用并行性的攻击的共同特征是它们对使用完全相同的散列函数处理的多个密码起作用加盐不是使用一种散列函数,而是使用许多不同的散列函数理想情况下,密码散列的每个实例都应该使用自己的散列函数。是一种在一大群散列函数中选择特定散列函数的方法。正确应用盐将完全阻止并行攻击(包括彩虹表)。


所以你的盐的问题是它不会干扰并行化破坏哈希,这正是盐渍的目的。我强烈建议您阅读原始答案,它对腌制有进一步的建议。

如果您将密码用作“盐”,那么您根本没有使用任何盐;你只是在散列密码。

如果两个用户选择相同的密码,他们最终会得到相同的散列密码。这就是人们常说的,好像它解释了问题一样,但似乎大多数人都弄错了。他们认为这意味着“冲突”,由于某种原因,在谈论密码散列时,许多人认为这是一个坏词。但这是错误的,不是重点。

关键是决定论假设我肆无忌惮地为 1000 个用户获取哈希密码的副本(例如,我从您的垃圾箱中检索了旧的备份磁带)。然后我可以“尝试”潜在的密码:我散列一个潜在的密码(使用密码本身作为“盐”),然后我在 1000 个散列值中查找值。这意味着通过支付一次哈希的计算代价,我实际上尝试了一千个用户+密码对。我正在并行攻击一千个散列密码,其成本与攻击单个密码相同。这种并行性可以以多种形式表现出来,包括彩虹表。

当攻击 1000 个散列密码的成本是攻击 1 个散列密码的成本的 1000 倍时,我们真的更喜欢它。为此,您需要真正的盐,即对于不同用户来说不同的盐,即使他们碰巧使用相同的密码——实际上,当他们可能使用相同的密码时。当没有真正的盐时,并行攻击之所以起作用,不是因为某些用户确实选择了相同的密码,而是因为如果他们选择了相同的密码,那么他们将获得相同的散列值。他们实际上并不需要选择相同的密码来触发弱点。

使用用户名作为盐要好得多。请注意,这不好;但还是更好。更好的是,实际上相当安全的是使用随机盐。

如果两个用户的密码相同,那么盐值将相同,从而导致两者的哈希值相同。这是不可取的,因为它会泄露有关密码的信息。如果 Alice 闯入您的数据库并看到 Bob 具有与她相同的哈希值,她就可以使用该信息。选择可以保证是独一无二的东西。

但是,您最大的问题是您在使用hash时没有任何关于该哈希是什么的信息。根据系统的不同,它甚至可能是旧的糟糕的 3DES 实现,它会删除第 8 个字符之后的所有内容。您应该使用适当的 KDF,例如 bcrypt 或 PBKDF2。

使用用户名或密码作为盐对我来说听起来不是一个好主意。

攻击者可能会合理地猜测您正在使用用户名或密码作为盐。根据您的设置,假设攻击者可以访问用户名可能是非常合理的。

此外,根据您的系统在执行密码方面的严格程度,攻击者可以利用出现在已知/常用密码字典中的密码,并且由于这些密码被用作盐,您的系统将容易受到这种攻击。

使用不依赖用户输入的盐是一个更好的主意。