对于我们的每个二进制资产,我们生成一个MD5哈希。这用于检查某个二进制资产是否已存在于我们的应用程序中。但两个不同的二进制资产是否可能生成相同的MD5哈希值。那么两个不同的字符串是否可能生成相同的MD5哈希值?
答案 0 :(得分:90)
对于一组甚至数十亿的资产,随机碰撞的可能性微不足道 - 你不应该担心什么。考虑到birthday paradox,给定一组2 ^ 64(或18,446,744,073,709,551,616)资产,该集合中单个 MD5碰撞的概率为50%。在这种规模下,您可能会在存储容量方面击败Google。
但是,由于MD5哈希函数已被破坏(它易受collision attack攻击),任何确定的攻击者都可以在几秒钟的CPU功率下产生2个冲突资产。因此,如果您想使用MD5,请确保此类攻击者不会损害您的应用程序的安全性!
另外,如果攻击者可能会在数据库中伪造与现有资产的冲突,请考虑其后果。虽然没有针对MD5的此类已知攻击(preimage attacks)(截至2011年),但通过扩展当前的碰撞攻击研究可能会成为可能。
如果这些问题成为问题,我建议查看SHA-2系列哈希函数(SHA-256,SHA-384和SHA-512)。缺点是它稍微慢一点,并且哈希输出更长。
答案 1 :(得分:37)
MD5是hash function - 所以是的,两个不同的字符串绝对会产生碰撞的MD5代码。
请注意,MD5代码具有固定长度,因此可能的MD5代码数量有限。然而,字符串的数量(任何长度)肯定是无限的,因此从逻辑上讲,必须是冲突。
答案 2 :(得分:12)
是的,有可能。这实际上是Birthday problem。但是,两个随机选择的具有相同MD5哈希的字符串的概率非常低。
答案 3 :(得分:10)
是的,当然:MD5哈希的长度有限,但是有无数个可能的字符串可以进行MD5哈希。
答案 4 :(得分:6)
是的,两个不同的字符串可能会生成相同的MD5哈希码。
这是一个简单的测试,使用十六进制字符串中非常相似的二进制消息:
create_user_and_set_email_as_username
它们生成不同的SHA-1总和,但具有相同的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
上面的碰撞示例取自Marc Stevens:Single-block collision for MD5,2012;他用源代码(alternate link to the paper)解释了他的方法。
另一项测试:
$ 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哈希值。
差异在一个字节中:
$ echo '0e306561559aa787d00bc6f70bbdfe3404cf03659e704f8534c00ffb659c4c8740cc942feb2da115a3f4155cbb8607497386656d7d1f34a42059d78f5a8dd1ef' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
756f3044edf52611a51a8fa7ec8f95e273f21f82 -
cee9a457e790cf20d4bdaa6d69f01e41
$ echo '0e306561559aa787d00bc6f70bbdfe3404cf03659e744f8534c00ffb659c4c8740cc942feb2da115a3f415dcbb8607497386656d7d1f34a42059d78f5a8dd1ef' | xxd -r -p | tee >/dev/null >(md5) >(sha1sum)
6d5294e385f50c12745a4d901285ddbffd3842cb -
cee9a457e790cf20d4bdaa6d69f01e41
上面的例子改编自Tao Tao和Dengguo Feng:Construct MD5 Collisions Using Just A Single Block Of Message,2010。
相关:
答案 5 :(得分:4)
答案 6 :(得分:4)
只是为了提供更多信息。 从数学的角度来看,Hash函数不是 injective 这意味着起始集与结果集之间不存在1对1(但单向)关系。
编辑:存在完整的内射散列函数:它被称为Perfect hashing。
答案 7 :(得分:3)
是的,它是!碰撞将成为一种可能性(尽管风险非常小)。如果没有,你会有一个非常有效的压缩方法!
编辑:正如Konrad Rudolph所说:转换为有限输出集(32个十六进制字符)的潜在无限输入集将导致无数次冲突
答案 8 :(得分:3)
正如其他人所说,是的,两个不同的输入之间可能会发生冲突。但是,在您的用例中,我不认为这是一个问题。我非常怀疑你会遇到碰撞 - 我已经使用MD5在之前的工作中指纹识别了许多图像(JPG,位图,PNG,原始)格式的数十万个图像文件而且我没有碰撞
但是,如果你试图指纹某种数据,也许你可以使用两种哈希算法 - 一次输入导致两种不同算法输出相同的几率几乎是不可能的。
答案 9 :(得分: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)))
好吧,不是最干净的解决方案,但是现在这会让你更频繁地碰到你碰巧遇到的碰撞。在某种程度上,我可能认为这个术语的所有现实意义都是不可能的。
为了我的缘故,我认为发生碰撞的可能性很小,我不会考虑这个&#34; surefire&#34;但不太可能发生它适合需要。
现在可能的组合显着增加。虽然你可以花很长时间研究这可能会给你带来多少组合,但我会在理论上说它比你上面引用的数字更显着地落在你身上
2^64 (or 18,446,744,073,709,551,616)
可能还有一百多个数字左右。这可能会给你理论上的最大值
结果字符串的可能数量:
528294531135665246352339784916516606518847326036121522127960709026673902556724859474417255887657187894674394993257128678882347559502685537250538978462939576908386683999005084168731517676426441053024232908211188404148028292751561738838396898767036476489538580897737998336
答案 10 :(得分:1)
我认为我们需要谨慎选择哈希算法,因为哈希冲突并不像我预期的那样罕见。我最近在我的项目中发现了一个非常简单的哈希冲突案例。我正在使用xxhash的Python包装器进行散列。链接:https://github.com/ewencp/pyhashxx
s1 = 'mdsAnalysisResult105588'
s2 = 'mdsAlertCompleteResult360224'
pyhashxx.hashxx(s1) # Out: 2535747266
pyhashxx.hashxx(s2) # Out: 2535747266
它在系统中引起了一个非常棘手的缓存问题,然后我终于发现它是一个哈希冲突。