理解消息摘要与消息认证码
2021-05-05 13:02:28 阿炯

消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,由一个单向Hash加密函数对消息进行作用而产生。HASH函数的抗冲突性使得如果一段明文稍有变化,哪怕只更改该段落的一个字母位,通过哈希算法作用后都将产生不同的输出值。而HASH算法的单向性使得要找到哈希值相同的两个不同的输入消息,在计算上是不可能的。所以数据的哈希值,即消息摘要,可以检验数据的完整性。

将长度不固定的消息(message)作为输入参数,运行特定的Hash函数,生成固定长度的Hash值输出,也称为这个消息的消息摘要(Message Digest)。简单地说,就是通过消息摘要算法产生一段字符串。输入内容进行消息摘要处理后输出一些内容。常见的有MD5和SHA系列(MDx、SHAx、MAC等方式)。理论上只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。

数字摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法或散列算法。消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文(摘要可以比方为指纹,消息摘要算法就是要得到文件指纹的系列方法)。

传统的Checksum是弱校验,可以将一些位翻转校验出来,但是却无法校验出一些复杂的数据错误、人为制造的数据篡改。使用Hash函数将原始属于作为输入参数,生成固定长度的消息摘要,MD5算法为128位,SHA-1为160位,附在原始数据的尾部,到达目的地,先将原始数据(message)与消息摘要(message digest)分离,然后运行同样的Hash算法,生成自己的消息摘要,比较两个消息摘要,相同则校验通过。

特点:
无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
一般地,只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。
只能进行正向的信息摘要,而无法从摘要中恢复出任何的消息,甚至根本就找不到任何与原信息相关的信息(不可逆性)。
好的摘要算法,没有人能从中找到“碰撞”或者说极度难找到,虽然“碰撞”是肯定存在的(碰撞即不同的内容产生相同的摘要)。

应用:
一般把对一个信息的摘要称为该消息的指纹或数字签名。数字签名是保证信息的完整性和不可否认性的方法。数据的完整性是指信宿接收到的消息一定是信源发送的信息,而中间绝无任何更改;信息的不可否认性是指信源不能否认曾经发送过的信息。其实,通过数字签名还能实现对信源的身份识别(认证),即确定“信源”是否是信宿意定的通信伙伴。

数字签名应该具有唯一性,即不同的消息的签名是不一样的;同时还应具有不可伪造性,即不可能找到另一个消息,使其签名与已有的消息的签名一样;还应具有不可逆性,即无法根据签名还原被签名的消息的任何信息。这些特征恰恰都是消息摘要算法的特征,所以消息摘要算法适合作为数字签名算法。

消息摘要算法有多种,包括MD2、MD4、MD5、SHA-1、SHA-256、RIPEMD128、RIPEMD160等,文尾有一个简要的概述。既然Hash算法是公开的,那如果有人先将数据篡改,再按照Hash算法生成一个全新的消息摘要附在数据的末尾,到达终点会如何?很显然校验会通过,那只有接受数据被篡改的现实,那如何避免以上不安全的数据传输呢?

加密的消息摘要(HMAC)上场了,不过先了解一下消息认证码。


消息认证码MAC(Message authentication code)

在密码学中,消息认证码又译为消息鉴别码、文件消息认证码、讯息鉴别码、信息认证码,是经过特定算法后产生的一小段信息,检查某段消息的完整性,以及作身份验证。它可以用来检查在消息传递过程中,其内容是否被更改过,不管更改的原因是来自意外或是蓄意攻击;同时可以作为消息来源的身份验证,确认消息的来源。

消息认证码的算法中,通常会使用带密钥的散列函数(HMAC),或者块密码的带认证工作模式(如GCM,CCM)。信息认证码不能提供对信息的保密,若要同时实现保密认证,同时需要对信息进行加密。

消息摘要的应用

1.数据完整性检查(Data Integrity Check)
用于SSL/TLS/IPsec,将原始数据作为输入参数,生成Message Digest,然后用共享对称密钥加密,接收方做逆操作。

2.数字证书签名( Digital Certification Signature)
将主机(服务器)的数字证书(明文)作为输入参数,生成Message Digest,然后用CA的私钥(Private Key)加密,这个Message Digest就变成了CA的数字签名,附在原始数字证书(明文)的末尾,成为一个整体,此整体即为CA签名的数字证书。服务器与客户端认证时,将上文CA签名的数字证书发给客户端,客户端由于拥有CA的公钥(浏览器预装或手动安装),可以解密CA的数字签名,得到Message Digest,然后自己对数字证书运行相同的Hash算法,然后比较两个Message Digest,相同则认证通过。

