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
posted on 2013-11-27 11:56 PEIYANGXINQU 阅读(1074) 评论(1) 编辑 收藏 举报