Hash 一个人能否构造一个;“好”;使用CRC32C作为基的哈希函数?

Hash 一个人能否构造一个;“好”;使用CRC32C作为基的哈希函数?,hash,intel,sse,crc32,Hash,Intel,Sse,Crc32,鉴于SSE 4.2(Intel Core i7&i5部件)包含CRC32指令,研究是否可以构建更快的通用哈希函数似乎是合理的。根据本发明,仅CRC32的16位均匀分布。那么,还有什么其他的转变可以克服这一点呢 更新 这个怎么样?只有16位适合哈希值。好的如果您的桌子是65535或更少,那就太好了。如果不是,则通过Nehalem POPCNT(填充计数)指令运行CRC值以获得设置的位数。然后,将其用作表数组的索引。如果您的表格位于1mm条目的南部,则此选项有效。我敢打赌,这比性能最好的哈希函数更便

鉴于SSE 4.2(Intel Core i7&i5部件)包含CRC32指令,研究是否可以构建更快的通用哈希函数似乎是合理的。根据本发明,仅CRC32的16位均匀分布。那么,还有什么其他的转变可以克服这一点呢

更新 这个怎么样?只有16位适合哈希值。好的如果您的桌子是65535或更少,那就太好了。如果不是,则通过Nehalem POPCNT(填充计数)指令运行CRC值以获得设置的位数。然后,将其用作表数组的索引。如果您的表格位于1mm条目的南部,则此选项有效。我敢打赌,这比性能最好的哈希函数更便宜/更快。现在,它有一个CRC32固有的,它应该很容易测试…如果我有丰富的业余时间工作它


戴维

重访,2014年8月
由Arnaud Bouchez在最近的一次评论中提出,鉴于其他答案和评论,我承认原始答案需要修改,或者至少需要修改。最后,我保留了原稿,以供参考

首先,也许是最重要的一点,对这个问题的公平回答取决于哈希代码的预期用途:“好”[哈希函数…]是什么意思?哈希将在何处/如何使用?(例如,它是否用于对相对较短的输入键进行散列?它是否用于索引/查找目的,以生成消息摘要或其他用途?所需的散列码本身、所有32位[CRC32或其衍生物]、更多位、更少位等有多长?
OP问题要求“一个更快的通用哈希函数”,因此重点是速度(CPU密集度较低和/或可以利用各种性质的并行处理的东西)。我们在此可能会注意到,哈希代码本身的计算时间通常只是哈希应用程序中问题的一部分(例如,如果哈希代码的大小或其固有特性导致许多冲突,需要处理额外的周期)。此外,“通用”的要求留下了许多关于可能用途的问题

考虑到这一点,一个简短而更好的答案可能是:

,CRC32C在较新英特尔处理器上的硬件实现可用于构建更快的哈希代码;但是,请注意,根据哈希的具体实现及其应用,由于冲突频率和需要使用更长的代码,总体结果可能不是最优的。此外,对于当然,哈希的加密使用应该仔细检查,因为CRC32算法本身在这方面非常薄弱

原始答案引用了Bret Mulvey关于评估散列函数的一篇文章,正如Mdlg的答案所指出的,本文的结论对于CRC32是错误的,因为它所基于的CRC32的实现是有缺陷的。尽管对于CRC32存在这一重大错误,但这篇文章在以下方面提供了有用的指导这篇文章的URL现在已经失效了;我在上找到了它,但我不知道作者是否在其他地方有它,也不知道他是否更新了它

这里的其他答案引用CityHash 1.0作为使用CRC32C的哈希库的示例。显然,这是在某些较长(超过32位)哈希代码的上下文中使用的,但不适用于CityHash 32()此外,城市哈希函数对CRC32的使用相对较少,与所有移位和洗牌以及为生成哈希代码而执行的其他操作相比。(这不是对CityHash的批评,因为我没有实际操作经验。我将粗略地回顾一下源代码,CityHash函数可以生成良好的代码,例如ell分布式代码,但速度并不明显快于其他各种散列函数。)

最后,您还可以在一篇文章中找到关于这个问题的见解


原始答案和编辑(2010年4月)

先验地,这听起来是个坏主意!

CRC32不是为散列目的而设计的,其分布可能不均匀,因此它是一个相对较差的散列码。此外,它的“置乱”能力相对较弱,导致非常差的单向散列,这将在加密应用中使用

[BRB:我在网上寻找这方面的参考资料…]

谷歌的第一个[keywords=CRC32 distribution]似乎证实了这一点:

编辑:上面引用的页面,以及实际上提供了在哈希函数中查找内容的良好基础

阅读[快速]这篇文章,证实了一个笼统的说法,即一般情况下,CRC32不应用作哈希,但是,根据哈希的具体用途,可能至少部分地使用CRC32作为哈希代码

例如,CRC32代码的较低(或更高,取决于实现)16位具有相对均匀的分布,并且,前提是人们不关心散列码的密码特性(例如,相似密钥产生非常相似的代码的事实),可以构建一个散列码,该散列码使用(例如)较低[或较高]16位的串联,用于由原始密钥的两半(或任何分割)产生的两个CRC32码。

我们需要运行测试,看看内置CRC32指令相对于可选散列函数的效率是否会使调用指令两次以及将代码拼接在一起等的开销不会导致函数整体速度变慢。

只要不使用加密散列,它就可以工作。

出于加密目的,CRC32是一个糟糕的基础,因为