3.数据校验 (Checksum)
将原始文件生成MD5 checksum,用户下载完文件,也计算一下下载文件的MD5 checksum,如果相同,则文件完好无缺。

4.数据来源可靠性认证(Authentication)



主要用于OSPF/ISIS/BGP,将原始数据+共享对称密钥作为共同输入参数,生成HMAC,接收方逆操作。

消息摘要与消息认证码MAC的区别在于消息摘要只能保证消息的完整性,MAC不仅能够保证完整性,还能够保证真实性。MAC不能保证消息的不可抵赖性,而数字签名可以保证。因为数字签名使用的是公钥密码体制,私钥只有你自己才知道;而MAC使用对称加密,既然一方能够验证你的MAC,就能够伪造你的MAC,因为发送方和接收方的秘钥是一样的。当然如果在MAC中绑定一些关键信息,并通过某些手段,让一方只能生成MAC,另一方只能验证MAC,也是可以实现签名效果的。详见附3。


加密的消息摘要HMAC(Keyed Hash Message Authentication Code)

密钥散列消息认证码(Keyed-hash message authentication code),又称散列消息认证码(Hash-based message authentication code,缩写为HMAC),是一种通过特别计算方式之后产生的消息认证码(MAC),即使用密码散列函数,同时结合一个加密密钥。它可以用来保证资料的完整性,同时可以用来作某个消息的身份验证。



上文提到的常规Hash算法,如MD5、SHA,只有一个输入参数:消息。如果输入参数有两个,一个是原始数据,另外一个是密钥(Key),将会生成一个加密的消息摘要HMAC。那第三方即使篡改数据,由于没有密钥,很难生成一个全新的加密摘要而不被终点主机发现并丢弃。

有人肯定会说,MD5/SHA-1碰撞(Collision )一直存在着,什么是碰撞?简而言之就是不同的消息,产生相同的消息摘要!无论是理论上还是现实中碰撞是存在的,尽管概率非常非常小,有安全研究人员在几秒之内通过特殊算法,可以人为地制造碰撞,那我们自然就会产生一个念头,没有Key,能否篡改一部分敏感数据,然后调整其它剩余数据,保证HMAC不变呢?尽管很难,这在理论上是成立的。为了增强HMAC的安全性,只要升级加密Hash算法就可以指数级地增加破解的难度,如HMAC-MD6、HMAC-SHA-3。

根据RFC 2104,HMAC的数学公式为:


其中:
H为密码散列函数(如SHA家族)
K为密钥(secret key)
m是要认证的消息
K'是从原始密钥K导出的另一个秘密密钥(如果K短于散列函数的输入块大小,则向右填充(Padding)零;如果比该块大小更长,则对K进行散列)
|| 代表串接
⊕ 代表异或(XOR)
opad 是外部填充(0x5c5c5c…5c5c,一段十六进制常量)
ipad 是内部填充(0x363636…3636,一段十六进制常量)

HMAC支持的算法有:md5、sha1、sha256、sha512、adler32、crc32、crc32b、fnv132、fnv164、fnv1a32、fnv1a64、gost、gost-crypto、haval128,3、haval128,4、haval128,5、haval160,3、haval160,4、haval160,5、haval192,3、haval192,4、haval192,5、haval224,3、haval224,4、haval224,5、haval256,3、haval256,4、haval256,5、joaat、md2、md4、ripemd128、ripemd160、ripemd256、ripemd320、sha224、sha384、snefru、snefru256、tiger128,3、tiger128,4、tiger160,3、tiger160,4、tiger192,3、tiger192,4、whirlpool

常见HMAC种类:
算法种类    摘要长度
HMAC-MD5    128
HMAC-SHA1    160
HMAC-SHA256    256
HMAC-SHA384    384
HMAC-SHA512    512

为了防止黑客通过彩虹表根据哈希值反推原始口令,在计算哈希时需要增加一个salt来使得相同的输入也能得到不同的哈希,这样就大大增加了黑客破解的难度。通常我们计算MD5时采用md5(message + salt)。类似的加盐校验方法有:MAC= H( key + message )、MAC = H(message + key) 或者 H(key + message + key)。但是它们依旧存在安全隐患,这些粗陋的MAC实现方法让大家意识到需要一种靠得住的MAC实现方法,这便是HMAC的由来。



