什么是哈希算法
将任意长度的二进制值串映射为固定长度的二进制值串,这个映射规则就是哈希算法,映射得到的值就叫哈希值。
设计一个优秀的哈希算法,需要注意以下几点:
1:从哈希值不能反向推导出原始数据,所以哈希算法也叫单项哈希算法。
2:对输入数据非常敏感,哪怕原始数据修改了 1 个 Bit,最后得到得哈希值也不一样。
3:散列冲突的概率要小,对于不同的原始数据,得到的哈希值相同的概率要小。
4:哈希算法的执行效率要高,即便是原始数据很长,也能高效的计算出哈希值。
哈希算法应用之安全加密
哈希算法常见的应用就是加密,比如说:MD5 也叫信息摘要算法;SHA 也叫安全散列算法。
对于加密的哈希算法来说,有两点至关重要:很难通过哈希值反向推出原始数据,散列冲突的概率要很小。
为什么散列冲突无法避免?组合数学中有一个鸽巢原理,也叫抽屉原理。也就是说,是一个鸽子放进是个抽屉里面,必然会有两只鸽子待在一个抽屉里面,这是不可避免的结果。对于 MD5 加密算法来说,得到的哈希值是固定的 128 位二进制串,也就是说最多能标识 2^128 个数据。如果现在有 2^128 + 1 个数据,那么最终得到的哈希值至少会有一个重复。
越是复杂的哈希加密算法,最终得到结果越是难以被破解,但是计算哈希值的复杂度也就相应的提高了。所以,哈希函数的设计,要综合考虑破解难易程度和算法执行效率的平衡点。
哈希算法应用之唯一标识
如果要在海量图库中判断一张图片是否存在,仅仅根据图片名字判断是不合理的,重名图片一定很多。
在计算机中,任何文件都可以转化为二进制码串,所以可以拿图片的码串进行对比。但是,文件大小不一,过大的文件,二进制码串必定很长,对比起来肯定耗时费力。
我们可以利用哈希算法为图片生成一个信息摘要作为图片的唯一标示,查找图片的时候可以用信息摘要做对比。信息摘要的生成,可以在图片的前中后三部分分别取出 100 个字节,生成最终的唯一标示。
在上述基础上,我们可以把图片的信息摘要当做 key 值,图片的其他信息作为 value 值,将其存储在散列表中,这就进一步提高了图片查找的效率。
哈希算法应用之数据校验
当我们通过种子文件从互联网上下载视频文件的时候,原始文件(假如说大小为 1G)会被分割成多个文件快(假设分割成 10 块,每块大小约 100M)。当我们将 10 块文件下载到本地的时候,再拼接成一个完整的文件,就可以观看视频了。
如果在下载过程中,文件被拦截篡改,那下载到本地拼接后就不能观看,所以需要我们对数据进行校验。
首先,我们可以对分割的 10 块文件分别哈希取值,然后将哈希值保存在种子文件中。当用户下载完成文件后,哈希取值,再和种子文件中的哈希值做对比,就可以校验出下载的文件是否经过篡改。
哈希算法应用之散列函数
散列函数主要应用在散列表中,它直接决定了散列冲突的概率和散列表的性能。相对于其他哈希算法的应用,散列函数对散列冲突的容忍性就高的多了。即便出现了散列冲突,可以通过开放寻址法以及链表法解决散列冲突。
散列函数同样也不关心是否可以通过哈希值反向推出原始数据。在散列表中,更关心散列函数得到的散列值是否随机均匀分布。当然,散列函数执行的效率也关系着散列表的性能。
补充
在开发过程中,我们会把用户的明文密码哈希求值后存储起来,保障用户的隐私。但是即便如初,一旦数据库数据泄露,密码一样不够安全。
字典攻击:黑客将常用的密码哈希求值后保存在字典数据库中,当黑客得到得到用户信息,即便是加密过的密码,用字典库中的哈希值做对比,从而匹配到用户的密码。
针对字典攻击,我们可以采用加盐(salt)的方式进行加密。在给用户的密码加密的时候,额外对密码追加一个字符串,然后在进行哈希求值,追加的字符串就是盐 (salt)。该盐可以放在密码的首中尾任意位置。
王争老师总结了一句很经典的话:安全和攻击是一种博弈关系,没有绝对的安全。所有的安全措施,只不过是增加了攻击的成本而已。
总结
本文创作灵感来源于 极客时间 王争老师的《数据结构与算法之美》课程,通过课后反思以及借鉴各位学友的发言总结,现整理出自己的知识架构,以便日后温故知新,查漏补缺。
初入算法学习,必是步履蹒跚,一路磕磕绊绊跌跌撞撞。看不懂别慌,也别忙着总结,先读五遍文章先,无他,唯手熟尔~
与诸君共勉