linux 是否有一个glibc哈希函数?

v1uwarro  于 2023-10-16  发布在  Linux
关注(0)|答案(9)|浏览(137)

我期待做一个自定义哈希表在C实现。GNU库中是否已经有MD5/SHA1散列函数,或者我必须使用外部库来实现?
我想找的是:

int hashValue;

hashValue = MD5_HASH(valToHash);
e0uiprwp

e0uiprwp1#

你可以看看Bob Jenkin对许多哈希函数的调查和分析:

或者只是将他的lookup3例程(他已经将其放入公共领域)放入您的项目中:

xfb7svmp

xfb7svmp2#

对于哈希表,您不需要加密强度,只需良好的随机化属性。破解的加密哈希函数(如MD5)很好,但您可能希望使用MD4,它更快,更简单,您可以直接在代码中包含实现。从规范中重写它并不难(因为你只需要一个哈希表的函数,所以如果你在某个时候弄错了,这并不是一个问题)。无耻的插头:在sphlib中有一个MD4的优化C实现。

idfiyjo8

idfiyjo83#

除非你已经有一个很好的理由使用MD5,否则你可能需要重新考虑。在哈希表中,什么是一个“好”的哈希函数很大程度上取决于你想要实现的目标。您可能想阅读Python的dictobject.c中的注解,以了解其他人所做的各种权衡。

dw1jzc5e

dw1jzc5e4#

有几个可信的、简单的版本可用--我在Rdigest源代码中有几个。以下是我在DESCRIPTION文件中写的内容:
产品描述:摘要包提供了使用md5,sha-1,sha-256和crc 32算法创建任意R对象的“散列”列表的功能,允许轻松比较R语言对象。罗恩Rivest的md5算法在RFC 1321中规定,SHA-1和SHA-256算法在FIPS-180-1和FIPS-180-2中规定,crc 32算法在
ftp://ftp.rocksoft.com/cliens/rocksoft/papers/crc_v3.txt。对于md5、sha-1和sha-256,此软件包使用Christophe Devine提供的小型独立实现。对于crc 32,使用来自zlib库的代码。
我认为Christophe的一些代码已经不在www.example.com上cr0.net,但是搜索应该会引导您找到其他几个包含它的项目。他的文件头很清楚:

/*                                                   
 * FIPS-180-1 compliant SHA-1 implementation,   
 * by Christophe Devine <[email protected]>;   
 * this program is licensed under the GPL.  
 */

他的代码与参考输出相符

bwleehnv

bwleehnv5#

Glibc的crypt()使用基于MD5的算法,如果salt以$1$开始。但是既然你提到你要做一个哈希表实现,也许Jenkins哈希会更合适。

slhcrj9b

slhcrj9b6#

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);
}

