通俗的理解哈希函数
哈希函数又称散列函数,它可以把一个不定长的数据经过一系列的运算后,获取一个定长字符串。哈希函数在现代计算机中有着广泛的应用。
什么是哈希函数
哈希函数是一种从任何一种数据中创建小的数字“指纹”的方法,就像我们人类的指纹一样,无论这个人是高矮胖瘦,都有着一枚小小的指纹可以代表它。值得注意的是,哈希函数不是指某一个具体的函数,而是一类函数,这类函数通常具备以下特点:
- 如果函数的输出值不相同,那么它们的输入值也一定不相同;
- 不具备可逆性,也就是说通过输出值无法反向计算出输入值;
- 不论输入值是长是短,它的输出值是定长的。
我们生活中有一个很鲜明的例子可以通俗的理解哈希函数——微信联系人:

在微信联系人中,不论一个人名字是长是短,总会被微信创建一个指纹:“第一个字的首字母”。比如王二的指纹是W,张三是Z。这个过程被称为“映射”,我们可以说王二映射到W上,张三映射到Z上。而完成这个映射的函数就被称之为哈希函数。

哈希碰撞
因为哈希会将不定长的数据映射成一个定长的字符串,那么冥冥之中就必然会有其他的数据和它哈希结果是一样的。这样的情况被称为哈希碰撞,就比如说在微信联系人中张三的哈希结果是Z,那么郑五、周六的哈希结果也只Z。哈希碰撞是所有哈希函数都极力避免的事情,但哈希函数始终无法完全避免哈希碰撞,因为输入值是不确定长的,而输出值是有一个具体定长的值,这就使得输入值和输入值的数量不对等,无法一一映射,所以,必然会有不同的值产生哈希碰撞。
哈希应用
保护资料
哈希值可用于唯一地识别机密信息,比如我们编程中经常会对原始密码进行 MD5 加密,MD5 就是一种哈希函数,MD5 加密后的密文再保存到数据库中。由于哈希函数具备不可逆的特性,这样就可以防止明文密码被泄露。但是由于哈希碰撞的存在,所以一般会在原始密码撒盐后再加密。
确保传递真实的信息
消息或数据的接受者确认消息是否被篡改的性质叫数据的真实性,也称为完整性。发信人通过将原消息和原消息的哈希值一起发送,接收者在接收到消息后,调用同样的哈希函数操作原消息,将得到的哈希值与接收到的哈希值进行比对,用于确认消息的完整性。但是,恶意攻击可能会将原消息带着哈希值一起篡改,所以,利用单纯的哈希确保消息的真实性还是有漏洞的。解决这个漏洞还得用对称加密,关于对称加密,这里不在赘述,有兴趣可以移步别处。
哈希表
哈希表也被称为散列表,是哈希的一个非常重要的应用。使用哈希表能够快速的按照关键字查找数据记录。例如,在英语字典中的关键字是英文单词,和它们相关的记录包含这些单词的定义。上文举例的微信联系人就很类似哈希表,给联系人编上首字母可以协助我们快速找到某一个人。
目前常见的散列算法
| 算法名称 | 输出大小(bits) | 内部大小 | 区块大小 | 长度大小 | 字符尺寸 | 碰撞情形 |
| HAVAL | 256/224/192/160/128 | 256 | 1024 | 64 | 32 | 是 |
| MD2 | 128 | 384 | 128 | No | 8 | 大多数 |
| MD4 | 128 | 128 | 512 | 64 | 32 | 是 |
| MD5 | 128 | 128 | 512 | 64 | 32 | 是 |
| PANAMA | 256 | 8736 | 256 | 否 | 32 | 是 |
| RadioGatún | 任意长度 | 58字 | 3字 | 否 | 1-64 | 否 |
| RIPEMD | 128 | 128 | 512 | 64 | 32 | 是 |
| RIPEMD-128/256 | 128/256 | 128/256 | 512 | 64 | 32 | 否 |
| RIPEMD-160/320 | 160/320 | 160/320 | 512 | 64 | 32 | 否 |
| SHA-0 | 160 | 160 | 512 | 64 | 32 | 是 |
| SHA-1 | 160 | 160 | 512 | 64 | 32 | 有缺陷 |
| SHA-256/224 | 256/224 | 256 | 512 | 64 | 32 | 否 |
| SHA-512/384 | 512/384 | 512 | 1024 | 128 | 64 | 否 |
| Tiger(2)-192/160/128 | 192/160/128 | 192 | 512 | 64 | 64 | 否 |
| WHIRLPOOL | 512 | 512 | 512 | 256 | 8 | 否 |
本文目录