【问题标题】:What's the big deal with brute force on hashes like MD5像 MD5 这样的哈希值的蛮力有什么大不了的
【发布时间】:2011-03-01 21:35:47
【问题描述】:

我刚刚花了一些时间阅读https://stackoverflow.com/questions/2768248/is-md5-really-that-bad(我强烈推荐!)。

在其中,它谈到了哈希冲突。也许我在这里遗漏了一些东西,但你不能只使用 MD5 加密你的密码,然后使用 SHA-1(或任何其他,没关系)。这不会增加所需的处理能力吗?暴力破解哈希并减少冲突的可能性?

【问题讨论】:

  • 奇怪和不幸的是,这个问题“出于节制的原因从 stackoverflow 中删除。”

标签: security hash cryptography md5 sha1


【解决方案1】:

您在谈论 2 个不同(尽管相关)的问题。首先是发生冲突的可能性,其次是能够对大量值运行算法以找到创建哈希的原始值。

  1. 碰撞。如果你运行 sha1(md5(text)) 你首先得到 md5 的哈希值,然后将它传递给 sha1。让我们假设 sha1 函数具有 128 位输出,而 md5 也具有 128 位输出。您在 md5 函数中发生碰撞的几率是 1/2^128。那么你在 sha1 中发生碰撞的机会是 1/2^128。如果其中任何一个发生碰撞,则函数整体发生碰撞,因此结果为 (1/2^128) + (1/2^128) 或 1/2^127
  2. 暴力破解。运行 sha1(md5(text)) 只会将查找原始字符串所需的时间加倍。就安全性而言,这不算什么。例如,如果每个算法都有 128 位的输出空间,并且暴力破解需要 1 小时,那么同样的暴力破解两次需要 2 小时才能得到原始字符串。这与将输出空间增加到 129 位相同。但是,如果您想真正使暴力破解成为不可能,您必须做的是将输出大小加倍(可以与加密中的密钥大小进行比较)。

【讨论】:

  • 嗯,这个答案对于碰撞是不正确的。 md5 空间中的碰撞将转移到 sha1 函数,因为 md5 函数的熵减少意味着输入到 sha1 函数的熵减少,因此这对函数能够减少的哈希总数的熵减少生产。 1/2^128 完全错误。
  • @sillyMunky,是的,你是对的。碰撞的可能性从 1/2^128 增加到 2/2^128(又名 1/2^127)。因此,添加 md5 哈希的 sha1 会增加冲突的机会。我已经更新了答案以反映这一点。
  • 它比碰撞更糟糕。 MD5 (MD5(text1)=MD5(text2)) 的任何冲突对于 SHA1+MD5 (SHA1(MD5(text1))=SHA1(MD5(text2))) 也是微不足道的。因此,由于 MD5 在冲突方面被破坏,SHA1+MD5 也被破坏。
  • 如果你真的想减少碰撞的可能性,你需要把md5和sha1的hash都独立同时检查。然后,在一种算法中发现的任何冲突也必须是另一种算法中的冲突,否则其中一项检查将失败。这极大地降低了任何碰撞对任何攻击者有用(或偶然发生)的可能性。
【解决方案2】:

当您多次散列密码时,实际上会增加散列冲突的机会,因此最佳做法是只散列一次。

这也与执行蛮力攻击的难易程度无关。这种攻击将系统地尝试给定范围内的每个可能的密码。因此,如果您的密码是“foobar”并且攻击测试了密码“foobar”,那么您对密码进行哈希处理的次数或次数都无关紧要,因为蛮力攻击成功地猜到了它。

因此,如果您希望保护自己免受暴力攻击,您可以限制用户尝试授权的频率或要求密码超过一定长度。

附带说明;已经获得您数据库访问权限的黑客使用彩虹表和类似方法来解密存储的密码。为了使这种攻击更加困难,您应该使用静态和动态盐。

【讨论】:

  • 使用盐并不能防止散列的破坏。然而,它确实使预先计算的攻击更加占用资源。 John The Ripper 不是预先计算的攻击,如果攻击者有盐,破解它并不比直接哈希 md5($pass) 更难破解。
  • “当您多次散列密码时,实际上会增加散列冲突的机会,因此最佳做法是只散列一次。” - 这完全不真实。如果它是真的,那么安全散列函数就不会是。
【解决方案3】:

散列哈希是一种“通过混淆进行加密”,这并不是真正的最佳实践。你是对的,理论上它可以“减少”碰撞的可能性,但它可能不会消除这种可能性。更重要的是,散列函数并不是真正的加密函数,谷歌“散列与加密”有数百种解释。

