使用XOR转换产生可用的校验和是否有效?我找不到任何证据表明碰撞比CRC32更多。
我确实对1000万个随机生成的8到32个长度字节数组进行了模拟,下面的hash32方法实际产生的冲突比CRC32少2%。
此外,代码的运行速度似乎比Java的内置util.zip.CRC32类快40倍。
public static long hash64( byte[] bytes )
{
long x = 1;
for ( int i = 0; i < bytes.length; i++ )
{
x ^= bytes[ i ];
x ^= ( x << 21 );
x ^= ( x >>> 35 );
x ^= ( x << 4 );
}
return x;
}
public static int hash32( byte[] bytes )
{
int x = 1;
for ( int i = 0; i < bytes.length; i++ )
{
x ^= bytes[ i ];
x ^= ( x << 13 );
x ^= ( x >>> 17 );
x ^= ( x << 5 );
}
return x;
}
答案 0 :(得分:1)
是的,如果您需要的只是一个简单的文件校验和,则它是完全有效的替代方法,但这不是最佳解决方案。
CRC经过优化,可可靠地检测到burst errors, not 的抗碰撞性或均匀分布。从表面上看,CRC-32可能看起来像是一般的哈希函数或校验和,但it readily fails avalanche and collision tests却可以工作。 CRC的运行速度也很慢,因为它必须执行多项式除法,即使将其大量优化为移位运算,也需要昂贵的运算。由于不可避免的每次检查的范围检查和条件检查,在诸如Java之类的解释语言中,利用查找表(LUT)的CRC的表版本也很慢。
您的解决方案是采用伪随机函数(PRF)Xorshift,并将其转换为哈希函数。从表面上看,这似乎已经通过了基本的碰撞测试,但这并不是一个很好的选择。它的雪崩行为非常差,因此发生碰撞的可能性大于您的测试不够敏感的概率。不仅如此,它还是次优的,一次只读取一个字节。存在具有可比性能的更好解决方案。
64-bit MurmurHash3是一个更好的选择,如果经过充分优化,它在Java中的性能会很好。对于大型输入,它甚至可能比您的解决方案更快。我还建议阅读Bret Mulvey's article on Hash Functions。它说明了如何以可消化的方式构造和测试哈希函数。