如何安全存储密码都不知道,难怪我会被面试官吊打咯!( 五 )


如何安全存储密码都不知道,难怪我会被面试官吊打咯!

文章插图
 
具体来说就是在不同位置出现了冲突:
// 不同输入 不同R函数产生相同的明文R1(FEDECE)=333R2(FEDEFE)=333但是很快在下一个不同的R函数,R3和R2的作用下就不再重叠了,可覆盖的明文数量影响不大,也只有333出现了重叠后续是独立的 。
极端情况下相同位置的冲突由于每个位置的R函数相同所以最终尾部明文仍然是相同的,可以进行纠正删除从而减少冗余数据,如图:
如何安全存储密码都不知道,难怪我会被面试官吊打咯!

文章插图
 
综上可知,彩虹表引入一组多个R函数确保了相同位置出现R冲突时的检测删除和不同位置出现R冲突的影响最小化,相比哈希链集合有一些优势 。
读到这里我们对于为什么叫做彩虹表隐约有了一点感觉,大概意思就是每一组哈希链都有不同的R函数,就像这样:
如何安全存储密码都不知道,难怪我会被面试官吊打咯!

文章插图
 
5.6 彩虹表的攻击简单过程彩虹表涉及一个复杂的建表过程,并且不同格式长度的密码和不同的哈希函数都会有不同的彩虹表,网上有一些现成的彩虹表,感兴趣的读者可以根据自己的现状下载一些彩虹表数据进行验证,一般来说在实用的彩虹表在100GB以上 。
要增加破解的概率就需要完善的彩虹表数据作为支撑,彩虹表的意义就在于把计算暴力破解和空间枚举结合起来 。
来简单说一下彩虹表的攻击过程吧:
如何安全存储密码都不知道,难怪我会被面试官吊打咯!

文章插图
 
假设有K组H-R函数组合,彩虹表按照[head_string,tail_string]格式存储,如图:
如何安全存储密码都不知道,难怪我会被面试官吊打咯!

文章插图
 
  • 假定给定的密文P位于最后一组H-R中,也就是第K个R函数存在R(P)=tail_string,如果tail_string存在于彩虹表中,则从head_string进行推算;
  • 如果第K个R函数生成的结果不存在,则向前继续搜索第K-1个R函数一直计算到最后获取tail_string,再判断是否存在;
  • 最坏的结果是从第1个R函数推算到最后得到的tail_srting仍然不存在,则说明这条链匹配失败;
到这里,我们基本上对彩虹表的原理和过程有了粗浅的认识,但是彩虹表也不是无敌的,因为它有个强大的对手【哈希+盐】存储 。
6. 哈希+盐组合加密存储一直在说无盐单向哈希存储,但什么是盐呢?
简单来说,盐就是在用户输入密码的基础上增加的额外部分数据,这部分数据也参与计算哈希存储密码 。
H(user_input_string+slat)=new_password和做菜一样,在存储密码中加盐也是技术活,不由得要问:为什么加盐就把单向哈希变得这么强大了呢?
其实很简单,因为盐不知道是怎么加的,也不知道加的什么!
如图展示了一个使用彩虹表破解明文之后进行登陆仍然失败的情况:
如何安全存储密码都不知道,难怪我会被面试官吊打咯!

文章插图
 
暴力破解得到的密码是bnghuopyi99,输入之后失败,因为用户输入的明文是nghuopyi,盐是b99,混合方式是取盐的第一个字符放在用户输入最前面,剩下的追加在后面从而形成了bnghuopyi99 。
随机的盐和不确定的添加方式,让彩虹表不那么给力了,换句话说每个用户可能有单独的混合方式,破解成本大大增加 。
到这里,仿佛哈希+盐的方式还是不错的,但是这仍然不是最优的解决方案,我们继续来看 。
7. 专业的密码加密算法前面我们学习的一些比如sha256这些算法本质上并不是为了存储密码设计的,相反这些摘要算法有其主要用途,那么不禁要问:有没有专门为密码设计的加密算法呢?
答案是肯定的 。
我们都知道GPU的性能是十分恐怖的,计算速度非常快,试想我们把加密算法变慢,攻击方也必然会被拖慢,比如加密算法需要200ms完成加密存储,这个时间对于用户而言是可以接受的,但是对于攻击方来说时间成本就非常大了 。
听着有种故意把对手绕晕的感觉,本质上专业的密码加密算法可以设置强度,来提高暴力破解的时间成本,比较常见的加密算法有以下几种:
  • bcrypt算法
bcrypt 是专门为密码存储而设计的算法,基于Blowfish 加密算法变形而来,由 Niels Provos 和 David Mazières 发表于 1999 年的 USENIX 。bcrypt 的work factor参数, 可用于调整计算强度,而且 work factor 是包括在输出的摘要中的,随着攻击者计算能力的提高,使用者可以逐步增大 work factor


推荐阅读