如果您有多个密码哈希,所有哈希都使用相同的哈希函数,是否可以使用它来以任何方式加速原始密码的检索?
(我发现了“如果您有多个哈希值,是否更容易获得原始密码”的问题,但这似乎是在谈论相同密码的多个哈希值,但使用不同的哈希函数创建。)
如果您有多个密码哈希,所有哈希都使用相同的哈希函数,是否可以使用它来以任何方式加速原始密码的检索?
(我发现了“如果您有多个哈希值,是否更容易获得原始密码”的问题,但这似乎是在谈论相同密码的多个哈希值,但使用不同的哈希函数创建。)
纯散列函数是确定性的,这意味着如果你散列任何给定的值,你应该总是得到相同的散列。5f4dcc3b5aa765d61d8327deb882cf99 始终是“密码”的 MD5 哈希。您可以在不同的机器上尝试使用不同语言编写的 MD5 实现,并且假设它们是正确的实现,您应该始终通过调用 md5("password") 或特定语言等效项获得相同的哈希值。
但是,在密码存储系统中,这是一个非常糟糕的属性。为了混淆,更好的密码存储方法使用盐。在这种情况下,被散列的字符串会针对每条记录进行更改。不是每个使用“密码”的人都获得相同的输出哈希,而是由“密码+盐”(或“盐+密码”、“密码+盐+字”或任何其他合并生成。对于这个问题),所以你会得到一堆不同的哈希值:
可以看出,这些都没有任何特别的共同特征,即使使用 MD5 哈希算法,这对于密码存储来说是一个糟糕的选择。(前两个中位置 8 和 9 的一对“b”只是巧合)。
这是因为 MD5 实现了“雪崩”效应——单个输入位的变化将导致大量输出发生变化(由于各种分析原因,理想情况下约为 50%)。
所有这些结合起来意味着即使使用上面使用的短盐,确定“密码”一词在三个哈希输入中的唯一方法是尝试所有可能性。
这取决于所使用的散列函数 - 您可以构建一个散列函数,其中添加类似的盐会导致输出发生类似的变化(因此“passwordsalt”和“passwordsals”在散列时只有少量变化),但那是对于用于密码存储的散列函数而言,这不是典型的。
此外,现代密码存储建议建议使用 bcrypt 或 scrypt 之类的东西,它们都会生成强盐作为哈希初始化的一部分:
所有这些都是“密码”的散列 - 拥有这三个对你一点帮助都没有。
加密散列函数是一个确定性函数,因此如果您使用相同的函数对相同的密码进行多次散列,您应该得到相同的输出。或者,换一种说法,如果您并不总是得到相同的输出,那么这意味着该函数是一个密码散列函数,具有一些被称为“盐”的注入随机性。
如果密码散列函数不错并且使用得当(例如它是 bcrypt),那么不,有几个散列将无济于事。要看到这一点,请考虑一下,从形式上讲,密码散列函数不是一个函数,而是一个完整的函数族,盐实际上是该族中特定函数的选择。使用不同的盐,您可以获得不同的函数,这些函数应该彼此“真正不同”,因此不存在计算N哈希的计算捷径,其成本低于计算成本的N倍。(实际上,用数学上正确的形式写下该属性非常困难,但上面的总结应该足以回答这个问题。)
因此,只有在重用盐值时,您才能提高攻击速度。选择好的盐是为了它们是独一无二的,如果盐是随机选择的并且足够大,这实际上很容易。此外,在您的情况下,如果将盐值重用于相同的密码,那么您将获得与以前相同的哈希值,而这根本不会获得任何东西。
当然,如果手头的密码散列函数做了一些奇怪和不熟练的事情,那么一切都会发生。我的答案是好的密码散列函数。
正如其他答案所说,通过相同的散列算法运行相同的密码将始终产生相同的散列。但我们也可以从字面上理解您的问题,在这种情况下,仍然有一个有用(和不同)的答案......
假设您已设法从受感染的服务器获取大量散列密码。您想恢复一些密码,而您并不特别在意哪些密码。这个目标是现实的——您的列表可能还包含匹配的用户名和/或电子邮件地址,并且您希望提供可在其他不相关站点(例如受害者的电子邮件帐户或 Paypal 帐户)上使用的凭据。
密码强度差异很大。有些人使用长的随机字符串。其他人使用非常常见的词,例如“密码”。这一事实使得可以在比完全蛮力搜索更短的时间内执行攻击。参见例如字典攻击和彩虹表。
如果您在列表中找到两个相同的哈希值,则几乎可以肯定它们是由相同的密码生成的。假设哈希属于两个真正独立的用户,那么这告诉您密码必须是一个相当弱的密码,因为根据定义,两个人不太可能独立地想到一个相同的强密码。这使得密码成为诸如基于字典的攻击之类的良好候选者。
因此,在更广泛的哈希列表的上下文中,拥有多个相同的哈希可以帮助您更快地检索原始哈希,因为它揭示了有关它的统计信息。