每个哈希值都有一个反值吗?

信息安全 哈希 md5
2021-09-01 22:23:16

有许多不同的散列函数,md5、sha 等。它们取一个值V并产生一个Hvia 转换Function(V) = H,其中Function是 md5、sha 等。

我的问题是:每个哈希值H都有一个值V吗?

例如,给定 md5 哈希值f2c057ed1807c5e4227737e32cdb8669(完全随机),我们能找到它的来源吗?

换句话说,如果我们列出所有哈希:

00000000000000000000000000000000
00000000000000000000000000000001
...
fffffffffffffffffffffffffffffffe
ffffffffffffffffffffffffffffffff

我们可以为它们中的每一个找到一个值吗?

编辑(来自OP的评论):我想知道每个可能的输出是否存在输入。我对找到逆不感兴趣

4个回答

我的问题是:是否每个哈希值 H 都有值 V?

例如,给定 md5 哈希值 f2c057ed1807c5e4227737e32cdb8669(完全随机),我们能找到它的来源吗?

这实际上是两个非常不同的问题:每个输出是否有输入,以及我们是否可以为每个输出找到输入。

对于你的第一个问题:我们不知道。对于给定的散列函数,可能输入的数量远远大于可能输出的数量,因此如果该函数不是满射的(即如果输出没有任何匹配的输入),我们会感到非常惊讶。例如,对于 MD5,有2128个可能的输出和 2 个18446744073709551616 -1 个可能的输入,因此我们预计每个输出平均有大约 2 个18446744073709551488 个相应的输入。有一个没有相应输入的输出是相当难以置信的。

但是,我们不知道如何证明它。在很大程度上,我们预计对于任何具体的散列函数都很难证明该属性(这种完全性证明本身并不是该函数的弱点,但是,随意地,散列函数的安全性依赖于关于这种分析的结构的难处理性)。

对于你的第二个问题:我们强烈希望它是不可行的。这就是所谓的原像电阻:对于给定的输出y ,要找到满足h ( x ) = y的x在计算上应该是不可行的即使在数学上证明了这样的输入一定存在(它没有被证明,但它被强烈怀疑,如上所述),实际找到它仍然应该是非常昂贵的。

如果散列函数是“理想的”,那么最好的攻击就是运气:您尝试可能的输入,直到找到匹配项。如果输出的大小为 n位,则“luck”的平均工作量应为 2 nn足够大(并且n = 128足够大),这是现有计算机无法做到的。如果“运气”仍然是最广为人知的攻击,则散列函数可以抵抗原像。

众所周知,MD5对原像的抵抗力并不理想,因为已经发现了一次努力 2 123.4的攻击——比 2 128快大约 10 倍,但在不可行领域还有很长的路要走,所以这种攻击只是理论上的。

不过,我想指出两点:

  • 如果我给你一个未知x的h ( x ),但你对我使用的x有一些想法(例如,你知道x是人类用户可以选择和记住的“密码”),那么你可以尝试x符合该想法的值。寻找h ( x ) 的原像的实际平均工作量是 2 nM /2 中的较小者,其中M是可能输入x的空间大小。对于“原始”原像攻击,所有位序列都是可能的输入,因此M很大,成本为 2 n. 但是,如果在特定的上下文中,已知x是从相对较小的空间中取出的,那么找到“正确的” x可以大大加快。

  • 如上所述,原像不应该是唯一的:对于给定的y ,应该存在大量值x ,这些值散列到y因此,对于给定的输出,您找不到“那个”对应的输入,而是“一个”对应的输入,它可能是也可能不是“正确的”输入。


第三个问题?事实上,尝试制作一个完整的输入到输出的地图是不同的。

正如@Xander 指出的那样,可能的 MD5 输出数量(2 128)太大而无法存储在地球上的任何地方;它超过了所有已构建的硬盘的累积大小。但是,如果您可以解决该存储问题,则可以考虑制作完整地图的成本。