HMAC通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。和我们自定义的加salt算法不同,Hmac算法针对各种哈希算法都通用,无论是MD5还是SHA-1。采用Hmac替代我们自己的salt算法,可以使程序算法更标准化,也更安全。


附1:消息摘要的算法

CRC8、CRC16、CRC32
CRC(Cyclic Redundancy Check,循环冗余校验)算法出现时间较长,应用也十分广泛,尤其是通讯领域,现在应用最多的就是 CRC32 算法,它产生一个4字节(32位)的校验值,一般是以8位十六进制数,如FA 12 CD 45等。CRC算法的优点在于简便、速度快,严格的来说,CRC更应该被称为数据校验算法,但其功能与数据摘要算法类似,因此也作为测试的可选算法。

在 WinRAR、WinZIP 等软件中,也是以 CRC32 作为文件校验算法的。一般常见的简单文件校验(Simple File Verify – SFV)也是以CRC32算法为基础,它通过生成一个后缀名为.SFV 的文本文件,这样可以任何时候可以将文件内容 CRC32运算的结果与.SFV文件中的值对比来确定此文件的完整性。与 SFV 相关工具软件有很多,如MagicSFV、MooSFV等。

MD2 、MD4、MD5
这是应用非常广泛的一个算法家族,尤其是 MD5(Message-Digest Algorithm 5,消息摘要算法版本5),它由MD2、MD3、MD4发展而来,由Ron Rivest(RSA公司)在1992年提出,目前被广泛应用于数据完整性校验、数据(消息)摘要、数据加密等。MD2、MD4、MD5 都产生16字节(128位)的校验值,一般用32位十六进制数表示。MD2的算法较慢但相对安全,MD4速度很快,但安全性下降,MD5比MD4更安全、速度更快。

目前在互联网上进行大文件传输时,都要得用MD5算法产生一个与文件匹配的、存储MD5值的文本文件(后缀名为 .md5或.md5sum),这样接收者在接收到文件后,就可以利用与 SFV 类似的方法来检查文件完整性,目前绝大多数大型软件公司或开源组织都是以这种方式来校验数据完整性,而且部分操作系统也使用此算法来对用户密码进行加密,另外它也是目前计算机犯罪中数据取证的最常用算法。与MD5相关的工具有很多,在Windows平台下的WinMD5等。

SHA1、SHA256、SHA384、SHA512
SHA(Secure Hash Algorithm)是由美国专门制定密码算法的标准机构——美国国家标准技术研究院(NIST)制定的,SHA系列算法的摘要长度分别为:SHA为20字节(160位)、SHA256为32字节(256位)、SHA384为48字节(384位)、SHA512为64字节(512位),由于它产生的数据摘要的长度更长,因此更难以发生碰撞,因此也更为安全,它是未来数据摘要算法的发展方向。由于SHA系列算法的数据摘要长度较长,因此其运算速度与MD5相比,也相对较慢。目前SHA1的应用较为广泛,主要应用于CA和数字证书中,另外在目前互联网中流行的BT软件中,也是使用SHA1来进行文件校验的。

RIPEMD、PANAMA、TIGER、ADLER32 等
RIPEMD是Hans Dobbertin等3人在对MD4,MD5缺陷分析基础上,于1996年提出来的,有4个标准128、160、256和320,其对应输出长度分别为16字节、20字节、32字节和40字节。TIGER由Ross在1995年提出。Tiger号称是最快的Hash算法,专门为64位机器做了优化。


附2:密码散列函数


密码散列函数(英语:Cryptographic hash function),又译为加密散列函数、密码散列函数、加密散列函数,是散列函数的一种。它被认为是一种单向函数,也就是说极其难以由散列函数输出的结果,回推输入的资料是什么。这样的单向函数被称为“现代密码学的驮马”。这种散列函数的输入资料,通常被称为消息(message),而它的输出结果,经常被称为消息摘要(message digest)或摘要(digest)。在信息安全中,有许多重要的应用,都使用了密码散列函数来实现,例如数字签名,消息认证码。



一个理想的密码散列函数应该有四个主要的特性:
对于任何一个给定的消息,它都很容易就能运算出散列数值。
难以由一个已知的散列数值,去推算出原始的消息。
在不更动散列数值的前提下,修改消息内容是不可行的。
对于两个不同的消息,只有极低的几率会产生相同的散列数值。


