对于我们的每个二进制资产,我们都会生成一个MD5哈希。这用于检查我们的应用程序中是否已存在某种二进制资产。但是有可能两个不同的二进制资产生成相同的MD5哈希。那么,两个不同的字符串可能会生成相同的MD5哈希吗?
对于我们的每个二进制资产,我们都会生成一个MD5哈希。这用于检查我们的应用程序中是否已存在某种二进制资产。但是有可能两个不同的二进制资产生成相同的MD5哈希。那么,两个不同的字符串可能会生成相同的MD5哈希吗?
Answers:
对于什至数十亿资产的集合,随机碰撞的可能性很小,几乎没有什么可担心的。考虑到生日悖论,给定一组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)。缺点是速度稍慢,哈希输出更长。
是的,两个不同的字符串可能会生成相同的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年。
有关:
只是为了提供更多信息。从数学角度来看,哈希函数不是单射的。
这意味着起始集和结果集之间不存在一对一(一种方式)的关系。
编辑:完整的注入式哈希函数存在:它称为Perfect hashing。
正如其他人所说,是的,两个不同的输入之间可能存在冲突。但是,在您的用例中,我认为这不是问题。我非常怀疑您是否会遇到碰撞-我在以前的工作中使用MD5指纹识别了成千上万个具有多种图像(JPG,位图,PNG,原始)格式的图像文件,但是我没有发生碰撞。
但是,如果您尝试对某种数据进行指纹识别,则也许可以使用两种哈希算法-一个输入导致两个不同算法的相同输出的几率几乎是不可能的。
我意识到这已经很老了,但我想我会贡献我的解决方案。有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
我认为我们需要根据我们的要求谨慎选择哈希算法,因为哈希冲突并不像我预期的那么罕见。我最近在我的项目中发现了一个非常简单的哈希冲突案例。我正在使用xxhash的Python包装器进行哈希处理。链接:https://github.com/ewencp/pyhashxx
s1 = 'mdsAnalysisResult105588'
s2 = 'mdsAlertCompleteResult360224'
pyhashxx.hashxx(s1) # Out: 2535747266
pyhashxx.hashxx(s2) # Out: 2535747266
它在系统中引起了一个非常棘手的缓存问题,然后我终于发现这是哈希冲突。