安全防护 — Hash算法与碰撞

1. Hash

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

程序开发中经常使用的MD4、MD5和SHA都是历史悠久的Hash算法。

在上边的这个例子中,“这是一个测试文案”是原始值,“2124968af757ed51e71e6abeacO4f98d” 就是经过hash算法得到的hash值。

整个Hash算法的过程就是把原始任意长度的值空间,映射成固定长度的值空间的过程。


2. Hash 算法用途

Hash算法在信息安全方面的应用:

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

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

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


3. Hash的特点

一个优秀的hash算法,需要什么样的要求呢?

  1. 从hash值不可以反向推导出原始的数据。
  2. 输入数据的微小变化会得到完全不同的hash值,相同的数据会得到相同的值。
  3. 哈希算法的执行效率要高效,长的文本也能快速地计算出哈希值。
  4. hash算法的冲突概率要小。

由于hash的原理是将输入空间的值映射成hash空间内,而hash值的空间远小于输入的空间。根据抽屉原理,一定会存在不同的输入被映射成相同输出的情况。那么作为一个好的hash算法,就需要这种冲突的概率尽可能小。


4. Hash冲突

所谓哈希(hash),就是将不同的输入映射成独一无二的、固定长度的值(又称"哈希值")。如果不同的输入得到了同一个哈希值,就发生了"哈希碰撞"


5. 如何防止哈希碰撞?

防止哈希碰撞的最有效方法,就是扩大哈希值的取值空间。

16个二进制位的哈希值,产生碰撞的可能性是65536分之一。也就是说,如果有65537个用户,就一定会产生碰撞。哈希值的长度扩大到32个二进制位,碰撞的可能性就会下降到4,294,967,296分之一。

更长的哈希值意味着更大的存储空间、更多的计算,将影响性能和成本。开发者必须做出抉择,在安全与成本之间找到平衡。


6. Hash碰撞的解决方案

前面提到了hash算法是一定会有冲突的,那么如果我们如果遇到了hash冲突需要解决的时候应该怎么处理呢? 比较常用的算法是链地址法开放地址法

  • 链地址法

链表地址法是使用一个链表数组,来存储相应数据,当hash遇到冲突的时候依次添加到链表的后面进行处理。

案例:

  • 开放地址法

开放地址法是指大小为M的数组保存N个键值对,其中M>N。我们需要依靠数组中的空位解决碰撞冲突。基于这种策略的所有方法被统称为“开放地址”哈希表。线性探测法,就是比较常用的一种“开放地址”哈希表的一种实现方式。线性探测法的核心思想是当冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。
简单来说就是∶一旦发生冲突,就去寻找下一个空的散列表地址,只要散列表足够大,空的散列地址总能找到。

案例(请自行与上边的链地址法进行比较):


如果觉得有收获就点个赞吧,更多知识,请点击关注查看我的主页信息哦~

你可能感兴趣的:(安全防护 — Hash算法与碰撞)