附3:消息认证码与数字签名

消息认证码和数字签名技术通过对消息的摘要进行加密,可用于消息防篡改和身份证明问题。

消息认证码全称是“基于Hash的消息认证码”(Hash-based Message Authentication Code,HMAC)。消息验证码基于对称加密,可以用于对消息完整性(integrity)进行保护。

基本过程为:对某个消息利用提前共享的对称密钥和Hash算法进行加密处理,得到HMAC值。该HMAC值持有方可以证明自己拥有共享的对称密钥,并且也可以利用HMAC确保消息内容未被篡改。

典型的HMAC(K,H,Message)算法包括三个因素,K为提前共享的对称密钥,H为提前商定的Hash算法(一般为公认的经典算法如SHA-256),Message为要处理的消息内容。如果不知道K或H的任何一个,则无法根据Message得到正确的HMAC 值。

消息认证码一般用于证明身份的场景。如Alice、Bob提前共享和HMCA的密钥和Hash算法,Alice需要知晓对方是否为Bob,可发送随机消息给Bob。Bob收到消息后进行计算,把消息HMAC值返回给Alice,Alice通过检验收到HMAC值的正确性可以知晓对方是否是Bob。注意这里并没有考虑中间人攻击的情况,假定信道是安全的。

消息认证码使用过程中主要问题是需要共享密钥。当密钥可能被多方拥有的场景下,无法证明消息来自某个确切的身份。反之,如果采用非对称加密方式,则可以追溯到来源身份,即数字签名。

数字签名与在纸质合同上签名确认合同内容和证明身份类似,数字签名基于非对称加密,既可以用于证实某数字内容的完整性,又同时可以确认来源(或不可抵赖,Non-Repudiation)。

一个典型的场景:Alice通过信道发给Bob一个文件(一份信息),Bob如何获知所收到的文件即为Alice发出的原始版本?Alice可以先对文件内容进行摘要,然后用自己的私钥对摘要进行加密(签名),之后同时将文件和签名都发给Bob。Bob收到文件和签名后,用Alice的公钥来解密签名,得到数字摘要,与收到文件进行摘要后的结果进行比对。如果一致,说明该文件确实是Alice发过来的(别人无法拥有Alice的私钥),并且文件内容没有被修改过(摘要结果一致)。

知名的数字签名算法包括DSA(Digital Signature Algorithm)和安全强度更高的ECSDA(Elliptic Curve Digital Signature Algorithm)等。除普通的数字签名应用场景外,针对一些特定的安全需求,产生了一些特殊数字签名技术,包括盲签名、多重签名、群签名、环签名等。

1.盲签名

盲签名(blind signature)是在1982年由David Chaum在论文《Blind Signatures for Untraceable Payment》中提出。签名者需要在无法看到原始内容的前提下对信息进行签名。盲签名可以实现对所签名内容的保护,防止签名者看到原始内容;另一方面,盲签名还可以实现防止追踪(unlinkability),签名者无法将签名内容和签名结果进行对应。典型的实现包括RSA盲签名算法等。

2.多重签名

多重签名(multiple signature)即n个签名者中,收集到至少m个(n>=m>=1)的签名,即认为合法。其中,n是提供的公钥个数,m是需要匹配公钥的最少的签名个数。多重签名可以有效地被应用在多人投票共同决策的场景中。例如双方进行协商,第三方作为审核方。三方中任何两方达成一致即可完成协商。比特币交易中就支持多重签名,可以实现多个人共同管理某个账户的比特币交易。

3.群签名

群签名(group signature)即某个群组内一个成员可以代表群组进行匿名签名。签名可以验证来自于该群组,却无法准确追踪到签名的是哪个成员。群签名需要存在一个群管理员来添加新的群成员,因此存在群管理员可能追踪到签名成员身份的风险。群签名最早于1991年由David Chaum和Eugene van Heyst提出。

4.环签名

环签名(ring signature),由Rivest、Shamir和Tauman三位密码学家在2001年首次提出。环签名属于一种简化的群签名。签名者首先选定一个临时的签名者集合,集合中包括签名者自身。然后签名者利用自己的私钥和签名集合中其他人的公钥就可以独立地产生签名,而无需他人的帮助。签名者集合中的其他成员可能并不知道自己被包含在最终的签名中。环签名在保护匿名性方面有很多的用途。

