什么时候哈希碰撞?

时间:2010-02-28 00:36:35

标签: algorithm hash

据我所知,根据鸽子原则,如果物品数量大于容器数量,那么至少一个容器将有多个物品。这个容器是否重要?这如何适用于MD5,SHA1,SHA2哈希?

5 个答案:

答案 0 :(得分:15)

不管它是哪个容器并不重要,事实上这对加密哈希来说并不重要; 更重要的是birthday paradox,它表示在发现冲突之前,您只需要平均散列sqrt(numberNeededByPigeonHolePrincipal)值。

因此,哈希需要足够大,以至于搜索空间的平方根太大而不能暴力。 SHA1的平方根搜索空间是2 80 ,截至2012年3月,没有找到具有相同SHA1-hash的两个值(尽管我预测会发生在内未来一两年......);与SHA2相同,SHA2是一系列具有更大搜索空间的哈希。 MD5虽然已经broken for a while

答案 1 :(得分:4)

如果你有更多的项目要哈希,那么你就会有哈希冲突。但是如果你的哈希算法很差,那么即使项目/时段比例非常小,你也会看到冲突。一个好的散列算法(包括你将在野外看到的大部分算法)将尝试尽可能均匀地在整个输出空间上散布所产生的散列,从而最大限度地减少碰撞。

请注意,哈希冲突不是世界末日。例如,当在哈希表中使用时,它只意味着在一个槽中存储了多个项目,并且表格代码将不得不遍历更多以查找或添加目标项目,从而略微增加查找时间。 / p>

你会看到人们将MD5称为“破碎”哈希算法,而实际上,它只是一个用作加密哈希的穷人。它会比你自己建立的更好。

答案 2 :(得分:2)

散列函数的要点是将项随机分配到容器中。对于任何好的哈希函数,它不会/不应该“重要”哪个容器是必须区分的。

这不适用于试图比随机分布更好的“完美哈希”实现 - 与您提到的算法不同。

正如迈克尔所说,在与插槽有多少项目之前,碰撞发生了很长时间。如果要处理birthday paradox,则必须具有优雅的碰撞处理(或完美的哈希)。

答案 3 :(得分:0)

我认为您使用哈希函数的应用程序是一个重要的区别。例如,散列容器中的频繁碰撞会降低性能。密码学中的频繁碰撞将产生更具破坏性的后果(参见:cryptographic hash function on Wikipedia)。

即使使用“体面”哈希算法,碰撞也相对容易发生。例如,在Java中,

String s = new String(new char[size]);

始终哈希为0.也就是说,Java中只包含\0哈希值的所有字符串都为0。


至于“这个容器到底有什么关系吗?”,这又取决于应用程序。您可以设计散列函数,将“类似”对象散列到附近的值。例如,当您要搜索类似对象时,这非常有用。只需将它们全部哈希,看看它们落在哪里。在这种情况下,需要碰撞或近碰撞,因为它将相似的对象分组。

在其他应用程序中,您希望对象中的最轻微更改都会导致完全不同的哈希值。例如,在密码学中就是这种情况,您希望尽可能确定某些内容未被修改。在这种情况下,找到散列到相同值的不同对象要困难得多。

答案 4 :(得分:0)

根据你的应用程序,像MDA,SHA1 / 2等加密哈希可能不是理想的选择,正是因为它们看起来像是完全随机的,因此给你的生日悖论所预测的冲突。传统上,使用基于余数运算的简单哈希的一个原因是密钥被期望是序列号或类似的,因此余数运算将比随机预期的维持更少的冲突。例如。如果你的哈希函数是密钥mod 1009,那么如果键是1..1000的整数,你可能在1009大小的容器中没有冲突。人们有时会通过仔细挑选容器大小和哈希函数来手动调整系统。实现均衡分裂。

当然,如果您不得不担心人们会恶意选择会导致您遇到困难的密钥,或者上游系统会向您发送非常偏向的密钥(因为例如它有自己的哈希表并决定处理散列到X的所有密钥立刻)。您可能希望使用基于密钥加密哈希函数的哈希来防御此问题。