【问题标题】:Hashes (MD5, SHA1, SHA256, SHA384, SHA512) - why isn't it possible to get the value back from the hash?哈希(MD5、SHA1、SHA256、SHA384、SHA512) - 为什么不能从哈希中取回值?
【发布时间】:2012-02-09 15:55:37
【问题描述】:

On this blog post,有一句话如下:

这个散列对于给定的文本是唯一的。如果你使用哈希函数 再次在相同的文本上,您将获得相同的哈希值。但是没有办法 从哈希中获取给定的文本。

请原谅我对数学的无知,但我无法理解为什么无法从哈希中获取给定的文本。

如果我们使用一个密钥加密值并使用另一个密钥解密,我会理解,但我无法在我的脑海中弄清楚。幕后究竟发生了什么?

任何让我头脑清醒的东西都会受到赞赏。

【问题讨论】:

  • 阅读有关这些散列算法的维基百科文章。应该可以帮助你理解。关键在于它们是独一无二的。我应该补充一点,您当然可以弄清楚文本属于什么,提供了某些信息。它是一种蛮力方法,例如所有已知的 md5 值都是已知的。因此,给定一个特定的字符数组,我们可以找出值是什么。仅仅使用这些散列算法并不聪明,你需要使用盐,否则即使 SHA512 给定足够的时间也很弱。
  • @Ramhound 好的,现在我很困惑。 Oded 在下面建议它们不是唯一的,而您说它们是唯一的。
  • 更正确的解释应该是这样的:“这个散列函数极不可能为不同的输入提供相同的输出,因此可以被认为是唯一的。”
  • @Ramhound - 哈希有冲突。即使使用 MD5,也有已知的输入会产生相同的哈希值。
  • @Oded - 我知道。 MD5 尤其是因为它需要的字节数。你不能散列更多的字节,然后它支持的冲突。话虽如此,MD5 仍然可以使用彩虹表。我想这是有限制的。我什至后悔发表那种声明。

标签: c# .net security hash cryptography


【解决方案1】:

散列不是加密。

哈希产生一个“摘要” - 输入的摘要。无论输入大小如何,散列大小始终相同(查看 MD5 如何为任何输入大小返回相同大小的结果)。

使用散列,您可以从几个不同的输入(散列冲突)中获得 相同的 散列 - 您将如何扭转这种情况? 正确的输入是什么?

我建议阅读this blog post from Troy Hunt 以更好地了解哈希、密码和安全性。

加密是另一回事 - 您会从输入和密钥中获得不同的密码 - 密码的大小会随着输入的增大而变大。如果你有正确的钥匙,这是可逆的


更新(根据不同的 cmets):

尽管可能会发生冲突,但当使用具有密码意义的哈希(如您发布的那些)时,它们将很少见且难以生成。

在对密码进行哈希处理时,始终使用 salt - 这样可以将哈希值被 rainbow tables 反转的可能性降低到几乎为零(假设使用了良好的盐)。

您需要权衡散列成本(可能是处理器密集型)和您所保护的成本。

由于您只是保护登录详细信息,因此使用 .NET 成员资格提供程序应该提供足够的安全性。

【讨论】:

  • 好的,这是我目前还没有意识到的。然后将纯文本密码作为哈希存储在数据库中是没有意义的,因为实际上有人可以使用多个不同的密码登录。
  • @tugberk - 我说碰撞可以发生。这取决于哈希值发生这种情况的可能性。找到碰撞并不容易。但是对于 MD5,如果您不使用加盐,则有 哈希查找表映射回输入(查找彩虹表)。
  • @tugberk:是的,确实如此。如果哈希密码存储在数据库中,则有多个有效密码映射到此缓存。但是,如果散列函数是 加密安全 散列函数(以及您在问题中提到的那些),那么很难 找到 映射到给定哈希。
  • @tugberk - 是的,加盐是必不可少的。我将使用什么取决于我要保护的内容。是财务吗?个人的?公开可用?
  • @tugberk - MD5 不安全,SHA1 不安全,请阅读发布的文章。 SHA512 是最安全的。您应该始终为每个密码使用唯一的盐。如果您尽可能使用相同的盐,那么它就没有用了。甚至可能会说甚至不存储整个哈希值,您不需要它,您只需要匹配密码即可。
