CRC32可以用作散列函数吗?
Posted
技术标签:
【中文标题】CRC32可以用作散列函数吗?【英文标题】:Can CRC32 be used as a hash function? 【发布时间】:2012-06-12 19:33:14 【问题描述】:CRC32 可以用作散列函数吗?这种方法有什么缺点吗? 有什么取舍吗?
【问题讨论】:
似乎已经被问到了。 ***.com/questions/2694740/… 这取决于你想用哈希做什么。 对于集合哈希的某个子集,是的。但是,它不是块代码,而是流代码。对于非常小的块,使用表格会更快。 【参考方案1】:CRC32 作为散列算法非常好工作。 CRC 的重点 是对字节流进行哈希处理,并尽可能减少冲突。也就是说,有几点需要考虑:
CRC 不安全。对于安全散列,您需要一个计算量更大的算法。对于简单的桶哈希器,安全性通常不是问题。
存在具有不同属性的不同 CRC 风格。确保使用正确的算法,例如使用哈希多项式 0x11EDC6F41 (CRC32C),这是最佳的通用选择。
作为哈希速度/质量的权衡,x86 CRC32 指令很难被击败。但是,旧 CPU 中不存在此指令,因此请注意移植性问题。
---- 编辑----
Mark Adler 提供了一个链接,指向 Bret Mulvey 的一篇有用的哈希评估文章。使用文章中提供的源代码,我为 CRC32C 和 Jenkins96 运行了“桶测试”。这些表格显示了真正均匀分布比偶然测量的结果更差的概率。因此,数字越大越好。作者认为 0.05 或更低为弱,0.01 或更低为非常弱。在这一切上我完全信任作者,我只是在报告结果。
在 CRC32C 的性能优于 Jenkins96 的所有实例中,我都放置了 *。通过这个简单的统计,CRC32C 是一个比 Jenkins96 更均匀的哈希 54 次 96 次。 特别是如果你可以使用 x86 CRC32 指令,速度性能权衡非常好。
CRC32C (0x1EDC6F41) 统一键 文本键 稀疏键 位 下 上 下 上 下 上 1 0.671 *0.671 *1.000 0.120 *0.572 *0.572 2 *0.706 *0.165 *0.729 *0.919 0.277 0.440 3 *0.878 *0.879 *0.556 0.362 *0.535 *0.542 4 0.573 0.332 0.433 0.462 *0.855 0.393 5 0.023 *0.681 0.470 0.907 0.266 0.059 6 *0.145 *0.523 0.354 *0.172 *0.336 0.588 7 0.424 0.722 0.172 *0.736 0.184 *0.842 8 *0.767 0.507 *0.533 0.437 0.337 0.321 9 0.480 0.725 *0.753 *0.807 *0.618 0.025 10 *0.719 0.161 *0.970 *0.740 *0.789 0.344 11 *0.610 0.225 *0.849 *0.814 *0.854 *0.003 12 *0.979 *0.239 *0.709 0.786 0.171 *0.865 13 *0.515 0.395 0.192 0.600 0.869 *0.238 14 0.089 *0.609 0.055 *0.414 *0.286 *0.398 15 *0.372 *0.719 *0.944 0.100 *0.852 *0.300 16 0.015 *0.946 *0.467 0.459 0.372 *0.793对于 Jenkins96,文章作者认为它是一个优秀的哈希:
詹金斯96 统一键 文本键 稀疏键 位 下 上 下 上 下 上 1 0.888 0.572 0.090 0.322 0.090 0.203 2 0.198 0.027 0.505 0.447 0.729 0.825 3 0.444 0.510 0.360 0.444 0.467 0.540 4 0.974 0.783 0.724 0.971 0.439 0.902 5 0.308 0.383 0.686 0.940 0.424 0.119 6 0.138 0.505 0.907 0.103 0.300 0.891 7 0.710 0.956 0.202 0.407 0.792 0.506 8 0.031 0.552 0.229 0.573 0.407 0.688 9 0.682 0.990 0.276 0.075 0.269 0.543 10 0.382 0.933 0.038 0.559 0.746 0.511 11 0.043 0.918 0.101 0.290 0.584 0.822 12 0.895 0.036 0.207 0.966 0.486 0.533 13 0.290 0.872 0.902 0.934 0.877 0.155 14 0.859 0.568 0.428 0.027 0.136 0.265 15 0.290 0.420 0.915 0.465 0.532 0.059 16 0.155 0.922 0.036 0.577 0.545 0.336【讨论】:
不,CRC 不能避免冲突以及其他算法。见home.comcast.net/~bretm/hash。 @Mark,作者没有使用 CRC32C 多项式。 CRC32C 在他的测试程序中可以很好地用作对字节字符串进行分桶的哈希。 很好的研究! +1。但是,我仍然认为即使使用 crc32 指令,它也不会击败为(非加密)散列而设计的散列算法。你可以在这里找到一些更高级的哈希算法开发和测试:code.google.com/p/smhasher。 顺便说一句,Bret Mulvey 几个月前将该网站移至:bretmulvey.com/hash 还是没有。 CRC-32 和 CRC-32C 都无法通过雪崩测试。【参考方案2】:我不知道为什么 Mark Adler 会说“crc32 很难将输入位分配给散列”。 crc32 散列中没有一个位与输入位完全相等。散列的任何位都是输入位的线性组合。其次,crc 总是将相同数量的不同输入序列均匀地映射到给定的哈希值。例如,如果你有 1000 位长的消息,在 crc32 之后,你总能找到 2^(1000-32) 个产生给定哈希值的序列,不多也不少。
如果您不需要安全功能,crc 可以完美地充当哈希。
其实我觉得其他非安全的hash函数可能比crc简单,如果你需要更长的crc,比如crc-256。
【讨论】:
我相信他说的是因为 CRC 未能通过统计随机性测试 - 均匀分布在代码范围内,不会偏向某些位。【参考方案3】:CRC32 将字节映射到 32 位整数,然后用 xor 对它们进行累加。这意味着每个字节仅影响散列中 32 位中的 8 位。当然 CRC32 也会发生变化,但它只是隐藏了问题。 IE。它会不均匀地分配密钥,在某些区域会有大量的聚类。看起来这样的哈希工作正常,直到你到达那个区域,突然你的 O(1) 哈希表变成了 O(n) 哈希表。
CRC32 旨在检测损坏的文件,而不是散列。正如 Mark 所说,它不会保护您的文件不被修改,因为黑客仍然可以通过在更改后插入正确制作的 32 位值来随意修改它们。
【讨论】:
以上是关于CRC32可以用作散列函数吗?的主要内容,如果未能解决你的问题,请参考以下文章