如果您对所有 128 位输出单独使用“运气”攻击,您可能预计总成本为 2 256(2 128乘以 2 128 成本但是,您可以通过同时处理所有输出来做得更好,即尝试随机(或顺序)输入并在获得输出时简单地填充您的大表。通过努力 2 128,您应该获得大约 63% 的完整地图,而“独立运气”方法需要多于 2 255的努力才能获得相同的结果。


编辑:正如@Owen 和@kasperd 所指出的,关于输入数量的论点实际上并不足以引发满射性;内部功能结构很重要。MD5 和 SHA-1 是Merkle-Damgård函数,这意味着它们的构建方式如下:

  • 有一个内部伪随机排列P:对于给定大小的输入块b(在 MD5 和 SHA-1 的情况下为 512 位),P b是正好n位的序列空间的排列(对于n = 128 MD5,对于 SHA-1, n = 160)。

  • 压缩函数定义为:

        f ( b , x ) = P b ( x ) + x

    也就是说,对于块b,我们将对应于b的排列应用于第二个输入x,然后我们将x “添加”到该排列的输出。(在 MD5 和 SHA-1 的情况下,加法是在 32 位字的基础上完成的,但这里的细节并不重要。)

  • 为了处理完整的输入消息m,首先用额外的位填充消息,以便总大小成为块大小的倍数,并且还对原始消息长度进行编码。然后将填充的输入分成连续的块b 0b 1等。寄存器r被初始化为大小为n位的常规值(“IV”,在 MD5 和 SHA-1 标准中指定)。然后将块一个一个地处理:注入块b i,我们计算f ( b i , r ),输出是r的新值. 当所有块都被处理后,r包含完整的哈希函数输出。

压缩函数中的加法步骤将伪随机排列P b变为伪随机函数一个相关的结果是,对于给定的值 bf ( b , x ) 不太可能是满射的。事实上,对于所有 2 n 个输入x,我们期望值f ( b , x )仅覆盖所有可能的 2 nn序列的大约 63%

这种处理产生了有趣的结果。首先,考虑所有大小正好为 1 GB 的输入(“传统”千兆字节正好是 1073741824 字节):有 2 8589934592 个这样的序列,即比 2 128多得多。但是,当对所有这些消息应用 MD5 时,它们都将被恰好填充一个额外的块(8589934592 = 16777216×512,因此将附加一个大小为 512 的额外块),此外,最后一个块将是相同的对于所有 1 GB 输入(它对输入长度进行编码,但在其他方面是确定性的,没有随机性并且不依赖于输入位的值)。让我们称b z为最后一个块。1 GB 输入消息的MD5因此,首先对前 16777216 个块进行大量处理,产生一个 128 位的值x,并且哈希输出 MD5( m ) 等于f ( b z , x )。

因此,所有 1 GB 的消息最终都会缩减为一个相同的压缩函数f ( b z , x )。因此,我们预计哈希输出仅覆盖所有 128 位序列的约 63%。这个例子证明了关于散列函数输入数量的参数是不完整的(尽管它给出了正确的想法)。

相反,如果我们考虑所有长度正好为 300 位的消息,那么它们都将被散列为f ( b , IV),具有 2 300 个不同的块b因此,我们有 2 300 个伪随机排列P b,全部应用于相同的 128 位输入(IV),产生 2 300 个128 位结果,这些结果都应该均匀分布在 128 位值的空间中. 将 IV 添加到所有这些都不会改变这种一致性。在这种情况下,计数论点起作用,因此主观性变得很可能。


编辑2:关于“63%”。当您在大小为N的空间中均匀地生成一个随机值时,命中给定值x的概率为 1/ N因此,达到给定值x的概率为 ( N -1)/ N

现在尝试N次:您随机、均匀且独立地生成N 个值(特别是,您可能会生成多次相同的值)。对于给定的x,不属于这N个值的概率是错过N次的概率,即:

    P = (( N -1)/ N ) N

这可以近似如下:

    P = e N ln (1-1/ N ) = e N (-1/ N + o(1)) = e -1+o(1)

因此,对于较大的N值,错过任何给定值的概率接近 1/ e因此,具有N个随机值的大小为N的空间的预期覆盖率将接近 1-(1/ e )。这大约是 63.21%。

这些实际上是人们对哈希函数提出的非常常见的问题。我将给出一个更数学的答案,包括一些帮助您进行谷歌搜索的术语。

我的问题是:每个哈希值H都有一个值V吗?

表达这个问题的数学方法是

对于散列函数H = Function(V),每个输出H是否都有V映射到它的原像?

或更紧凑,

散列函数是Function()满射的吗?

MD5, SHA-1, SHA-256, , 等是否SHA-3是满射的是一个很好的问题,并且在互联网上已经被问过很多次(谷歌可以找到一些很好的讨论)。简短的回答是:我们不知道我们强烈怀疑它们是,但这不是我们能够通过数学或实验证明的东西。

让您了解为什么这是一个难题;CS.se 上的这个答案谈到MD5并指出哈希函数的设计非常接近随机并避免任何模式,这使得任何类型的数学分析都非常困难。你总是可以编写一个程序来猜测输入,直到你看到所有可能的输出。MD5有一个128-bit输出,这意味着您需要命中2 128个哈希值。假设您在第一次尝试时获得了所有这些,并且您可以每秒检查 1 次,那么您将花费大约10 31和至少10 28 GB 的硬盘空间来进行详尽的检查(请注意,宇宙是估计的是 ~ 10 10岁,地球上的总硬盘容量约为 10 12 GB)。

-family中的散列函数SHA具有更大的输出空间,并且在数学上更复杂,这意味着这种分析对它们来说更难处理。

还要注意,由于散列函数接受任何大小的输入,并给出固定大小的输出,因此(理论上)可能有无限数量的输入将映射到任何给定的散列。因此,哈希值H可能有大量{V1, V2, ...}映射到它的值。


对于您问题的第二部分:

给定 md5 哈希值f2c057ed1807c5e4227737e32cdb8669(完全随机),我们能找到 [产生它的输入集] 吗?

查找将产生给定哈希的字符串是一种称为原像攻击的密码分析形式。正如其他人指出的那样,要使散列函数被认为是加密散列函数,它必须能够抵抗原像攻击 - 或者换句话说,除了获取所有可能字符串的列表,散列它们之外,它必须不可能反转,并且看看他们是否匹配。

如果有人找到比检查所有可能的字符串更快的反转哈希的快捷方式,这将被视为该哈希函数中的漏洞,并且该哈希函数将被视为“损坏”。MD5被认为已损坏并且不再推荐用于加密,因此您可能能够找到针对它的已知原像攻击。如果您查找这些,您可能会找到帮助您反转MD5哈希值的工具。-familySHA的哈希值还没有被破坏,所以你对那些不走运。

这就是单向哈希(即 md5、sha1、sha2 等)的目的。它们不应该是可逆的。如果您可以反转散列,许多安全性将立即变得不安全。散列不包含对其进行散列的信息。散列的过程在一个方向上很容易,而在另一个方向上真的很困难,这就是原因。

现在,如果您有很多内容并将其散列,然后将该内容及其散列存储在一个大散列图中,那么您可以通过散列查找它来快速反转事情,并找到您生成该散列的内容。这就是所谓的彩虹表,它在过去一直是破解密码的可行方法,但现在已经不是那么多了。

即使可以,请考虑一下。假设我制作了 100MB 电影的 MD5 哈希值。如果我可以反转这个哈希值并从中获取我的 100MB 电影,那么我将拥有一个非常强大的压缩算法!因为这意味着我可以获取任何 1Mb、100MB、1Gb、1Tb 等内容并将其转换为 32 字节的散列来表示我想要的任何内容。现在我真的可以用 32 个字节来表示任何大小的所有可以想象的内容吗?这是不可能的,因为 32 个字节中没有足够的信息密度来表示我们可以想象的每一个可能的内容 2^128 = 340,282,366,920,938,463,463,374,607,431,768,211,456。那将是我也可以创建的独特内容的上限。

我认为这个答案比我更好地解释了数学如何使这成为不可能(或至少非常非常困难):

为什么哈希函数是一种方式?如果我知道算法,为什么我不能从中计算输入?

如果您正在谈论加密哈希,则无法恢复用于生成“H”哈希的“V”值。它们的设计方式可以防止这种情况发生。

人们发现原始“V”值的方法是生成各种“V”,计算它们各自的“H”并比较这些“H”,看看哪个与原始“H”哈希值相等。是的,只是通过暴力破解它。