Hash算法及Hash冲突的解决方式详解

709 阅读4分钟

什么是hash?

Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

Hash算法可以将一个数据转换为一个标志,这个标志和源数据的每一个字节都有十分紧密的关系。Hash算法还具有一个特点,就是很难找到逆向规律。

Hash算法是一个广义的算法,也可以认为是一种思想,使用Hash算法可以提高存储空间的利用率,可以提高数据的查询效率,也可以做数字签名来保障数据传递的安全性。所以Hash算法被广泛地应用在互联网应用中。

Hash算法有哪些?

哈希算法的方式很多,典型的哈希算法包括:MD4、MD5 和安全哈希算法(SHA-1)等。

MD4算法

MD4算法是哈希算法中较为成熟的算法之一,它一般使用在32位的计算机处理器模块内,通过软件系统来实现其算法功能。然而,由于MD4算法本身存在的安全性漏洞,还是被更为先进安全的算法所淘汰。但MD4算法为之后的MD5算法、SHA-1算法、ripemd算法等提供了很好的理论基础。

image.png

MD5算法

MD5算法是MD4算法的升级版,它在MD4算法的基础上增加了safety-belts功能,使整个算法变得更加可靠。MD5算法在MD4算法的基础上加入了第四轮的计算模式,每一个步骤都是一一对应的固定值,改进了MD4算法中在第二轮、第三轮计算中的漏洞,完善了访问输入分组的次序,从而减小其对称性和相同性。通过这些变化,使得MD5与MD4相比变得复杂很多,整个运转速度也要比MD4慢一些,但是从整体安全性、抗冲突和抗分析方面有了很大的提高。

SHA-1算法

SHA-1算法也叫做安全哈希算法,主要应用于digital signature standard dss里面定义的数字签名算法。SHA-1算法长度一般为160bit的message digest,SHA-1算法在接收消息摘要的过程中,可以利用message digest来检查数据的完整情况。它不会从message digest中还原相关的内容,此外两个不同的message digest不会产生相同的message digest,因此SHA-1算法具有很强的brute-force性能。SHA-1算法的计算方式是基于MD4的算法原理,它的填补和分组模式与MD5是一样的,但是在算法中,SHA-1的非线性函数、循环左移运算和加法常数与MD5算法的运算方式有一定的差异,SHA-1的安全性和稳定性比MD5算法更加可靠,且运算速度也有了一定的提高。

什么是Hash冲突?

我们已经知道Hash属于压缩映射,一定能会产生多个实际值映射为一个Hash值的情况,这就产生了冲突。

如何解决Hash冲突?

开放定址法:

基本思想是,出现冲突后按照一定算法查找一个空位置存放,根据算法的不同又可以分为线性探测再散列、二次探测再散列、伪随机探测再散列。

线性探测再散列即依次向后查找;

二次探测再散列,即依次向前后查找,增量为1、2、3的二次方;

伪随机,顾名思义就是随机产生一个增量位移。

java中的ThreadLocal里用的则是线性探测再散列。

链地址法:

这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。Java里的HashMap用的就是链地址法,为了避免hash 洪水攻击,1.8版本开始还引入了红黑树。

再哈希法:

这种方法是同时构造多个不同的哈希函数:Hi=RH1(key) i=1,2,…,k当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。

建立公共溢出区

这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。