【解决方案2】:

散列就像使用校验和来验证数据,而不是加密或压缩数据。

【讨论】:

    【解决方案3】:

    它不是加密/解密。比如简单的哈希函数:

    int hash(int data)
    {
        return data % 2;
    }
    

    问题?

    【讨论】:

    【解决方案4】:

    这本质上是数学,哈希函数是一个非 1 比 1 的函数。它在所有二进制数据 B* 的集合中获取一个范围的输入,并将其映射到某个固定长度的二进制字符串集 Bn,用于固定 n左右。(这个定义是在然而) 您可以尝试通过蛮力计算给定哈希的原像,但在不知道大小的情况下,它是无限的。

    【讨论】:

      【解决方案5】:

      您可以散列任意长度的数据,从单个字节到 TB 文件。所有可能的数据都可以散列为一个 256 位的值(以 SHA-256 为例)。这意味着 SHA-256 哈希算法有 2^256 个可能的值输出。但是,可以输入到 SHA-256 的可能值远不止 2^256 个。您可以输入任意长度的任意字节组合。

      由于可能的输入远多于可能的输出,因此某些输入必须生成相同的输出。由于您不知道许多可能的输入中的哪一个产生了输出,因此不可能可靠地倒退。

      【讨论】:

        【解决方案6】:

        至少有两个原因:

        1. 散列通常使用非对称函数进行计算 - 这意味着找到某些运算的反向值比直接运算要困难得多(在时间/资源/努力方面)。

        2. 相同算法的哈希总是相同的长度 - 这意味着可能的哈希是有限的。这意味着对于每个散列,都会有无限个冲突 - 不同的源数据块形成相同的散列值。

        【讨论】:

          【解决方案7】:

          哈希函数是多对一的函数。这意味着许多输入会给出相同的结果,但对于任何给定的输入,您只会得到一个结果。

          为什么会这样可以通过考虑一个哈希函数来直观地看到,该函数接受任意长度的字符串输入并生成一个 32 位整数。字符串显然比 2^32 多得多,这意味着您的哈希函数 不能 为每个输入字符串提供唯一的输出。 (有关更多讨论,请参阅http://en.wikipedia.org/wiki/Pigeonhole_principle - 使用和应用部分专门讨论哈希)

          鉴于我们现在知道哈希函数的任何结果都可能由一个或多个输入生成,并且除了结果之外我们没有其他信息,因此我们无法确定使用了哪个输入,因此无法反转。

          【讨论】:

          • 这可能无法逆转,我们可以识别哪些鸽子进入哪些洞,这是MD5的整个问题,没有足够的鸽子洞。
          • @Ramhound:我不清楚你在说什么。你是说鸽子洞越少越容易找到可以进入特定鸽子洞的东西?
          • 是的,他就是这么说的。由于 MD5 的哈希长度略短,为 128 位,因此任何输入只能生成 2^128 个不同的哈希。因此,您将遇到比 SHA-512 之类的冲突更多的冲突,SHA-512 的哈希长度为 512 位,导致 2^512 种不同的可能哈希。 MD5 的较短长度是目前认为不安全的主要原因。
          【解决方案8】:

          一个非常简单的哈希算法是获取文本中每个单词的第一个字符。如果你使用相同的文本,你总是可以得到相同的哈希值,但不可能从每个单词的第一个字符重建原始文本。

          上面我的答案中的示例哈希:

          AvshawbtttfcoewwatIyttstycagotshbisitrtotfohtfcoew
          

          现在尝试从给定的哈希中找出相应的文本。 ;-)

          【讨论】:

          • 这并没有解决作者的问题。
          • @Ramhound:问题是I cannot understand why it is not possible to get the given text from the hash. 我给出了一个简单易懂的哈希算法,并举了一个无法从(我的回答)中取出原始文本的例子,但你可以简单地通过在我的答案中取每个单词的第一个字符来证明正确性。
          猜你喜欢
          • 2020-11-05
          • 2012-03-28
          • 2011-08-16
          • 1970-01-01
          • 2019-12-08
          • 2018-05-18
          • 1970-01-01
          • 2018-12-03
          • 2012-08-17
          相关资源
          最近更新 更多