数字签名算法自身的安全性由数学问题进行保障,但在使用上,系统的安全性也十分关键。目前常见的数字签名算法往往需要选取合适的随机数作为配置参数,配置参数不合理的使用或泄露都会造成安全漏洞,需要进行安全保护。


附4:哈希(hash)算法梳理

Hash,一般翻译做散列,也有直接音译为哈希,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。


数学表述为:h = H(M) ,其中H()–单向散列函数,M–任意长度明文,h–固定长度散列值。

在信息安全领域中应用的Hash算法,还需要满足其他关键特性:

单向性(one-way),从预映射,能够简单迅速的得到散列值,而在计算上不可能构造一个预映射,使其散列结果等于某个特定的散列值,即构造相应的M=H-1(h)不可行。这样,散列值就能在统计上唯一的表征输入值,因此,密码学上的 Hash 又被称为”消息摘要(message digest)”,就是要求能方便的将”消息”进行”摘要”,但在”摘要”中无法得到比”摘要”本身更多的关于”消息”的信息。

抗冲突性(collision-resistant),即在统计上无法产生2个散列值相同的预映射。给定M,计算上无法找到M’,满足H(M)=H(M’) ,此谓弱抗冲突性;计算上也难以寻找一对任意的M和M’,使满足H(M)=H(M’) ,此谓强抗冲突性。要求”强抗冲突性”主要是为了防范所谓”生日攻击(birthday attack)”,在一个10人的团体中,你能找到和你生日相同的人的概率是4%,而在同一团体中,有2人生日相同的概率是7%。类似的,当预映射的空间很大的情况下,算法必须有足够的强度来保证不能轻易找到”相同生日”的人。

映射分布均匀性和差分分布均匀性,散列结果中,为 0 的 bit 和为 1 的 bit,其总数应该大致相等;输入中一个 bit 的变化,散列结果中将有一半以上的 bit 改变,这又叫做”雪崩效应(avalanche effect)”;要实现使散列结果中出现 1bit 的变化,则输入中至少有一半以上的 bit 必须发生变化。其实质是必须使输入中每一个 bit 的信息,尽量均匀的反映到输出的每一个 bit 上去;输出中的每一个 bit,都是输入中尽可能多 bit 的信息一起作用的结果。

Damgard 和 Merkle 定义了所谓“压缩函数(compression function)”,就是将一个固定长度输入,变换成较短的固定长度的输出,这对密码学实践上 Hash 函数的设计产生了很大的影响。Hash函数就是被设计为基于通过特定压缩函数的不断重复“压缩”输入的分组和前一次压缩处理的结果的过程,直到整个消息都被压缩完毕,最后的输出作为整个消息的散列值。尽管还缺乏严格的证明,但绝大多数业界的研究者都同意,如果压缩函数是安全的,那么以上述形式散列任意长度的消息也将是安全的。

哈希(Hash)和加密(Encrypt)的区别

概括来说,哈希(Hash)是将目标文本转换成具有相同长度的、不可逆的杂凑字符串(或叫做消息摘要),而加密(Encrypt)是将目标文本转换成具有不同长度的、可逆的密文。

从数学角度讲,哈希和加密都是一个映射。下面正式定义两者:
一个哈希算法$R=H(S)$是一个多对一映射,给定目标文本S,H可以将其唯一映射为R,并且对于所有S,R具有相同的长度。由于是多对一映射,所以H不存在逆映射$S=H^{-1}(R)$使得R转换为唯一的S。

一个加密算法$R=E(S,K_E)$是一个一一映射,其中第二个参数叫做加密密钥,E可以将给定的明文S结合加密密钥$K_E$唯一映射为密文R,并且存在另一个一一映射$S=D(R,K_D)$,可以结合$K_D$将密文R唯一映射为对应明文S,其中$K_D$叫做解密密钥。

下图是哈希和加密过程的图示:


Hash函数的应用

错误校正

使用一个散列函数可以很直观的检测出数据在传输时发生的错误。在数据的发送方,对将要发送的数据应用散列函数,并将计算的结果同原始数据一同发送。在数据的接收方,同样的散列函数被再一次应用到接收到的数据上,如果两次散列函数计算出来的结果不一致,那么就说明数据在传输的过程中某些地方有错误了。这就叫做冗余校验。

语音识别

