我想在C语言中实现一个自定义哈希表,GNU库中是否已经有MD5/SHA1哈希函数,还是我需要使用外部库?
以下是我大致要实现的功能:
int hashValue;
hashValue = MD5_HASH(valToHash);
有一些可信的、简单的版本可供使用——在R的摘要源代码中我有几个版本。以下是我在DESCRIPTION文件中编写的内容:
描述:digest包提供了使用md5、sha-1、sha-256和crc32算法创建任意R对象的“哈希”摘要的函数,从而方便比较R语言对象。Ron Rivest的md5算法在RFC 1321中指定,SHA-1和SHA-256算法在FIPS-180-1和FIPS-180-2中指定,crc32算法在ftp://ftp.rocksoft.com/cliens/rocksoft/papers/crc_v3.txt中描述。对于md5、sha-1和sha-256,此软件包使用Christophe Devine提供的小型独立实现。对于crc32,使用zlib库中的代码。我认为Christophe的一些代码不再在cr0.net上,但搜索应该会引导您找到其他几个项目并将其合并。他的文件头非常清晰:/*
* FIPS-180-1 compliant SHA-1 implementation,
* by Christophe Devine <devine@cr0.net>;
* this program is licensed under the GPL.
*/
他的代码与参考输出相匹配。
gcrypt和openssl可以进行MD5、SHA和其他哈希操作,以下是使用libgcrypt的示例:
#include <gcrypt.h>
#include <stdio.h>
// compile gcc md5_test.c -lgcrypt
int main(int argc, char *argv[])
{
unsigned char digest[16];
char digest_ascii[32+1] = {0,};
int digest_length = gcry_md_get_algo_dlen (GCRY_MD_MD5);
int i;
printf("hashing=%s len=%d\n", argv[1], digest_length);
gcry_md_hash_buffer(GCRY_MD_MD5, digest, argv[1], strlen(argv[1]));
for (i=0; i < digest_length; i++) {
sprintf(digest_ascii+(i*2), "%02x", digest[i]);
}
printf("hash=%s\n", digest_ascii);
}
`
除非您已经有充分的理由使用MD5,否则您可能需要重新考虑。在哈希表中,什么样的“好”哈希函数取决于您试图实现什么目标。您可以阅读Python的dictobject.c
中的评论,以了解其他人所做出的权衡。
如果salt以$1$开头,Glibc的crypt()
使用基于MD5的算法。但是你提到你要做哈希表实现,也许Jenkins哈希更合适。
OpenSSL库拥有您所需的所有加密例程,包括密码哈希。
Murmur3是一种快速的非加密算法,您可以使用它。
在这个主题https://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed中可以找到Murmur与其他算法的速度比较。
一个可能的实现:https://github.com/PeterScott/murmur3
示例:
uint32_t hash;
uint32_t seed = 42;
char* input = "HelloWorld";
MurmurHash3_x86_32(input, strlen(input), seed, &hash);
printf("x86_32: %08x\n", hash);
对于现代x86系统来说,CityHash64通常是一个不错的选择,尽管它并不总是最快的选项。对于少量数据(约16字节),FarmHash64可能是最快的选择;对于中等大小的数据(约128字节),CityHash64可能是最快的;但是随着数据变得越来越大(约4KB),xxHash64会逐渐占据优势,最终主导其他两种算法。大多数哈希表的键值通常较小,但如果您知道键值始终很大,您也可以考虑使用xxHash64。
如果您还针对非x86系统(ARM、RISC-V、PowerPC)或旧的x86 CPU(尤其是AMD的CPU),您应该明确选择CityHash64,因为在这些条件下,上述三种算法都表现较差,而CityHash64证明比其他两种算法更稳定。有时候FarmHash64在非x86 CPU上可能是最快的,但即使它击败了CityHash64,差距也相对较小,所以CityHash64仍然是一个不错的选择。
当针对32位系统时,请使用xxHash32,即使32位哈希值足够,因为对于32位来说,xxHash32总是在哈希数据变大时快速占据主导地位,并且始终产生良好的结果,尤其是在中等大小范围内。
以下是一些适用于哈希表实现的良好候选的哈希函数:
clhash: 这个哈希函数速度非常快。如果哈希值小于64字节,比CityHash快60%,否则同样快。然而,它需要一条特殊的x86指令,只有较新的x86 CPU支持。因此,它不能在旧的CPU上使用,也不能在非x86系统(如ARM、RISC-V或PowerPC)上使用。memcpy()
复制原始字节更快(当要哈希的数据当前在CPU缓存中时)。与大多数其他哈希算法不同,它主要基于乘法运算,现代CPU可以非常快速地执行,但在旧的CPU上,CityHash可能提供更好的性能。