`

niknxzdl

niknxzdl7#

OpenSSL库拥有您想要的所有加密例程,包括加密哈希。

p5fdfcr1

p5fdfcr18#

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);
zbq4xfa0

zbq4xfa09#

tl;dr Answer

对于现代x86系统来说,CityHash 64可能总是一个不错的选择,尽管它并不总是最快的选择。对于少量的数据(~16字节),FarmHash 64可能是最快的选择,对于中等大小的数据(~128字节),CityHash 64可能是最快的一个,但是数据越大(~4KB),所有的东西就越有利于xxHash 64,最终将主导其他两个。大多数哈希表的键都很小,但如果你知道你的键总是很大,你也可以考虑xxHash 64。
如果你的目标也是非x86系统(ARM、RISC-V、PowerPC)或较旧的x86 CPU(尤其是AMD的CPU),你肯定会更喜欢CityHash 64,因为上面提到的三种CPU在这些条件下的性能都会更差,但CityHash 64被证明比其他两种更稳定。有时FarmHash 64会是最快的非x86 CPU,但即使它击败了CityHash 64,它也是一个相对接近的选择,所以CityHash 64仍然是一个很好的选择。
当目标是32位系统时,使用xxHash 32代替,也就是说,如果32位哈希值足够,对于32位,xxHash 32总是产生良好的结果,并且当哈希数据变得更大时,xxHash 32很快就主导了所有其他数据,已经开始在中等大小范围内。

完整答案

如果你需要哈希表实现的哈希函数,这里有一个很好的候选者列表:

  • clhash:这个哈希值快得离谱。如果哈希值低于64字节,则比CityHash快60%,否则同样快。然而,它需要一个特殊的x86指令,只有较新的x86 CPU支持。因此,它不能移植到旧的CPU,也不能移植到非x86系统(例如,ARM或RISC-V或PowerPC)。

https://github.com/lemire/clhash

  • xxHash:非常快速和可移植的哈希算法,可以利用各种CPU功能,有时比使用memcpy()复制原始字节更快(当然,只有当要哈希的数据当前在CPU缓存中时才有效)。不像大多数其他散列,它使用了很多位移位逻辑指令,这个散列在很大程度上是基于乘法数字,现代CPU可以做得很快,但与旧的CityHash可能会提供更好的性能。

https://xxhash.com

  • CityHash:快速和可移植的算法。它将使用一些SSE,在现代x86 CPU上甚至更快,但它在所有CPU上都提供了良好的性能。请注意,CityHash是用C++编写的,但很容易移植到普通C。

https://github.com/google/cityhash

  • MurmurHash 3:良好的散列,针对不同的x86 CPU进行了优化,并假设小端整数。它可以在非x86 CPU上编译而没有问题,但是它的速度会受到影响,如果这些CPU是大端,你需要在两个地方实现位交换(源代码指出了这些,进一步降低了性能)。如果你不进行位交换,你就破坏了混合,不会得到任何好的哈希值。

https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp

  • FarmHash:是CityHash的继承者,基本上是CityHash和Murmur家族的几个概念的混合。它可能比CityHash更好,也可能不是。谷歌说,它在他们的数据中心表现更好,但你的里程可能会有所不同。

https://github.com/google/farmhash

  • lookup 3:非常可移植的散列函数,只建立在标准C上,我会考虑基线。最初的MurmurHash实际上是作为一个更快的查找替代品而创建的。baseline是什么意思如果你选择的哈希算法不能在速度上超过lookup 3,或者不能创建同样好的哈希值,立即放弃它。没有一个哈希值甚至不能击败lookup 3,这是值得考虑的。你为什么要浪费时间在这上面?只需将公共领域的lookup 3实现复制到您的项目中,然后继续。

https://www.burtleburtle.net/bob/c/lookup3.c

  • SpookyHash:lookup 3的作者还写了另一种可移植的哈希,在没有SSE的机器上比CityHash更快,但参考实现针对x86和小端进行了优化,非常像MurMur 3和C++;但是将这些代码移植到好的老C应该没有问题。

https://www.burtleburtle.net/bob/hash/spooky.html
xxHash在首页上有一个基准比较,但它错过了clhash,并且它只包含三个MurMur 3变体中的一个(只有32位)。它还声称SpookHash只有64位,而实际上它是128位(当产生32/64位哈希时,它只是相应地缩短了128位值)。我不太信任那个表,我认为它被修改过,使xxHash看起来更上级。
在一天结束的时候,没有明确的答案什么是最好的哈希使用。例如,在Core i7- 5820 K系统上并使用64位构建,xxHash 64在更大(0.5KB+)的数据大小上获胜,紧随其后的是64位FarmHash和CityHash;在较小的数据上,这三个总是非常接近,有时一个赢,有时另一个赢。在Phone SE(A9 CPU)上,使用64位进程,xxHash永远不会获胜,CityHash和FarmHash占主导地位。然而,在同一个系统中,在一个32位进程中,xxHash 32击败了其他进程。在Xbox One(AMD Jaguar 1.75GHz CPU)上,尽管使用SSE的x86,但CityHash和FarmHash在xxHash上占主导地位。

问题是,大多数现代哈希函数都是在考虑特定CPU的情况下编写的,对架构进行了假设,或者针对特定数据中心运营商(如Google或Facebook)的需求进行了优化,并且在按设计使用时会优于所有其他哈希函数,但当用于其他场景或其他平台时,结果可能完全不同。它们都具有出色的哈希质量,并且在实践中产生很少的冲突,所以这并不是使它们与众不同的原因。
查看2016年的这篇博客文章,了解详细结果:
https://aras-p.info/blog/2016/08/09/More-Hash-Function-Tests
但有一件事是肯定的:它们都可以轻松地击败MD5,这比上面提到的任何一个都慢100倍,因为MD5被设计为加密安全,这需要比避免冲突所需的更难的混合。当然,MD5也希望避免冲突(两个不相关的数据片段同时产生相同的哈希值),但对于加密哈希函数来说,更重要的是无法反向哈希,这意味着,给定一个特定的哈希值,它必须不可能产生数据,当得到哈希时,将产生完全相同的值。如果你可以产生碰撞,那是非常糟糕的,并允许许多类型的攻击,这就是为什么MD5不再安全了(有一种已知的方法可以产生碰撞,而且非常快),但到今天为止,没有方法可以产生将哈希到给定值的数据,如果你可以做到这一点,所有的门都对你甚至可以想到的任何攻击开放。

相关问题