对于像从一个已知列表中匹配一个MP3文件这样的应用,一种可能的方案是使用传统的散列函数——例如MD5,但是这种方案会对时间平移、CD读取错误、不同的音频压缩算法或者音量调整的实现机制等情况非常敏感。使用一些类似于MD5的方法有利于迅速找到那些严格相同(从音频文件的二进制数据来看)的音频文件,但是要找到全部相同(从音频文件的内容来看)的音频文件就需要使用其他更高级的算法了。


信息安全

Hash算法在信息安全方面的应用主要体现在以下的3个方面:

文件校验
我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。MD5 Hash算法的”数字指纹”特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法。

数字签名
Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。对 Hash 值,又称”数字摘要”进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。

鉴权协议
鉴权协议又被称作挑战–认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。


常见Hash函数介绍

MD5 和 SHA1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。在附1中有介绍。

MD4(RFC 1320)是 MIT 的Ronald L. Rivest在 1990 年设计的,MD 是 Message Digest(消息摘要) 的缩写。它适用在32位字长的处理器上用高速软件实现——它是基于 32位操作数的位操作来实现的。
MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。
SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。


现代化的Hash算法

Jenkins Hash

1997年Bob Jenkins在《 Dr. Dobbs Journal》杂志上发表了一片关于散列函数的文章《A hash function for hash Table lookup》,这篇文章自从发表以后现在网上有更多的扩展内容。这篇文章中,Bob广泛收录了很多已有的散列函数,这其中也包括了他自己所谓的“lookup2”。随后在2006年,Bob发布了lookup3,由于它即快速(Bob自称,0.5 bytes/cycle)又无严重缺陷,被广泛使用。lookup3即为Jenkins Hash。更多有关Bob's散列函数的内容请参阅维基百科:Jenkins hash function。memcached的hash算法,支持两种算法:jenkins, murmur3,默认是jenkins。

MurmurHash

Austin Appleby在2008年发布了一个新的散列函数:MurmurHash。其最新版本大约是lookup3速度的2倍(大约为1 byte/cycle),它有32位和64位两个版本。32位版本只使用32位数学函数并给出一个32位的哈希值,而64位版本使用了64位的数学函数,并给出64位哈希值。根据Austin的分析,MurmurHash具有优异的性能,虽然Bob Jenkins 在《Dr. Dobbs article》杂志上声称“我预测MurmurHash比起lookup3要弱,但是我不知道具体值,因为我还没测试过它”。MurmurHash能够迅速走红得益于其出色的速度和统计特性。当前的版本是MurmurHash3,Redis、Memcached、Cassandra、HBase、Lucene都在使用它。

CityHash

CityHash是2011年Google发布的字符串散列算法,和murmurhash一样,属于非加密型hash算法。CityHash算法的开发是受到了MurmurHash的启发。其主要优点是大部分步骤包含了至少两步独立的数学运算。现代 CPU 通常能从这种代码获得最佳性能。CityHash 也有其缺点:代码较同类流行算法复杂。Google 希望为速度而不是为了简单而优化,因此没有照顾较短输入的特例。Google发布的有两种算法:cityhash64 与 cityhash128。它们分别根据字串计算 64 和 128 位的散列值。这些算法不适用于加密,但适合用在散列表等处。CityHash的速度取决于CRC32 指令,目前为SSE 4.2(Intel Nehalem及以后版本)。

SpookyHash

2011年Bob Jenkins发布了他自己的一个新散列函数SpookyHash(这样命名是因为它是在万圣节发布的)。它们都拥有2倍于MurmurHash的速度,但他们都只使用了64位数学函数而没有32位版本,SpookyHash给出128位输出。

FramHash

2014年Google发布了FarmHash,一个新的用于字符串的哈希函数系列。FarmHash从CityHash继承了许多技巧和技术,是它的后继。FarmHash有多个目标,声称从多个方面改进了CityHash。与CityHash相比,FarmHash的另一项改进是在多个特定于平台的实现之上提供了一个接口。这样,当开发人员只是想要一个用于哈希表的、快速健壮的哈希函数,而不需要在每个平台上都一样时,FarmHash也能满足要求。目前,FarmHash只包含在32、64和128位平台上用于字节数组的哈希函数。未来开发计划包含了对整数、元组和其它数据的支持。

其他Hash算法
XXHash
SuperFastHash

该选用哪个Hash函数

当然,发布时间更晚的,功能方面可能更优,但是也有可能存在某种限制。如果是32位的机器,建议使用MurmurHash,要比lookup3的32位更快些。



本文总结自:互联网