为什么不混合哈希?

信息安全 哈希 算法
2021-08-26 13:47:08

为了使专门的硬件更难以定位哈希,我直观地认为混合一组不同的哈希算法应该提供额外的强度。为简单起见,我们假设, isisHash1的迭代次数SHA256Hash2bcryptHash3scrypt

myhash = Hash1(Hash2(Hash3(0, password, salt), password, salt), password, salt)

假设Hash1Hash2Hash3每个在典型用户的硬件上计算需要 1/3 秒,为什么似乎更倾向于使用

myhash = Hash1(Hash1(Hash1(0, password, salt), password, salt), password, salt)

编辑:将 short format 更改Hash1(Hash1(Hash1(password ^ salt)))为更准确的 format Hash1(Hash1(Hash1(0, password, salt), password, salt), password, salt),以避免仅指出与前一种格式冲突数量较多的答案。只要剩余的熵myhash(~256 - x 由于碰撞,x 接近 0)明显高于用户密码的熵,冲突就不是用户密码散列的一个因素。除非由密码生成器选择,否则用户的密码几乎总是少于 60 位的熵。

4个回答

在尝试对密码进行哈希处理时,攻击者始终可以使用与防御者相同的硬件。攻击者试图做得更好,通过使用专门的硬件,这将使他能够以比使用防御者的硬件更低的总成本散列N 个潜在密码。所述总成本包括购买硬件,在其上显影的相关软件的成本,然后运行的硬件,这基本上相当于所使用的电的成本的(对于硬件供电和用于冷却它)的成本。对于严重的攻击者,电力成本占主导地位。

每当有一些攻击者可以比防御者便宜的操作时,攻击者就会获胜。重要的一点是,密码破解是一个令人尴尬的并行问题:根据定义,攻击者有许多潜在的密码可以尝试。

假设您级联三个不同的散列函数Hash1这意味着防御者必须手头有所有三个实现,都在他的服务器上运行。另一方面,攻击者可以有更好的调度:他可以(比如说)散列一百万个潜在密码并将结果保存在某个缓冲区中;然后将硬件切换到适用的东西,并在上一步中保存的一百万个输出上运行它,再次将输出保存在某个缓冲区中;最后再次切换硬件,使用.Hash2Hash3Hash1Hash2Hash2Hash3

这种“硬件切换”在使用FPGA时尤为重要:每次“切换”都是对相同实际硬件的重新编程,最多只需几秒钟。通过使用这种调度和缓冲,“切换”成本可以忽略不计。

这也可以用作流水线:如果攻击者构建了三台专用机器,一台用于Hash1,一台用于 ,Hash2一台用于Hash3,那么他可以Hash1使用第一个潜在密码运行,然后将输出发送到计算 的机器Hash2当第二台机器计算Hash2时,第一台机器可以计算Hash1另一个潜在的密码。等等。在实践中,攻击者可以随时保持他所有的专用机器处于满负荷状态,从而嘲笑你“增加强度”的尝试。

此外,如果要实现三个不同的哈希函数,并且只有一个可以使用专用硬件进行优化,那么攻击者仍然可以通过优化那个来获得胜利。粗略地说,如果你级联 bcrypt、scrypt 和 SHA-256,那么攻击者将使用 PC 进行前两者,使用 GPU 进行 SHA-256,从而避免大约 1/3 的成本。


总而言之,“混合一组不同的哈希算法应该提供额外的强度”的直觉是错误的。它恰恰相反。这种混合增加了防御者的开发和使用成本,同时它不会减慢攻击者(他们有很多并行性可以从中受益),并增加了攻击者的优化选项。

(所有这些都是在没有讨论实际问题的情况下说的,例如所有级联函数的单个盐的管理,以及自制密码学的危险。)

我被要求将我的评论作为答案,所以就这样吧。

基本上,我说过 bcrypt、scrypt 和 pbkdf2 之类的东西本身并不是哈希,而是 KDF(密钥派生函数)。KDF 建立在 HMAC 算法之上,而 HMAC 算法又建立在 SHA-256 等单向散列算法之上,以生成消息摘要值。

从 KDF 中获取价值已经涉及到大量的混合、搅拌和摇晃。

即使混合多个 KDF 的输出不会削弱整体安全性,它似乎也不会实质性地改善它。

复制我对 progs.SE 上类似问题的回答:

问题

hash1(hash2(hash3(...hashn(pass+salt)+salt)+salt)...)+salt)

是这仅与链中最弱的哈希函数一样强。例如,如果 hashn(最里面的哈希)产生冲突,整个哈希链都会产生冲突(不管链中的其他哈希是什么

一个更强大的链条将是

hash1(hash2(hash3(...hashn(pass+salt)+pass+salt)+pass+salt)...)+pass+salt)

在这里我们避免了早期碰撞问题,我们基本上生成了一个盐,它取决于最终哈希的密码

如果链中的一个步骤发生冲突也没关系,因为在下一步中再次使用密码并且应该为不同的密码给出不同的结果

使用不同的哈希算法不会给你更多的熵,而是更少。我想您已经听说过“安全性不强于最弱点”这句话,这里也同样适用。它的熵不会超过最弱算法给出的熵。

但是多次使用相同的算法对密码进行哈希处理会给您带来更高的安全性。但是使用强散列算法几轮而不是弱算法多轮。示例这更安全:

sha512 ( sha512 ( sha512 ( password + salt )))

比:

sha1 ( sha1 ( sha1 ( sha1 ( sha1 ( sha1 ( ... sha1 ( password + salt ) ... ))))))

我看到有些人不相信这一点,并希望我证明这一点。让我们举个例子。我选择了三种散列算法,SHA256、SHA1 和 MD5。

  • SHA256 产生 256 位输出
  • SHA1 产生 160 位输出
  • MD5 产生 128 位输出

所以如果我们有:

sha256 ( sha1 ( md5 ( password + salt )));

首先用 MD5 对密码和盐进行哈希处理,输出将是 128 位大,因此 MD5 输出的总可能性为 2^128。然后用 SHA1 对 MD5 和进行散列,但您不需要散列所有可能性,只需 2^128 作为 MD5 输出。然后用 SHA256 对 SHA1 和进行哈希处理,但又一次。不必对 SHA256 的所有可能性进行哈希处理,只需对 MD5 产生的 2^128 个可能性进行哈希处理。所以这个散列算法只能产生熵为2^128的输出,就像MD5一样。而且MD5有多个漏洞,所以实际强度不到2^128。