如何用 C 编写散列函数?
Posted
技术标签:
【中文标题】如何用 C 编写散列函数?【英文标题】:How to write a hash function in C? 【发布时间】:2011-01-15 08:05:54 【问题描述】:哈希表被认为是存储/检索数据的最快/最佳方式。
我对哈希表的理解,哈希如下(如有错误请指正或如有补充请补充):
哈希表只不过是一个用于存储值的数组(单维或多维)。 散列是在数组中找到索引/位置以插入/检索数据的过程。您获取一个数据项并将其作为键传递给哈希函数,然后您将获得插入/检索数据的索引/位置。我有一个问题:
用于存储/检索数据的散列函数是否不同于 用于身份验证的安全应用程序中的加密哈希函数 像 MD5、HMAC、SHA-1 等...?
它们有何不同?
是否有一些标准或指南? 我们如何确保哈希函数的输出,即索引不超出范围?如果您能提及一些好的链接以更好地理解这些内容,那就太好了。
【问题讨论】:
范围可以用模块(%)操作符限制。 以下页面有几个用 C(和许多其他语言)实现的通用哈希函数的实现:partow.net/programming/hashfunctions/index.html 【参考方案1】:设计目标不同。
例如,对于cryptographic hash functions,您希望散列和散列函数不能用于确定原始数据或任何其他会产生相同散列的数据。
与哈希表和其他数据结构一起使用的哈希函数不需要此类安全属性。如果散列函数很快就足够了,它将输入集均匀地分配到可能的散列集中(以避免不必要的聚类/冲突)。
【讨论】:
【参考方案2】:加密哈希强调让任何人都难以故意制造冲突。对于哈希表,重点通常是快速产生合理的结果分布。因此,两者通常是完全不同的(特别是,加密哈希通常会慢 很多)。
对于典型的哈希函数,结果仅受类型的限制——例如如果它返回一个 size_t,它返回 any 可能的 size_t 是完全可以的。您可以将输出范围缩小到表格大小(例如,使用除以表格大小的余数,通常应该是质数)。
例如,一个相当典型的普通哈希函数可能看起来像:
// warning: untested code.
size_t hash(char const *input)
const int ret_size = 32;
size_t ret = 0x555555;
const int per_char = 7;
while (*input)
ret ^= *input++;
ret = ((ret << per_char) | (ret >> (ret_size - per_char));
return ret;
这里的基本思想是让输入字符串的每一位都影响结果,并且(尽可能快地)让结果的每一位至少受到部分输入的影响。请注意,我并不是特别推荐它作为一个很棒的哈希函数——只是试图说明你想要完成的一些基础知识。
【讨论】:
加密哈希函数不一定很慢。特别是,据报道,MD4 哈希函数在某些平台上比 CRC32 更快(我认为是基于 ARM 的)。然而,加密散列函数往往具有较大的固定开销,这意味着它们对于小的输入消息会很慢。当输入大小超过 1 KB 左右时,像 MD4 这样的函数可以实现非常高的处理带宽(在我的 2.4 GHz Intel CPU 上超过 600 MB/s)。尽管如此,对于小的输入(小于 54 字节),我的 PC 仍然每秒计算 800 万个 MD4(单核)。 @Thomas:首先,虽然 CRC32 可以相当快,但大多数哈希函数都快一点。其次,虽然它肯定是作为加密散列而设计的,但 MD4 不再真正符合条件了。它在几年前就被彻底破坏了——产生碰撞的速度与产生原始哈希的速度差不多。有关实现,请参阅:stachliu.com/md4coll.c。 我知道 MD4 被破坏了,但是对于非加密目的(我们正在谈论的)MD4 是相当好的;如果故意冲突是一个问题,那么根据定义,每个非加密哈希函数都被排除在外。在没有安全问题的情况下,至少可以设想 MD4。一些对等系统使用 MD4 来识别文件元素。至于快速但强大的加密功能,选择新功能的竞争一直存在。详情请见en.wikipedia.org/wiki/NIST_hash_function_competition(我是其中一位候选人的合著者)。 @Thomas:您声称“加密哈希函数不一定很慢”。我的回复只是说 MD4 不支持该断言,因为它不是加密哈希函数。【参考方案3】:鲍勃·詹金斯 (Bob Jenkins) 写了一篇关于他的优点的深入描述,虽然有点过时了,hash function。这篇文章有更新、更好的哈希函数的链接,但这篇文章解决了构建一个好的哈希函数的问题。
此外,大多数哈希表实现实际上使用链表数组来解决冲突。如果你只想使用一个数组,那么哈希函数需要检查冲突并创建一个新的哈希索引。
您提到的加密哈希函数可以用作哈希表的哈希函数, 但它们比为哈希表设计的哈希函数要慢得多。速度使蛮力攻击更容易。
【讨论】:
以上是关于如何用 C 编写散列函数?的主要内容,如果未能解决你的问题,请参考以下文章