彩虹表 成功率计算

说起彩虹表不得不提到三个人,Martin Hellman(co-author of the Diffie-Hellman key agreement algorithm)、Rivest(the R in RSA)、Philippe Oechslin,以下简称M、R、P。虽然说彩虹表的概念是P提出的,但是前人的贡献也是巨大的

彩虹表是用来破解散列算法的结果并还原散列之前的明文的、预先计算的明文对,而不是明文和散列值对。

hash散列算法:

hash散列算法的功能是将一个值从一个大的集合P映射到一个固定长度的较小集合Q中,大概的过程是将值按照二进制位填充、分组、位运算,最终得到一个固定位数的值,所以每一个值p经过映射都有唯一且确定的一个值q。假设这个散列算法为H,一个合格的散列算法需要满足的条件是

  1. 由p计算q的速度应该很快
  2. 单向性 即根据明文p能够很快计算出一个散列值q=H§,很难通过q用数学方法得到p
  3. 根据一个q=H§,很难找到一个不同的p1使得q=H(p1)

由于hash算法的不可逆性,对hash算法加密后的密文的破解基本上只能用暴力破解的方式,彩虹表也是。最原始的暴力破解的方式是穷举法和字典法。(具体详解请看下面参考的网页和文献)。由于穷举法需要大量的时间,破解时间以亿年为单位,而字典法需要大量的内存,如果将14位的大小写字母和数字的明文空间存储起来,需要的内存数量是10^14TB,显然这是很难办到的。

hash链表

1980年,M提出了一种时间和内存相互折中的方法,time memory trade-off(TMTO),也就是最早的hash链表。在一次hash散列中,假设明文为p1,hash算法为H,加密后的密文为h1,即
在这里插入图片描述
这也是在字典表中的存储方式,存储一个hash值和明文对。hash链表使用了reduction函数R。R函数的功能是将一个散列值重新映射到明文空间中,因此R函数的值域和定义域是和H函数相反的。用上面的例子来说,R函数可以将p1的hash值h1映射成另一个p2,其中p1不等于p2。p2再经过H散列可以变成散列值h2。因此散列链的结构如下: 散列链
其中存储了(p1,h1)(p2,h2)……(pn,hn)n对hash值,但是一条hash链表只需要存储开头和结尾的明文字符p1和pn+1

R函数

一个的hash链表的成功率取决于其中明文的覆盖范围,这显示出一个好的R函数的重要性。一个好的R函数应该满足
1.减少映射回明文空间的碰撞;
2.像hash函数一样尽可能将明文随机映射到明文空间 ;
3.将明文的值限制在要求的字符范围内;

但是一个表中链太长链太多都会造成明文的碰撞,然后一条链上剩余的值都会产生碰撞,这就造成了很多不必要的计算。其中在P的论文中有说明,这种碰撞导致的时间消耗占50%以上。因此hash链表的建议是将明文数量按照 N(1/3)个表 ,每个表中有N(1/3) 个链,每个链上有 N(1/3) 对明文和散列值。

破解过程

将hash链表建立后,剩下的就是破解密文s了。

首先对密文s用R函数映射到明文空间得到一个值s1,查找所有链的结束点是否有与s1相同的,如果有相同,那么大概率这个密文s对应的明文是这条链上的pn,如果未查找到相同值,将这个s1再进行一次 H和R运算得到明文s2,s2与所有链的结束点比较,如果相同那么大概率这个密文s对应的明文是这条链上的pn-1,如果循环往复直到找到一个相同的值与链的结束点相同,如果未找到,查找失败。

distinguished point 检查点

检查点的概念是R对Mhash链表的优化
因为在当时对破解密码来说,最大的瓶颈不是处理器,而是内存访问。因为在每一步都需要将得到的明文值与所有链的结束点进行比对,这就造成了大量的内存访问。因此为了减小内存访问速度这个瓶颈,R提出了检查点的概念,即为每条链的结束点定义一个规则,每条链必须以符合规则的结束点结束。这就没必要每次都访问内存,如果得到的明文不符合结束点的规则,不需要比较,直接计算下一个明文。

rainbow table

