MD5加密和彩虹表
首先叙述一下彩虹表的原理。本部分内容、图片和例子基本来自英文维基的Rainbow table词条(Rainbow table)——中文维基中目前(2013年10月9日)尚无对应的词条——因此对本答案中这部分的转载请遵循维基的版权协议。
彩虹表的核心在于预先计算好的哈希链(Precomputed hash chains)。
当面对要破解的哈希函数H,首先要定义一个简化函数(reduction function)R,该函数的定义域和值域应该是和哈希函数相反的,通过该函数可以将哈希值约简为一个与原文相同格式的值("plain text" value)。需要强调的是,由于哈希函数H是不可逆的,所以对于密文进行R运算几乎不可能得到明文原文。例如,六位字母明文“aaaaaa”进行H运算后得到了“281DAF40”,而对“281DAF40”进行R运算后得到另一个六位字母格式的值“sgfnyd”。因为这个值落在H的定义域中,因此可以对它继续进行H运算。
就这样,将H运算、R运算、H运算……这个过程反复地重复下去,重复一个特定的次数k以后,就得到一条哈希链,例如:
这条链条并不需要完整地保存下来,只需要保存其起节点和末节点即可,例如上例中只需要保存起节点“aaaaaa”和末节点“kiebgt”。以大量的随机明文作为起节点,通过上述步骤计算出哈希链并将终节点进行储存,即可得到一张彩虹表。
这张彩虹表需要如何使用呢?例如,我们知道哈希运算后的密文为“920ECF10”,则先对其进行一次R运算,得到“kiebgt”。
正巧在本例中,它等于彩虹表中的一个末节点,因此我们可以猜测,明文有极大的可能存在于以起节点“aaaaaa”开头、末节点“kiebgt”结尾的这条哈希链中。(注意可能性并不是100%,因为函数H和R均有可能发生碰撞,从不同的输入值得到相同的输出值。)
为了验证我们的猜测,可以从起节点“aaaaaa”开始重复哈希链的计算过程:
算到这里我们发现,“sgfnyd”进行哈希运算的结果正是密文“920ECF10”,这样就找到了所需的明文。
如果不幸,第一次R运算后并未在彩虹表中找到对应的末节点,则需要继续重复H运算、R运算这样的步骤。可以发现,最多重复k次,我们即可断定,所需的明文在这张彩虹表中——已经找到了对应的末节点,并从起节点算出了明文;或是所需的明文不在这张彩虹表中——表中并未储存长度大于k的哈希链,因此再计算也没有意义了。
如果让我来解释哈希链的意义,我认为,每一条哈希链实际上是代表了属性相同的一组明文:每一个明文都可以通过起节点迅速的计算得出,计算次数不大于k,因而可以大大节约时间。对每一组明文,只需要保存其特征值(起节点和末节点),储存空间只需约1/k,因而大大节约了空间。
可以看出,当k越大时,破解一个哈希值的期望时间就越长,但彩虹表所占用的空间就越小;相反,k越小时,彩虹表本身就越大,相应的破解时间就越短。这正是保持空间、时间二者平衡的精髓所在。RainbowCrack中rtgen工具使用的默认k值好像是2100。极端的,令k=1,简化函数R(x)=x,这样的彩虹表就变成了通常的错误理解,即将明文、密文对应关系全部保存的表。此时由于k极小,因而得到的表的体积极大,甚至可能超出储存能力。(当然,对于范围较小的明文,如6位以下数字英文的组合,或是全世界常用密码的集合,生成k=1的表还是不费什么事的。)
在构造哈希链的时候,一个优秀的函数R功不可没。首先R需要能将值域限定在固定的范围——例如给定的长度范围、给定的字符取值范围等等——之内,否则的话,哈希链中大量的计算结果并不在可接受的取值范围内,一条链条无法对应多个明文,链条就失去了意义;其次R必须同哈希函数一样,尽量保证输出值在值域中的均匀分布,减少碰撞的概率。否则,多条哈希链碰撞得到同样的末节点,或是大量的明文无法在哈希链中出现,都会降低最终生成的彩虹表的价值。我没有继续深入研究已有的彩虹表工具中R的算法,但可以肯定这是彩虹表原理中的精髓所在。
多说一些,关于彩虹表的防御方式,其实都是与彩虹表的原理,即其生成步骤中用到的函数H有关。
最常用的方法,在其它的答案中也提到了,那就是加盐(salt),这其实是改变了哈希函数H的形式。由于彩虹表在生成和破解的过程中,都反复用到了函数H,H如果发生了改变,则已有的彩虹表数据就完全无法使用,必须针对特定的H重新生成,这样就提高了破解的难度。
防御彩虹表的另一种方法是提高H函数的计算难度,例如将H定义为计算1k次MD5后的结果。由于H在算法中的重复性,当单次H函数的计算耗时增加,意味着彩虹表的生成时间会大大的增加,从而也能提高破解的成本。
===========简化比喻的分隔线==============
如果将哈希后的密文比作一把锁,暴力破解的方法就是现场制作各种各样不同齿形的钥匙,再来尝试能否开锁,这样耗时无疑很长;我以前错误理解的“彩虹表”,是事先制作好所有齿形的钥匙,全部拿过来尝试开锁,这样虽然省去了制作钥匙的时间,但是后来发现这些钥匙实在是太多了,没法全部带在身上。而真正的彩虹表,是将钥匙按照某种规律进行分组,每组钥匙中只需要带最有特点的一个,当发现某个“特征钥匙”差一点就能开锁了,则当场对该钥匙进行简单的打磨,直到能开锁为止。这种方法是既省力又省时的。
网站密码加密原理(初级)http://blog.csdn.net/ubuntu64fan/article/details/7096642
http://www.cnblogs.com/luminji/archive/2011/05/24/2055021.html
MD5加密和彩虹表的更多相关文章
- 一种简单的md5加盐加密的方法(防止彩虹表撞库)
md5加密(或者说摘要算法)大家都很熟悉了 就不解释了 现在很多数据库设计都喜欢用单向加密的方式保存密码,验证时对提交的密码再次加密之后做密文对比 /// <summary> 使用MD5加 ...
- MD5加密算法中的加盐值 ,和彩虹表攻击 防止彩虹表撞库
一.什么是彩虹表? 彩虹表(Rainbow Tables)就是一个庞大的.针对各种可能的字母组合预先计算好的哈希值的集合,不一定是针对MD5算法的,各种算法的都有,有了它可以快速的破解各类密码.越是复 ...
- MD5小彩虹表
为方便日常查询,需要一个MD5小彩虹表,当然网上有比较多的这样的查询站点,但感觉最近使用起来十分不便. 因此,编写一个小程序,用来查询一些经常出现的MD5,也即弱口令MD5查询.采用python3编写 ...
- 使用crypto模块实现md5加密功能(解决中文加密前后端不一致的问题)
正常情况下使用md5加密 var crypto = require('crypto'); var md5Sign = function (data) { var md5 = crypto.create ...
- 驰骋工作流引擎-流程数据md5加密
关键字:工作流程数据加密 md5 数据保密流程数据防篡改软加密设置方式: 对工作流引擎的数据加密研究, 流程数据的加密方案与实现过程.输入图片说明需求背景1, 流程数据加密是为了防止流程数据被篡改 ...
- 【web安全】-- springboot实现两次MD5加密
一.为什么要做两次MD5 客户端MD5:HTTP在网络上是使用明文传输,用户输入的明文密码直接在网络上传输太危险.所以,在客户端先进行一次MD5(明文+固定盐). 服务端:服务端接受到后,也不是直接写 ...
- python之MD5加密
一. MD5加密import hashlib #Python3里的引用#import md5 #Python2里的引用 1. md5是不可逆的,不能解密2. 所有语言生成的md5串都是一样的 3. 不 ...
- MD5加密+加盐
了解: MD5加密,是属于不可逆的.我们知道正常使用MD5加密技术,同一字符,加密后的16进制数是不变的,自从出现彩虹表,对于公司内部员工来说,可以反查数据,获取不可能的权限,所以出现了salt算法. ...
- rainbow table 彩虹表
RainbowTable 的使用和性能的小测试 - SV的边界 - CSDN博客 https://blog.csdn.net/cecilulysess/article/details/4804707 ...
随机推荐
- Java - 28 Java 泛型
Java 泛型 如果我们只写一个排序方法,就能够对整型数组.字符串数组甚至支持排序的任何类型的数组进行排序,这该多好啊. Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类 ...
- Android 6.0动态申请权限时,权限框闪一下就消失的问题;
Android 蓝牙BLE开发需要位置权限,不然扫描不到周围的蓝牙信息: 位置权限申请: if (Build.VERSION.SDK_INT < 23){return;} //判断是否有权限 i ...
- C# JToken类的使用,实现解析动态json数据、遍历、查找
在原来解析json数据是,一般都是用反序列化来实现json数据的解读,这需要首先知道json数据的结构并且建立相应的类才能反序列化,一旦遇到动态的json数据,这种方法就不使用. 为了解决动态解析js ...
- 使用原子类或synchronized(没用Lock)解决阐述多线程所遇到线程安全问题和解决方案
例子题目: 创建10个线程,每个线程执行10000次加1,输出总和 正常结果100000 但是如果出现线程不安全会低于100000 import java.util.concurrent.Count ...
- linux之 redis 的rdb 转 aof 及主从复
redis持久化RDB基于快照的持久化通过save命令,强制持久化 在redis.conf中dbfilename dbmp.rdbsave 900 1save 300 10save 60 10 ...
- 错误为Lc.exe已退出,代码为-1
近来在做项目的时候,突然遇到 了 LC.exe 已退出,代码为-1 的提示,怎么也编译不了,在查了相关的资料后,终于明白了原因,其解决方案如下 : 1. 以管理员的身份来运行vs, 并把项目中“pro ...
- JVM总结-垃圾回收
Java 虚拟机的自动内存管理,将原本需要由开发人员手动回收的内存,交给垃圾回收器来自动回收.不过既然是自动机制,肯定没法做到像手动回收那般精准高效 [1] ,而且还会带来不少与垃圾回收实现相关的问题 ...
- 【Jmeter自学】常见错误类型(九)
==================================================================================================== ...
- oracle 表或视图不存在
导入导出时,会自动表名自动加上了““双引号需要将表名改一下就可以了 alter table "oldtablename" rename to newtableName;
- 学习笔记:vue(代码篇)
http://cn.vuejs.org/ VUE官网 http://cn.vuejs.org/v2/guide/ 教程 VUE模板文件: <html lang="zh-cn" ...