一、MD5 是什么

MD5 英文全称 Message-Digest Algorithm 5,翻译成中文是 消息摘要算法第五版,为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。

MD5 算法具有以下特点:

  • 压缩性:任意长度的数据,算出的 MD5 值长度都是固定的(128 bit)。
  • 易计算:从原数据计算出 MD5 值很容易。
  • 抗修改:对原数据进行任何改动,哪怕只修改 1 个字节,所得到的 MD5 值都有很大区别。
  • 抗碰撞:已知原数据和其 MD5 值,想找到一个具有相同 MD5 值的数据(即伪造数据)是非常困难的(极小碰撞概率)。


二、使用 MD5 存储密码

MD5 的用处太多了,数据完整性校验、数字签名、文件完整性检查、密码保存等等,这里以一个密码保存来简单描述一下。

2.1 无盐的 MD5

大型网站需要保存千千万万用户的密码,如果密码使用明文保存,万一哪天数据库被黑客攻破了,用户的密码就全泄露了。

如果数据库只保存用户密码的 MD5 消息摘要,那么即使黑客拿到了用户们的 MD5 消息摘要,也无法复原出用户的密码。

有同学会抗议,这个说法不对!黑客可以使用彩虹表将用户密码复原出,网站常用的密码一般也就 6~10 位,这个取值空间还是很好破解的。没错,但是我们可以通过加盐提高破解的难度。

2.2 加盐的 MD5

我们知道,如果直接对密码进行散列,那么黑客可以对通过获得这个密码散列值,然后通过查散列值字典(例如 MD5 密码破解网站),得到某用户的密码。

加盐可以一定程度上解决这一问题。当用户首次提供密码时(通常是注册时),由系统自动对这个密码追加盐,然后再散列。而当用户登录时,系统为用户提供的密码追加同样的盐,然后散列,再比较散列值,已确定密码是否正确。

这个盐值是由系统随机生成的,并且只有系统知道。这样,即便两个用户使用了同一个密码,由于系统为它们生成的盐值不同,他们的散列值也是不同的。即便黑客可以通过自己的密码和自己生成的散列值来找具有特定密码的用户,但这个几率太小了(密码和盐值都得和黑客使用的一样才行)。


那是不是加了盐值之后就绝对安全了呢?当然没有!黑客还是可以根据他们数据字典中的密码,加上我们泄露数据库中的盐值,然后散列,然后再匹配。但是由于我们的盐值是随机产生的,假如我们的用户数据表中有 30w 条数据,数据字典中有 600w 条数据,黑客如果想要完全覆盖的话,他们加上盐值后再散列的数据字典数据量就应该是 30w * 600w = 180000000w,一万八千亿啊,干坏事的成本太高了吧。但是如果只是想破解某个用户的密码的话,只需为这 600w 条数据加上盐值,然后散列匹配。可见加盐虽然大大提高了安全系数,但也并非绝对安全。

实际项目中,盐值不一定要加在最前面或最后面,也可以插在中间,也可以分开插入,也可以倒序,程序设计时可以灵活调整,都可以使破解的难度指数级增长。

三、彩虹表是什么

聊完 MD5,咱们再聊聊彩虹表。

彩虹表不是 “明文 ⇨ 密码” 的简单存储。要从 c = hash(m) 逆向得到原始明文 m,有三种办法:

  • 暴力破解法:时间成本太高。
  • 字典法:提前构建一个 “明文 ⇨ 密文” 对应关系的一个大型数据库,破解时通过密文直接反查明文。但存储一个这样的数据库,空间成本是惊人的。
  • 构建彩虹表:在字典法的基础上改进,以时间换空间。是现在破解哈希函数常用的办法。

3.1 彩虹表的前身

既然存储所有的明文密码对需要的空间太大,密码学家们想出了一种以计算时间降低存储空间的办法,被称为 “预计算的哈希链集”

假设这是一条 k = 2 的哈希链:


其中 H 函数 就是要破解的哈希函数。

约简函数(reduction function)R 函数 是构建这条链的时候定义的一个函数:它的值域和定义域与 H 函数相反。通过该函数可以将哈希值约简为一个与原文相同格式的值。

这条链是这样生成的:

存储的时候,不需要存储所有的节点,只需要存储每条链的头尾节点(这里是 aaa 和ccc)。

以大量的随机明文作为起节点,通过上述步骤计算出哈希链并将终节点进行储存,可得到一张哈希链集。

预计算的哈希链集的使用

