短字符串(标记名称)的最佳32位哈希函数是什么?

And*_*kin 45 tags algorithm hash 32-bit

对于相对较短的字符串,最好的32位散列函数是什么?

字符串是包含英文字母,数字,空格和一些其他字符(标签名称#,$,.,...).例如:Unit testing,C# 2.0.

我正在寻找"最佳碰撞"中的"最佳",性能对我的目标并不重要.

Nic*_*kis 25

我不确定它是否是最佳选择,但这里是字符串的哈希函数:

编程实践(HASH TABLES,第57页)

/* hash: compute hash value of string */
unsigned int hash(char *str)
{
   unsigned int h;
   unsigned char *p;

   h = 0;
   for (p = (unsigned char*)str; *p != '\0'; p++)
      h = MULTIPLIER * h + *p;
   return h; // or, h % ARRAY_SIZE;
}
Run Code Online (Sandbox Code Playgroud)

根据经验,值31和37已被证明是
ASCII字符串的散列函数中乘数的良好选择.

  • 是的,我们使用这个精确的散列函数,MULTIPLIER = 37表示字符串和路径.对我们来说效果很好,即使在2年后我还没有遇到碰撞问题(当然不能保证我们不会) (2认同)
  • 我注意到Perl的哈希算法使用MULTIPLIER = 33,并在最后做了一个额外的步骤:h + =(h >> 5)以改善低阶位的分布. (2认同)
  • 该算法是http://www.cse.yorku.ca/~oz/hash.html中讨论的变体之一.不幸的是,它容易出现基本的哈希冲突攻击(参见[http://www.ocert.org/advisories/ocert-2011-003.html]),因为使用基于子串的(见参考文献)冲突是微不足道的计算; 如果它从未与外部提供的密钥一起使用,则可以正常工作. (2认同)

Nic*_*son 23

如果性能不重要,只需采用安全散列(如MD5或SHA1),并将其输出截断为32位.这将为您提供与随机无法区分的哈希码的分布.

  • MD4(参见http://tools.ietf.org/html/rfc1320)可能更好,因为它实现起来比MD5稍微简单一些.请注意,MD4和MD5都无法与随机区分(两者都是"密码破坏"),但它们仍然足够接近手头的目的. (3认同)
  • @Thomas MD5在你可以创建哈希冲突的意义上被破坏 - 两个明文产生相同的哈希.这并不意味着MD5的输出可以与随机区分开来 - 对MD5没有原像攻击.哪个更容易实现也有点无关紧要 - 他几乎肯定会用他选择的语言预先制作MD5或SHA1. (2认同)
  • @Nick:对MD5的攻击基于差异路径.通过在MD5输入上应用输入差异,您可以获得小于但高于随机的概率,以找出输出中的预期差异.这不会导致preimage攻击,但它使MD5可以与随机预言区分开来.在MD4的情况下,这被证明在(学术上)可用于HMAC(其中碰撞本身不用担心). (2认同)

小智 16

对此,我很抱歉.今年早些时候,我创作了一个名为Hashing Short Strings的页面,这可能对本次讨论很有帮助.总之,我发现CRC-32和FNV-1a优于散列短串.在我的测试中,它们是高效的并且产生广泛分布和无碰撞的哈希.当输出被折叠到32位时,我惊讶地发现MD5,SHA-1和SHA-3产生了少量的冲突.

  • @yyny 上面发布的文章显示了 DJB2 算法对于 2 个字符长的字符串产生 2220 次冲突,对于 3 个字符长的字符串产生 70164 次冲突。冲突率低得多的哈希(例如 FNV-1a)不是更适合对大量小字符串进行哈希吗? (2认同)