Hash 两个不同的字符串能否生成相同的MD5哈希代码?

Hash 两个不同的字符串能否生成相同的MD5哈希代码?,hash,cryptography,md5,hash-collision,Hash,Cryptography,Md5,Hash Collision,对于每个二进制资产,我们生成一个MD5哈希。这用于检查某个二进制资产是否已经存在于我们的应用程序中。但是,两个不同的二进制资产是否可能生成相同的MD5哈希。那么,两个不同的字符串是否可能生成相同的MD5哈希?是的,这是可能的。这实际上是一个错误。但是,两个随机选择的字符串具有相同MD5哈希的概率非常低 有关示例,请参阅和问题。是的,确实如此!有可能发生碰撞(尽管风险很小)。如果不是,你会有一个相当有效的压缩方法 编辑:正如Konrad Rudolph所说:一组潜在的无限输入转换成一组有限的输出(

对于每个二进制资产,我们生成一个MD5哈希。这用于检查某个二进制资产是否已经存在于我们的应用程序中。但是,两个不同的二进制资产是否可能生成相同的MD5哈希。那么,两个不同的字符串是否可能生成相同的MD5哈希?

是的,这是可能的。这实际上是一个错误。但是,两个随机选择的字符串具有相同MD5哈希的概率非常低

有关示例,请参阅和问题。

是的,确实如此!有可能发生碰撞(尽管风险很小)。如果不是,你会有一个相当有效的压缩方法

编辑:正如Konrad Rudolph所说:一组潜在的无限输入转换成一组有限的输出(32个十六进制字符)将导致无数次的冲突。

MD5是一个–因此,是的,两个不同的字符串完全可以生成冲突的MD5代码


特别要注意的是,MD5代码具有固定的长度,因此MD5代码的可能数量是有限的。但是,字符串的数量(任何长度)绝对是无限的,因此从逻辑上讲,一定会有冲突。

是的,这是可能的。它被称为a

尽管如此,MD5等算法的设计目的是将碰撞概率降至最低


上的Wikipedia条目解释了MD5中的一些漏洞,您应该注意这些漏洞。

是的,当然:MD5哈希的长度是有限的,但是可以对无限多个字符串进行MD5哈希。

正如其他人所说,是的,两个不同的输入之间可能会发生冲突。然而,在您的用例中,我不认为这是一个问题。我非常怀疑你会遇到冲突——在以前的工作中,我使用MD5对数十万个图像文件(JPG、位图、PNG、raw)进行指纹识别,我没有遇到冲突


但是,如果您试图对某种数据进行指纹识别,也许可以使用两种哈希算法——一种输入导致两种不同算法的相同输出的可能性几乎是不可能的。

只是为了提供更多信息。 从数学角度来看,哈希函数不是内射的 这意味着在起始集和结果集之间不存在1对1(而是单向)关系


编辑:存在完整的内射散列函数:它被调用。

对于一组甚至数十亿的资产,发生随机冲突的可能性非常小——您不必担心。考虑到,给定一组2^64(或18446744073709551616)资产,此集合中单个MD5碰撞的概率为50%。在这个规模上,你可能会在存储容量方面击败谷歌

但是,由于MD5散列函数已被破坏(易受攻击),任何确定的攻击者都可以在几秒钟内产生2个冲突资产。因此,如果您想使用MD5,请确保此类攻击者不会危害应用程序的安全性

也可以考虑,如果<强>攻击者可以在数据库中创建与现有资产的冲突。虽然目前还没有针对MD5的此类已知攻击()(截至2011年),但通过扩展当前对碰撞攻击的研究,这可能成为可能


如果这些都是问题,我建议看看SHA-2系列的散列函数(SHA-256、SHA-384和SHA-512)。缺点是它的速度稍慢,并且散列输出较长。

我认为我们需要根据需要谨慎选择散列算法,因为散列冲突并不像我预期的那样罕见。我最近在我的项目中发现了一个非常简单的哈希冲突案例。我正在使用xxhash的Python包装器进行哈希。链接:


它在系统中造成了一个非常棘手的缓存问题,然后我最终发现这是一个哈希冲突。

是的,可能两个不同的字符串可以生成相同的MD5哈希代码

下面是一个简单的测试,使用非常相似的十六进制字符串二进制消息:

$ echo '4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
c6b384c4968b28812b676b49d40c09f8af4ed4cc  -
008ee33a9d58b51cfeb425b0959121c9

$ echo '4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
c728d8d93091e9c7b87b43d9e33829379231d7ca  -
008ee33a9d58b51cfeb425b0959121c9
它们生成不同的SHA-1和,但MD5哈希值相同。其次,字符串非常相似,因此很难找到它们之间的区别

可通过以下命令找到差异:

$ diff -u <(echo 4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2 | fold -w2) <(echo 4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2 | fold -w2)
--- /dev/fd/63  2016-02-05 12:55:04.000000000 +0000
+++ /dev/fd/62  2016-02-05 12:55:04.000000000 +0000
@@ -33,7 +33,7 @@
 af
 bf
 a2
-00
+02
 a8
 28
 4b
@@ -53,7 +53,7 @@
 6d
 a0
 d1
-55
+d5
 5d
 83
 60
不同的SHA-1和,相同的MD5散列

不同之处在于一个字节:

$ diff -u <(echo 0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef | fold -w2) <(echo 0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef | fold -w2)
--- /dev/fd/63  2016-02-05 12:56:43.000000000 +0000
+++ /dev/fd/62  2016-02-05 12:56:43.000000000 +0000
@@ -19,7 +19,7 @@
 03
 65
 9e
-70
+74
 4f
 85
 34
@@ -41,7 +41,7 @@
 a3
 f4
 15
-5c
+dc
 bb
 86
 07

$diff-u我意识到这很古老,但我想我会贡献我的解决方案。有2^128个可能的哈希组合。因此,生日悖论的概率为2^64。虽然下面的解决方案不会消除碰撞的可能性,但它肯定会大大降低风险

2^64 = 18,446,744,073,709,500,000 possible combinations

我所做的是,根据输入字符串将一些哈希放在一起,得到一个更长的结果字符串,您考虑哈希……/P> 我的伪代码是:

Result = Hash(string) & Hash(Reverse(string)) & Hash(Length(string))
这是因为实际上不可能发生碰撞。但如果你想成为超级偏执狂,而不能让它发生,存储空间不是问题(计算周期也不是问题)

好吧,这不是最干净的解决方案,但现在你可以更多地了解碰撞的频率。在这一点上,我可以假设在这个术语的所有现实意义上都是不可能的

为了我的缘故,我认为发生碰撞的可能性很小,我认为这不是“必然的结果”,但不太可能发生,它符合需要。 现在,可能的组合显著增加。虽然你可能会花很长时间考虑这能让你得到多少组合,但我会说,理论上,这会让你比上面引用的数量多得多

2^64 (or 18,446,744,073,709,551,616) 
可能会多出一百位左右。理论上,这可以给你提供的最大值是

可能产生的字符串数:

5282945311356652463523978491651660651
Result = Hash(string) & Hash(Reverse(string)) & Hash(Length(string))
Result = Hash(string) & Hash(Reverse(string)) & Hash(Length(string)) 
         & Hash(Reverse(SpellOutLengthWithWords(Length(string)))) 
         & Hash(Rotate13(string)) Hash(Hash(string)) & Hash(Reverse(Hash(string)))
2^64 (or 18,446,744,073,709,551,616)