彩虹表(rainbow table)

1 彩虹表引入

在看微众银行开源的WeIdentity规范中的可验证凭证Credential数据结构时,看到有关于防止彩虹表方式反向破解哈希的问题,如下图所示。

在执行选择性披露用户的信息时,是将claim中的其他字段内容进行hash,只披露其中某一条或几条数据给验证方。如果不加盐会有什么后果,下面会给出答案。

{
  "claim": {
     "age": 1,
     "gender": "F",
     "id": "did:weid:101:0xd6f4d1215c52ee7e7975ac946a0e094040aa5eeb",
     "name": "1"
  },
  "proof": {
     "salt": {//对应claim加的盐值
        "age": "IObiF",
        "gender": "GdzQs",
        "id": "dDIIt",
        "name": "PecuG"
     },
   },
 }

注意:仅摘取了Credential结构的与本次内容相关的部分内容。

2 存储密码的方式以及安全分析

存储方式 安全性
明文m存储 无安全性可言
存储明文的哈希值hash(m) 由于彩虹表的存证,很容易批量还原出密码明文m
存储密码明文的加盐哈希 hash(m+salt) salt可以是用户名、手机号等,但必须保证每个用户的salt都不一样才相对安全,盐值不是秘密的,可以随机生成并与密码哈希一起存储。

从1976年开始,业界开始使用Cryptographic Hash加密用户密码,最早见于Unix Crypt。但MD5、SHA-1已被破解,不适合再用来保存密码。
例如,保存用户密码的SHA256值,这样就安全了吗?不行。黑客可以用查询表或彩虹表来破解用户密码。注意是破解密码不是破解sha256,能根据sha256破解密码的原因是,
用户密码往往需要大脑记忆、手工输入,所以不会太复杂,往往具有有限的长度、确定的取值空间。

  • 短的取值简单的密码可以用查询表破解
    比如8位数字密码,一共只有10^8种可能。一亿条数据并不算多,黑客可以提前吧0-99999999的sha256都计算好,
    并以sha256做key密码为value存储为一个查询表,当给定sha256需要破解时,从表中查询即可。

  • 取值相对复杂,且长度较长的密码,可以用彩虹表破解
    比如10位,允许数字、字母大小写的密码,一共有(10+26+26)^10种可能,记录非常之多难以用查询表全部保存起来。这时候黑客会用一种叫做彩虹表的技术来破解,彩虹表用了典型的计算机世界里解决问题的思路,时间换空间。在这个例子里面,空间不够,那就多花一些时间。在彩虹表中,可以将全部的sha256值转化为长度相同的若干条Hash链,只保存Hash链的头和尾,在破解的时候先查询得到sha256存在于哪条hash链中,然后计算这一条hash链上的所有sha256,通过时比对来破解用户密码。

3 彩虹表的前身

彩虹表之前已经出现了对hash函数的破解算法,被称为:“预计算的哈希链集”(Precomputed hash chains)。下面是k=2的哈希链:

KaTeX parse error: Undefined control sequence: \require at position 2: \̲r̲e̲q̲u̲i̲r̲e̲{AMScd} \begin{…

不变的R函数会存证:哈希碰撞问题

在哈希链集中,每次对哈希结果逆向计算时,采用的R函数是一样的,因此会产生哈希碰撞。随着哈希碰撞的增加,这样的重复链条会造成严重的冗余、存储空间和破解时间的浪费。

KaTeX parse error: Undefined control sequence: \require at position 2: \̲r̲e̲q̲u̲i̲r̲e̲{AMScd} \begin{…

KaTeX parse error: Undefined control sequence: \require at position 2: \̲r̲e̲q̲u̲i̲r̲e̲{AMScd} \begin{…

因此,在选择函数R时,非常重要。更详细的解释,可参考知乎问答[1]。

4 彩虹表

彩虹表.png

上图一展示了一个Hash链长度为3的彩虹表,因为在Hash链中需要将Hash值使用R函数映射回密码取值空间,为了降低R函数的冲突概率,长度为K的Hash链中,彩虹表会使用k个R函数,因为每次迭代映射回密码空间使用的R函数不一样,这种破解方法被称作彩虹表攻击。

网络[2]上已有一些已经计算好的彩虹表可以直接使用,所以直接保存用户密码的sha256是非常不安全的。

如果已经有了上图一生成的彩虹表,怎样找到Hash函数H的一条密文re3xes对应的明文呢?
实现这个,需要两个步骤,第一步猜测密文属于哪一条链;第二步验证猜测,同时计算出对应的明文。

解释这个破解过程需要明确一点:如果re3xes对应的明文属于彩虹表中的某条链,那么就有可能找到其对应的明文,注意这里的”属于某条链“不仅仅是指属于彩虹表的一条链中存放的头尾两个字符串,还包括这两个字符串中的中间数据,图一中中间计算的明文数据secret、jimbo也算是属于彩虹表的第一条链中,同理bernie、zurich属于第二条链,culture、crypto属于最后一条链,虽然彩虹表中只保存了每条链的链首链尾两个字符串,但是这些中间数据是可以根据链首字符串重新计算出来的。

彩虹表破解过程.png

图二展示了re3xes的破解过程。

先猜测下密文re3xes对应的明文数据是某条链中间计算出数据的最后一个,注意第一、二条链的中间数据中的最后一个明文口令jimbo、zurich,依次经过H-R3运算得到保存的链尾字符串rootroot、myname,那么密文re3xes经过R2-H-R3转换之后得到的数据就是某条链的链尾字符串,这点应该不难理解。

如密文v0d$x对应的明文jimbo是第一条链最后一个中间明文数据,则v0d$x经过R3转换得到链尾字符串rootroot,但是密文re3xes经过R3函数转换之后得到的rambo并不是表中保存的任一条链的链尾字符串,这就说明re3xes对应的明文数据并不是某条链中间计算出数据的最后一个,猜测不成立。

继续猜测re3xes对应的明文数据可能是某条链中间计算出数据的倒数第二个,同样可以很容易推出re3xes依次经过R2-H-R3转换之后得到的数据是某条链的链尾字符串,计算出re3xes经R2-H-R3转换的结果为linux23,通过搜索彩虹中存放的链尾字符串,得到linux23恰好是最后一条链的链尾,到了这一步已经成功了一大半。

下面就来根据存储的最后一条链链首的passwd重新计算出密文re3xes对应的明文,进行验证阶段。既然re3xes经R2-H-R3转换之后得到链尾的linux23,那么链首的passwd经H-R1-H运算后的结果culture就是re3xes对应的明文。

5 彩虹表攻击的防御

加盐值,一般来说就是将用户的key+salt一起Hash,即Hash(key+salt),然后与salt一起保存。

S a l t e d h a s h ( p a s s

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值