假设密文刚好是 4D5E6F ,首先对其进行一次 R 运算,得到 ccc,然后发现刚好命中了哈希链集中的(aaa, ccc)链条。可以确定其极大概率在这个链条中。于是从 aaa 开始重复哈希链的计算过程,发现 bbb 的哈希结果刚好是 4D5E6F,于是破解成功。

假设密文不是 4D5E6F 而是 1A2B3C ,第一次 R 运算后的结果并未在末节点中找到,则再重复一次 H 运算 + R 运算,这时又得到了末节点中的值 ccc。于是再从头开始运算,可知 aaa 的哈希结果刚好是 1A2B3C,破解成功。

如过密文重复了 k(=2)次之后,仍然没有在末节点中找到对应的值,则破解失败。

预计算的哈希链集的意义

对于一个长度为 k 的预计算的哈希链集,每次破解计算次数不超过 k,因此比暴力破解大大节约时间。同时每条链只保存起节点和末节点,储存空间只需约 1 / k,因而大大节约了空间。

R 函数存在的问题

要发挥预计算的哈希链集的作用,需要一个分布均匀的 R 函数。当出现碰撞时,就会出现下面这种情况


由于两条链出现了重复。这两条哈希链能解密的明文数量就远小于理论上的明文数(2 * k)。由于集合只保存链条的首末节点,因此这样的重复链条并不能被迅速地发现。

3.2 彩虹表

彩虹表的出现,针对性的解决了 R 函数导致的链重复问题:它在各步的运算中,并不使用统一的 R 函数,而是分别使用 R1…Rk 一共 k 个不同的 R 函数。

这样一来,即使发生碰撞,通常会是下面的情况:

即使在极端情况下,两个链条在同一序列位置上发生碰撞,导致后续链条完全一致,这样的链条也会因为末节点相同而检测出来,可以丢弃其中一条而不浪费存储空间。

彩虹表的使用

首先,假设要破解的密文位于某一链条的 k - 1 位置处,对其进行 Rk 运算,看是否能够在末节点中找到对应的值。如果找到,则可以如前所述,使用起节点验证其正确性。

否则,继续假设密文位于 k - 2 位置处,这时就需要进行 Rk - 1、H、Rk 两步运算,然后在末节点中查找结果。

如此反复,在最不利条件下需要将密文进行完整的 R1、H、…Rk 运算后,才能得知密文是否存在于彩虹表之中。

彩虹表中时间、空间的平衡

哈希链集的最大计算次数为 k,平均计算次数为 k / 2;彩虹表的最大计算次数为 1 + 2 + …k = k(k - 1) / 2,平均计算次数为 [(k + 2) * (k + 1)] / 6。

可见,要解相同个数的明文,彩虹表的代价会高于哈希链集。

无论哈希链集还是彩虹表,当 k 越大时,破解时间就越长,但彩虹表所占用的空间就越小;相反,当 k 越小时,彩虹表本身就越大,相应的破解时间就越短。

3.3 为什么加盐哈希可以抵御彩虹表

彩虹表在生成的过程中,针对的是特定的 H 函数,H 函数如果发生了改变,则已有的彩虹表数据就完全无法使用。

如果每个用户都用一个不同的盐值,那么每个用户的 H 函数都不同,则必须要为每个用户都生成一个不同的彩虹表。大大提高了破解难度。

总结:奇妙的比喻

最后以一个奇妙的比喻来总结该文章:

如果将 MD5 哈希后的密文比作一把锁,暴力破解的方法就是现场制作各种各样不同齿形的钥匙,再来尝试能否开锁,这样耗时无疑很长很长。。。

我以前错误理解的 “彩虹表”,是事先制作好所有齿形的钥匙,全部拿过来尝试开锁,这样虽然省去了制作钥匙的时间,但是后来发现这些钥匙实在是太多了,没法全部带在身上。

而真正的彩虹表,是将钥匙按照某种规律进行分组,每组钥匙中只需要带最有特点的一个,当发现某个 “特征钥匙” 差一点就能开锁了,则当场对该钥匙进行简单的打磨,直到能开锁为止。这种方法是既省力又省时的。

写在最后:

扫描下方二维码或关注微信公众号:CodeFish 回复关键字 “电子书” 即可获取本文章相关书籍资料!

更多优质电子书资源持续更新中…

