我们正试图解决我们开发团队的内部辩论:
我们正在寻找64位PHP哈希函数。我们找到了PHP implementation of MurmurHash3,但MurmurHash3是32位或128位,而不是64位。
同事#1认为,要从MurmurHash3生成64位散列,我们可以简单地对128位散列的第一个(或最后一个或任意)64位进行切片,并且它将作为防冲突作为本机64位散列函数。
同事#2认为我们必须找到一个原生的64位散列函数来减少冲突,并且128位散列的64位片段不会像本机64位散列那样具有抗冲突性。< / p>
谁是对的?
如果我们采用像SHA1而不是Murmur3这样的加密哈希的第一个(或最后一个或任何)64位,答案是否会改变?
答案 0 :(得分:15)
如果你有真正的随机,均匀分布的值,那么&#34;切片&#34;将产生完全相同的结果,就好像从一开始就使用较小的值开始一样。要了解原因,请考虑这个非常简单的示例:假设您的随机发生器输出3个随机位,但您只需要一个随机位即可。让我们假设输出是
b1 b2 b3
可能的值是
000, 001, 010, 011, 100, 101, 110, 111
并且所有都以1/8的相等概率发生。现在无论你为了自己的目的而从这三个方面切入的是什么 - 第一个,第二个或第三个 - 有一个&#39; 1&#39;无论位置如何,总是为1/2,对于&#39; 0&#39;同样如此。
您可以轻松地将此实验扩展到128位中的64位:无论您切片哪个位,在某个位置以一个或零结束的概率将是一半。这意味着如果你从均匀分布的随机变量中取样,那么切片不会或多或少地产生碰撞概率。
现在一个很好的问题是随机函数是否真的是我们能够做的最好的事情来防止碰撞。但事实证明,只要函数偏离随机函数,就会发现发现碰撞的概率会增加。
现实生活中的问题是哈希函数根本不是随机的,相反,它们具有确定性。但加密哈希函数的设计目标如下:如果我们不知道它们的初始状态,那么它们的输出在计算上与真正的随机函数无法区分,也就是没有计算上有效的方法来判断哈希输出和实际随机值之间的差异。这就是为什么如果你能找到一个&#34; distinctisher&#34;这个方法来告诉散列来自真实随机值的概率高于一半,你就会认为哈希已经被破坏了。遗憾的是,我们无法真正证明现有加密哈希值的这些属性,但除非有人违反这些属性,否则我们可能会认为这些属性具有一定的信心。下面是一个paper示例,其中有一个SHA-3提交的区分符说明了该过程。
总而言之,除非找到给定加密哈希的区分符,否则切片完全正常并且不会增加碰撞的概率。
非加密哈希不必像加密哈希那样满足相同的要求。它们通常被定义为非常快并且在理智/仁慈的条件下满足某些特性&#34;但是如果有人试图恶意操纵它们,它们可能很容易失败。这在实践中意味着一个很好的例子就是今年早些时候对哈希表实现(hashDoS)的计算复杂性攻击。在正常情况下,非加密哈希值可以很好地工作,但是它们的抗碰撞性可能会被一些聪明的输入严重破坏。加密哈希函数不会发生这种情况,因为它们的定义要求它们不受各种智能输入的影响。
因为有可能(有时甚至很容易)找到非加密哈希输出的上述区分符,我们可以立即说它们不符合加密哈希函数的条件。能够分辨出差异意味着输出中存在模式或偏差。
而这一事实本身就意味着它们或多或少地偏离了随机函数,因此(在我们上面说过之后)碰撞可能比随机函数更可能发生。最后,由于冲突发生的概率已经超过了全部128位,因此在输出时间越短越好,在这种情况下可能更容易发生冲突。
tl; dr 截断时,您可以使用加密哈希函数安全。但是,你和#34;本地人&#34;会更好。 64位加密散列函数与将较大输出截断为64位的非加密散列相比较。
答案 1 :(得分:7)
由于雪崩效应,强散列是指源中的单个位变化导致散列平均翻转的一半位的散列。那么,对于一个好的哈希,&#34;哈希&#34;均匀分布,因此每个部分或切片受到相等且均匀分布的源位数量的影响,因此与同一位长度的任何其他切片一样强。
只要哈希具有良好的属性和均匀分布,我就同意同事1。
答案 2 :(得分:1)
如果不提及这个问题,这个问题似乎不完整:
对于特定类别的输入,某些哈希值可证明是perfect哈希值(例如,对于n
的某个合理值,输入长度n
。如果你截断那个哈希,那么你可能会破坏该属性,在这种情况下,根据定义,你将冲突率从零增加到非零,并且你已经削弱了该用例中的哈希值。
这不是一般情况,但它是截断哈希时合理关注的一个例子。