其实rainbow table也是对hash链表的一个优化,只是食大便了,与R的方向不同。
rainbow table提出的优化是在一条链上,每一个R函数都应该是独一无二的。即:
在这里插入图片描述
这样能很明显的减少链的碰撞:如果两条链在不同的列产生了相同的明文,但是由于下一个R函数不同,下一个得到明文也不同。只有当两个相同的明文出现在同一列,两条链才会产生碰撞。而这样的概率只有1/t(t是链表长度)。
以下t:链长度 m:链数量
在P的论文有说,t个大小为m x t的hash链表的成功率与大小为mt x t的成功率大约相等,不过论文中也没有给出解释。
不过如果不拘泥于形式化验证的话,可以这样想:t个hash链表之间采用不同的R函数,每个hash链表都相当于rainbow table中的一列,所以t个hash链表总的明文覆盖范围应该和一个采用t个R函数的彩虹表差不多。
不过如果只有这个,也不算很大的创新。理论上来说,彩虹表相比于hash链表要减少一半的破解时间,而且碰撞减少了很多,这也可以减少很大一部分时间。将一个hash链表从n遍历到1,需要O(t)的时间复杂度,但是由于有t张表,因此需要t2的时间。将一个彩虹表从n遍历到1需要t(t-1)/2,因此减少了约一半的时间。

P的论文中可以按照t=N1/3,m=N2/3配置,这应该就是现阶段时间和内存的妥协吧,如果未来哪个方向如果有什么重大突破,这种比例我觉得还会随之变化。

总结

虽然采用预先计算的hash链表或者是彩虹表能够很大程度的减少破解的时间,但是制作彩虹表的计算量一点都没有减少,甚至更多。这是因为,一张彩虹表如果要达到一个可接受的百分之五十以上的成功率,要计算的明文数量至少是所有明文空间的数量,因为R函数映射的每一个值并不一定都在明文空间内。所以往往我们需要多个彩虹表来提高破解的成功率。

成功率计算

单个彩虹表的成功率可以计算表的每一列来得到,这可以看成一个古典表的问题(即Hellman提出的hash链表)。在彩虹表的第一列,我们以m1=m,即链的数量,个不同的明文作为第一列。第二列由m1个明文随机分布到明文空间为N的范围内,产生了m2个不同的明文,其中:
第二列不同明文的个数
每一列i都有mi个不同的明文,所以一个彩虹表的成功率的计算公式如下:
成功率计算公式
对这个公式的理解:每一个彩虹表从最后一列开始搜索,如果没有发现产生的明文,则去倒数第二列搜索,如此往复,最终如果搜索到第一列仍然没有发现明文,则搜索失败。搜索失败只有一种情况,即在每一列都搜索失败,所以最后的成功率等于1减去失败的概率。在第i列失败的概率为1-mi/N,所以全部搜索失败的概率为(1-m1/N)(1-m2/N)……(1-mt/N),成功的概率即1-失败的概率。
下面是我用python实现的根据明文空间N 链长度t 链数量m计算一个彩虹表的成功率函数

def success_rate(N, t, m):
    keys = []
    keys.append(m)
    for i in range(1,t):
        key_i = N*(1-(1-1/N)**keys[i-1])
        keys.append(key_i)
    result_fail=1
    for i in range(t):
        result_fail *= (1-keys[i]/N)
    return 1-result_fail

if __name__=="__main__":
    result_success = success_rate(7555858447479,15200,805306368)# lm_ascii-32-65-123-4 1-7
    #result_success =success_rate(6704780954517120,422000,67108864*360)#md5_ascii-32-951-8
    print(result_success)

多个彩虹表的成功率计算:
其实和计算一个彩虹表的成功率方法有共同之处,所谓成功千万条,失败只一条。查找失败的情况是在所有的彩虹表中都查询失败。由于不同的彩虹表采用的R函数集不同,所以多个彩虹表之间没有影响。设每个彩虹表的成功率为s1,s2……,sn,每个彩虹表的N t m都相等,所以每个彩虹表单独的成功率都相等,设为s,失败概率为1-s,多个彩虹表查找时失败的概率为(1-s)n ,即成功的概率为1-(1-s)n

疑问

1、我写的这个函数用很多数据检验过,(数据来源于rainbowcrack)比如上面第一个明文空间数量为7555858447479,得到的成功率为55.8%,采用8个彩虹表计算出的成功率确实可以达到99.9%。 但是对第二个md5的95个字符的明文空间,得到的成功率大相径庭。有大佬的话,求告知。
2、而且P提出的公式有一个前提,那就是如果R函数将其中一列映射后的值不在明文空间中,那么其后面的所有值应该都不会被计算为有效的明文。但是为什么一个不在明文空间的一个二进制串,在经过hash,再映射之后不会重新进入明文空间呢。

参考文献:
http://www.h-online.com/security/features/Hellman-and-Rivest-746294.html
https://blog.csdn.net/Saintyyu/article/details/102583941
https://blog.csdn.net/Saintyyu/article/details/102583941
Making a Faster Cryptanalytic Time-Memory Trade-Off

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值