【讨论】:

  • 散列哈希不会降低冲突的可能性。
  • 尤其是在使用不同的算法时。我不认为这样的笼统陈述在所有情况下都是正确的……或者至少,可以制定一个示例,其中散列哈希确实会降低可能性。
  • 不,无论是否使用不同的算法,它都不会降低碰撞的可能性。使用sha1(md5($pass)) 的示例,如果 pass=="X" 和 pass=="Y" 在 md5() 下产生冲突,则相同的 md5 输出文本被传递到 sha1() 散列中,因此 保证 产生相同的输出 - 即碰撞。更糟糕的是, md5("X") 和 md5("Y") 可能会产生不同的输出,当输入 sha1() 时恰好会产生自己的碰撞,因此,正如@Zackman 所说,您实际上会增加碰撞的概率。
  • 我同意你的例子,也许它应该删除我的答案或者至少编辑它说“可以减少”......我最初的想法是 md5($pass) 与 md5(sha512( $pass)) 具有短输入(比 sha512 的输出短)。在这种情况下,后者不会比前者更不容易发生冲突(尽管可能并不比 sha512 本身更容易发生冲突),因为它本质上是向 md5 添加更多位而不仅仅是输入本身?
【解决方案4】:

首先不使用哈希函数加密创建消息摘要。

你的问题:

但你不能只加密(散列)你的 密码使用,比如说,MD5,然后, 说,SHA-1(或任何其他,不 问题。)

如果散列函数不提供这些属性中的任何一个,那么无论你散列多少次,攻击者也可以散列 n 次以获得冲突。

  1. 对于任何给定的代码 h,在计算上都无法找到 这样 x 使得 H(x)=h,这个性质是 称为单向或抗原像。

  2. 对于任何给定的块 x,要找到 y≠x 在计算上是不可行的 H(y)=H(x)。这个性质是 转介第二原像抗性或 抗碰撞能力弱

  3. 要找到任何 pear (x,y) 在计算上是不可行的,使得 H(x)=H(y)。这叫强 抗碰撞。

正如 The Rook 提到的,密码是通过为每个用户添加不同的盐值来存储的。如果攻击者利用密码文件,字典会变长,计算开销和时间也会变长。

假设攻击者拥有密码的哈希值,并开始从字典文件中读取并与哈希值进行比较,如果匹配则密码被破解,如果使用盐则从字典中读取并添加一些盐值然后尝试找到一个匹配。但是这应该为每个用户完成。所以盐增加的复杂性是(来自维基百科)

假设用户的(加密的)密钥 被偷了,而且他知道使用一个 200,000 个英语单词作为他的 密码。系统使用 32 位 盐。加盐键现在是 附加到此的原始密码 随机 32 位盐。因为这 salt,攻击者预先计算的 哈希没有价值。他必须 计算每个单词的哈希值 每个 2^32 (4,294,967,296) 可能 附加盐,直到找到匹配项。 可能输入的总数 可以通过乘以得到 字典中的单词数 可能的盐的数量:

if H(password+salt)(in system)=H(Your password+salt) (login process)
login else
print<<error

【讨论】:

    【解决方案5】:

    碰撞攻击(例如,针对 MD5 的已知类型)并没有真正的好处。为了对密码有效,您需要原像攻击(即能够找到一些将散列到已知散列码的输入的能力)。虽然已知有针对 MD5 的原像攻击,但它们目前并不实用。

    碰撞攻击可用于完全不同的目的。已执行的一个示例是为两个冲突的不同身份创建两个 X.509 证书。提交一个由证书颁发机构签名,然后您可以使用另一个声称您完全是其他人。由于哈希将与第一个冲突,当/如果用户尝试验证证书时,它将显示为已验证。

    【讨论】:

      【解决方案6】:

      首先 md5 和 sha1 不是加密函数,它们是消息摘要函数。此外,在现实世界中,大多数哈希值都被 John The Ripper 和 Rainbow Crack 等字典攻击所破坏。

      John The Ripper 最适合攻击者知道加盐值的加盐密码。 Rainbow Crack 适用于具有小的未知盐和直哈希的密码,例如md5($pass)。

      Rainbow Crack 需要很长时间来构建表格,但之后密码会在几秒钟内破解。这取决于您的磁盘驱动器的速度。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        • 2020-06-26
        • 2015-03-23
        • 2012-07-22
        • 2012-08-17
        • 2011-05-17
        相关资源
        最近更新 更多