hash - 128位哈希的任何64位部分是否像64位哈希一样具有防冲突能力?

标签 hash cryptography sha1 murmurhash

我们正在尝试对开发团队进行内部辩论:

我们正在寻找64位PHP哈希函数。我们找到了PHP implementation of MurmurHash3,但是MurmurHash3是32位或128位,而不是64位。

#1同事认为,要从MurmurHash3生成64位哈希,我们可以简单地对128位哈希的第一个(或最后一个或任何一个)64位进行切片,并且它将像本机一样防碰撞64位哈希函数。

同事#2认为,我们必须找到一种本机64位哈希函数来减少冲突,并且128位哈希的64位分片将不像本机64位哈希那样具有防碰撞能力。

谁是对的?

如果我们采用诸如SHA1之类的加密散列的第一个(或最后一个或任何一个)64位而不是Murmur3,答案是否会改变?

最佳答案

如果您具有真正的随机且均匀分布的值,则“切片”将产生与从一开始就从较小的值开始完全相同的结果。要了解为什么,请考虑以下非常简单的示例:假设您的随机数发生器输出3个随机位,但是只需要一个随机位即可。假设输出为

b1 b2 b3


可能的值为

000, 001, 010, 011, 100, 101, 110, 111


并且所有发生的可能性均等为1/8。现在,无论您出于什么目的,从这三个部分中切下的任意一个(第一,第二或第三位),无论位置如何,“ 1”的概率始终为1/2-对于“ 0”也是如此'。

您可以轻松地将该实验扩展到128位中的64位:无论您对哪些位进行切片,最终在某个位置以1或0结束的可能性将是一半。这意味着如果您从均匀分布的随机变量中获取了样本,那么切片将不会或多或少地降低发生碰撞的可能性。

现在有一个很好的问题:随机函数是否真的是我们可以做的最好的预防冲突方法。但是事实证明,只要函数偏离随机,发现碰撞的可能性就会增加。

加密哈希函数:同事#1获胜

现实生活中的问题是,散列函数根本不是随机的,相反,它们是无确定性的。但是密码散列函数的设计目标如下:如果我们不知道它们的初始状态,那么它们的输出将与真正的随机函数在计算上无法区分,那就是没有一种有效的计算方法来区分散列输出之间的差异和真实的随机值。这就是为什么如果您能找到“区分符”,就认为散列已经很杂乱的原因,这是一种从概率大于一半的真实随机值中分辨出散列的方法。不幸的是,我们无法真正证明现有加密散列的这些属性,但是除非有人破解了它们,否则我们可能会假设这些属性具有一定的把握。这是关于SHA-3提交之一的区分符的paper示例,说明了该过程。

总而言之,除非为给定的密码哈希找到区分符,否则切片非常好,并且不会增加发生冲突的可能性。

非加密哈希函数:同事#2可能会获胜

非加密哈希不必满足与加密哈希相同的一组要求。通常将它们定义为非常快并且在“理智/仁慈的条件下”满足某些属性,但是如果有人试图恶意操纵它们,它们可能很容易落空。关于这在实践中意味着什么的一个很好的例子是今年早些时候针对哈希表实现(hashDoS)的计算复杂性攻击。在正常情况下,非加密哈希工作得很好,但是某些聪明的输入可能会严重削弱它们的抗碰撞能力。密码散列函数不会发生这种情况,因为它们的定义要求它们不受各种聪明输入的影响。

因为有可能(有时甚至很容易)为非加密散列的输出找到类似于上述的区分符,所以我们可以立即说它们不符合加密散列函数的条件。能够分辨出差异意味着输出中存在某种模式或偏差。

而且仅此事实就意味着它们或多或少地偏离了随机函数,因此(按照我们上面的说法,)碰撞可能比随机函数更有可能发生碰撞。最终,由于已经对完整的128位发生冲突的可能性更高,因此使用较短的输出将不会变得更好,在这种情况下冲突可能会更大。

tl; dr截断密码哈希函数很安全。但是,与截断具有较大输出到64位的非密码哈希相比,使用“本机” 64位密码哈希函数更好。

关于hash - 128位哈希的任何64位部分是否像64位哈希一样具有防冲突能力?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11475423/

相关文章:

c++ - 通过网络在不同平台之间比较 boost::typeindex type hash_code() 是否安全?

c++ - C++ 编译器是否识别 2 的幂?

java - 通过 Java 在 Matlab 中计算 MD5 哈希(符合 RFC 1321)

cryptography - 破解DES的代码

go - 卡在 Go 中的 cryptopals 挑战 4

java - 如何将 SHA-1 输出的数组大小从 20 字节更改为适合 AES 加密中的 IV 16 字节

python - boost Python 哈希

python - 如何使用 m2crypto 在非 SSL 设置中验证 X509 证书链

java - java 编码(js 到 java)

c - 散列密码并使用 C 中的签名进行检查