深入理解 MD5 加密、彩虹表算法原理相关推荐

  1. 为什么MD5不可逆, 彩虹表是怎么攻击的

    为什么MD5是不可逆的? 先说大白话版本的,因为MD5算法里面有很多不可逆的运算.比如移位,假设:10010001 左移两位后是:01000100,你有什么办法把它移回来吗?移出去的已经找不回了哦. ...

  2. C语言正余弦函数定点查表算法原理及实现

    如果用数学库中的sin和cos函数计算,可能涉及浮点.乘法.除法运算,运行速率较低.这里介绍一种正余弦查表算法. 参考代码:SMT32 FOC电机库的mc_math.c. 首先我们知道正弦和余弦的函数 ...

  3. java加盐_Java中MD5加密加盐算法

    前俩天项目组需要做一个密码的加密加盐操作,无意中在网上看到一个对应的加密加盐算法,特意在此做一个记录 import java.security.MessageDigest; import java.u ...

  4. 除留余数法构造哈希表_哈希表算法原理

    基本概念 哈希表(Hash Table)是一种根据关键字直接访问内存存储位置的数据结构.通过哈希表,数据元素的存放位置和数据元素的关键字之间建立起某种对应关系,建立这种对应关系的函数称为哈希函数. 哈 ...

  5. 彩虹表破解开机密码、MD5算法等的原理

    http://www.91ri.org/7593.html  自己发到91ri的,博客备份下. 前言 或许对于大多数人来说,实际中并不需要了解这些理论,能够使用现成的工具就行,但是我个人觉得了解了这些 ...

  6. 彩虹表原理及其算法的思考

    最近在网上看到使用RainbowCrack破解Windows密码的一篇文章,读后深感彩虹表的设计思路十分有趣,此篇博文用以总结彩虹表的工作原理以及个人的一些思考. 参考资料: 彩虹表 - 维基百科 M ...

  7. 彻底搞懂彩虹表的实现原理

    为什么要写这篇文章 鉴于今天摸索了一上午,终于搞清楚了彩虹表的实现原理,特此记录,以备后查. 什么是彩虹表 7788的术语我就不多说了,简而言之,就是一种破解md5或者sha1这种哈希散列算法的一种办 ...

  8. 11 种加密 哈希算法的原理及其 Java 实现

    11 种加密 & 哈希算法的原理及其 Java 实现 一.目的 二.运行环境 三.基本原理及步骤 (I)各种加密算法的原理: ① DES 数据加密标准(Data Encryption Stan ...

  9. MD5 加密安全吗?

    MD5 加密安全吗? MD5 是 Message Digest Algorithm 的缩写,译为信息摘要算法,它是 Java 语言中使用很广泛的一种加密算法.MD5 可以将任意字符串,通过不可逆的字符 ...

最新文章

  1. python3 赋值 浅拷贝 深拷贝 简介
  2. java中Error与Exception有什么区别
  3. html如何与py_Web项目如何做单元测试?
  4. 常见网络命令整理(ping、trcert、netstat)
  5. [机器学习]-K近邻-最简单的入门实战例子
  6. 类火墙的iptables
  7. 《算法图解》——数组和链表
  8. Script to show Active Distributed Transactions
  9. 【WC2013】糖果公园
  10. Vue+Mui商城项目使用说明(首页仿淘宝)
  11. 飞信WEB接口的一个返回网页C#处理源码
  12. QoS(服务质量)指标
  13. 牛客网暑期ACM多校训练营(第六场) C.Generation I (思维+逆元+组合数学)
  14. win10切换输入法快捷键_怎么给电脑win10添加其他语言输入?例:日语,俄语
  15. 赠与今年的大学毕业生,胡适
  16. 基于Joplin+PicGo+阿里OSS搭建自己的云笔记
  17. JZOJ5462. 【NOIP2017提高A组冲刺11.8】好文章
  18. Struts2框架之Action详解
  19. js实现将svg下载成png
  20. 2019-05-19 Jave学习日记之Object类型

热门文章

  1. Tomcat各目录作用
  2. 荒野行动PC版出现launcher.exe问题
  3. C语言中if和switch语句的基本用法
  4. 转 PR2018中如何调整音频的大小及缓入缓出效果
  5. shell181网格划分_ANSYS中Shell181单元介绍谁知道
  6. php openssl.capath,php - openssl_pkey_get_public返回false,但是密钥确实存在 - 堆栈内存溢出...
  7. linux 文本编辑工具vim
  8. 【Vue源码解析】Vue虚拟dom和diff算法
  9. java构造器是什么?
  10. Android 通过AccessibilityService实现微信聊天记录导出