两个不同的字符串可以生成相同的MD5哈希码吗?


92

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

Answers:


93

对于什至数十亿资产的集合,随机碰撞的可能性很小,几乎没有什么可担心的。考虑到生日悖论,给定一组2 ^ 64(或18,446,744,073,709,551,616)个资产,该组中一次 MD5碰撞的概率为50%。以这种规模,您可能会在存储容量方面击败Google。

但是,由于MD5哈希函数已被破坏(很容易受到碰撞攻击),因此任何确定的攻击者都可以在几秒钟的CPU能力内产生2个冲突资产。因此,如果要使用MD5,请确保这样的攻击者不会损害应用程序的安全性!

此外,如果攻击者可以伪造与数据库中现有资产的冲突,请考虑后果。尽管没有针对MD5的此类已知攻击(前映像攻击)(截至2011年),但可以通过扩展当前对碰撞攻击的研究来实现。

如果发现有问题,建议您查看SHA-2系列哈希函数(SHA-256,SHA-384和SHA-512)。缺点是速度稍慢,哈希输出更长。


4
据我了解,“天”在这一点上是一个巨大的夸大其词。
尼克·约翰逊,

1
是的,我更新了我的帖子。2004年的随机碰撞攻击确实非常快。2007年MD5 前缀碰撞攻击可能需要数天-但一般是更加有益的攻击者
intgr

2
请参阅鲁本斯的答案以获取一个工作示例,该示例将在几个小时内在两个不同的可执行文件之间产生冲突。:)
尼克·约翰逊,

38

MD5是一个哈希函数 –是的,两个不同的字符串绝对可以生成冲突的MD5代码。

特别要注意的是,MD5码的长度是固定的,因此MD5码的可能数量受到限制。但是,字符串(任意长度)的数量绝对是无限的,因此从逻辑上讲必须存在冲突。


12

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

这个这个问题的例子。


1
什么概率?那碰撞?不,那将是1,即很高。;-)
Konrad Rudolph

好吧,是的。肯定存在两个具有相同MD5哈希值的字符串。
sharptooth

3
我知道这是信鸽问题。
Daniel A. White

生日问题仅涉及碰撞的可能性。为了证明这一点,必须有一个你想要的皮江法孔原则
JK。

如果可以的话,我会两次投票赞成你的答案。我们在说几率有多低?
Alex Spencer

10

是的,当然:MD5散列的长度是有限的,但是可以通过MD5散列的字符串数量是无限的。


9

是的,两个不同的字符串可能会生成相同的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

上面的碰撞示例来自Marc Stevens:MD5的单块碰撞,2012年;他用源代码解释了他的方法(本文的备用链接)。


另一个测试:

$ echo '0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
756f3044edf52611a51a8fa7ec8f95e273f21f82  -
cee9a457e790cf20d4bdaa6d69f01e41

$ echo '0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
6d5294e385f50c12745a4d901285ddbffd3842cb  -
cee9a457e790cf20d4bdaa6d69f01e41

不同的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

上面的示例改编自Tao Xie和Dengguo Feng:仅使用单个消息块构建MD5冲突,2010年。


有关:


4

是的,有可能。这称为哈希冲突

话虽如此,诸如MD5之类的算法旨在将碰撞的可能性降到最低。

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


4

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

维基百科上的双射

编辑:完整的注入式哈希函数存在:它称为Perfect hashing


1
当输出大小小于输入大小时,没有完美的哈希函数。
2011年

3

是的!可能发生碰撞(尽管风险很小)。如果没有,您将拥有一种非常有效的压缩方法!

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


3

正如其他人所说,是的,两个不同的输入之间可能存在冲突。但是,在您的用例中,我认为这不是问题。我非常怀疑您是否会遇到碰撞-我在以前的工作中使用MD5指纹识别了成千上万个具有多种图像(JPG,位图,PNG,原始)格式的图像文件,但是我没有发生碰撞。

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


1
实际上,如果攻击者可以使用一种哈希算法产生冲突,那么他就可以使用它来获取第二种算法的冲突。最近在crypto.stackexchange上关于我的问题对此进行了讨论。
圣保罗Ebermann

2

我意识到这已经很老了,但我想我会贡献我的解决方案。有2 ^ 128种可能的哈希组合。因此,生日悖论的概率为2 ^ 64。尽管以下解决方案无法消除发生碰撞的可能性,但肯定会大大降低风险。

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

我所做的是我根据输入字符串将一些哈希值放在一起,以获得更长的结果字符串,您可以将其视为哈希值...

所以我的伪代码是:

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) 

可能增加一百位数左右。这可以给你的理论最大值是

结果字符串的可能数量:

5282945311356652463523397849165166065188473260361215221279607090266739025567248594744172558876571878946743949932571286788823475595026855372505389789789399399090838668399900508416873151767642644105302423290821118118840840802829275275161738838396898798767036476489545


1

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

s1 = 'mdsAnalysisResult105588'
s2 = 'mdsAlertCompleteResult360224'
pyhashxx.hashxx(s1) # Out: 2535747266
pyhashxx.hashxx(s2) # Out: 2535747266

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.