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 彩虹表

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

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

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

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

图二展示了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一起保存。

Saltedhash(password)=Hash(password+salt)Saltedhash(password) = Hash(password + salt)Saltedhash(password)=Hash(password+salt)
Saltedhash(password)=Hash(Hash(password)+salt)Saltedhash(password) = Hash(Hash(password) + salt)Saltedhash(password)=Hash(Hash(password)+salt)

盐应该怎么生成,随机生成一个字符串?

  • 使用CSPRNG生成盐

CSPRNG,Cryptographically Secure Pseudo-Random Number Generator。CSPRNG算法,不是普通的随机数算法。
CSPRNG是加密安全的,这意味着用它产生的随机数更加随机,且不可预测。

编程语言 CSPRNG
C/C++ CryptGenRandom
Java Java.security.SecureRandom
  • 盐不能太短,且盐不能重复使用

如果盐很短,那意味着密码+盐组成的字符串的长度和取值空间都有限。黑客完全可以为密码+盐的所有组合建立彩虹表。
如果所有用户的密码都使用同一个盐进行加密。那么不管盐有多复杂、多大的长度,黑客都可以很容易的使用这个固定盐重新建立彩虹表,破解你的所有用户的密码。

注意:有些系统用一个每个用户都不同的字段,uid、手机号、或者别的什么,来作为盐加密密码。这不是一个好主意,这几乎违背了上面全部三条盐的生成规则。

6 密码存储深度讨论

为每一个密码都加上不同的高质量的盐,做HASH,然后保存。这样安全性在当今能保障吗?

计算机硬件飞速发展,一个现代通用CPU能以每月数百万次的速度计算sha256,而GPU集群计算sha256,更是可以达到每秒10亿次以上。这使得暴力破解密码成为可能,黑客不再依赖查询表或彩虹表,而是使用定制过的硬件和专用算法,直接计算每一种可能,实时破解用户密码。

针对这一点,密码学家们设计了PBKDF2、BCRYPT、SCRYPT等用来加密密码的Hash算法,称作Password Hash。在他们的算法内部,通常都需要计算Cryptographic Hash很多次,从而减慢Hash的计算速度,增大黑客暴力破解的成本。

Cryptographic Hash具有如下几个特点:
(1)给定任意大小任意类型的输入,计算hash非常快;
(2)给定一个hash,没有办法计算得出该hash所对应的输入;
(3)对输入做很小改动,hash就会发生很大变化;
(4)没有办法计算得到两个hash相同的输入。

2013年NIST(美国国家标准与技术研究院)举办了密码Hash算法大赛(Password Hashing Competition,PHC),意在寻找一种标准的用来加密密码的hash算法,并借此在业界宣传加密存储用户密码的重要性。最终Argon2算法赢得了这场竞赛,该算法是卢森堡大学的Alex Biryukov,Daniel Dinu和Dmitry Khovratovich设计的一种算法。如今,PHC[3]推荐使用密码哈希算法Argon2,其源码[4],算法Paper[5]。

7 密码泄露事件

2016年Dropbox曾发生部分用户密码数据泄露事件,当时其CTO表示他们对自己加密密码的方式很有信心,请用户放心。随后,Dropbox在其官方技术博客发表名为《How Dropbox securely stores your passwords》[6]的文章,讲述了他们的用户密码加密存储方案。

如上图所示,Dropbox首先对用户密码做了一次sha512哈希将密码转化为64个字节,然后对sha512的结果使用Bcrypt算法(每个用户独立的盐、强度为10)计算,最后使用AES算法和全局唯一的密钥将Bcrypt算法的计算结果加密并保存。文章[6]中,Dropbox描述了这三层加密的原因:

  • 首先使用sha512。将用户纯文本密码归一化为Hash值。因为两个原因:一个是Bcrypt算对输入敏感,如果用户输入的密码较长,可能导致Bcrypt计算过慢从而影响响应时间;另一个是有些Bcrypt算法的实现会将长输入直接截断为72字节,从信息论的角度讲,这导致用户信息的熵变小;

  • 然后使用Bcrypt算法。选择Bcrypt的原因,是Dropbox的工程师对这个算法更熟悉调优更有经验,参数选择的标准,是Dropbox的线上API服务器可以在100ms左右的时间可计算出结果。另外,关于Bcrypt和Scrypt哪个算法更优,密码学家也没有定论。同时,Dropbox也在关注密码hash算法新秀Argon2,并表示会在合适的时机引入;

  • 最后使用AES加密。因为Bcrypt不是完美的算法,所以Dropbox使用AES和全局密钥进一步降低密码被破解的风险,为了防止密钥泄露,Dropbox采用了专用的密钥保存硬件。Dropbox还提到了最后使用AES加密的另一个好处,即密钥可定时更换,以降低用户信息/密钥泄露带来的风险。

8 BCOS关于可验证Credential中proof的盐生成实现

在代码实现中,salt的默认长度是5,DEFAULT_SALT_LENGTH=5DEFAULT\_SALT\_LENGTH = 5DEFAULT_SALT_LENGTH=5,

    /*** generate random string.* @return random string*/public static String getRandomSalt() {String length = PropertyUtils.getProperty("salt.length", DEFAULT_SALT_LENGTH);int saltLength = Integer.valueOf(length);String salt = RandomStringUtils.random(saltLength, true, true);return salt;}

使用apache的common包中提供的工具类RandomStringUtilsRandomStringUtilsRandomStringUtils产生的盐值,工具类中实际上是引用了Java自身提供的随机数产生器工具java.util.Randomjava.util.Randomjava.util.Random。并没有使用securitysecuritysecurity中的SecureRandomSecureRandomSecureRandom类。

9 往期回顾

数字签名系列

  • 图解 ECDSA 签名与验签基本原理
  • 图解 BLS 签名与验签基本原理
  • BLS 签名理论原理和工程实现
  • 基于 RSA 的实用门限签名算法
  • 门限密钥共享技术原理
  • 隐私保护利器之环签名实现原理
  • 多重签名 MultiSig:Schnorr 协议与 ECDSA 协议
  • Schnorr 协议:零知识身份证明和数字签名

智能合约隐私计算

  • 智能合约隐私计算:开篇
  • 智能合约隐私计算:同态加密应用举例
  • 智能合约隐私计算之再谈Paillier同态加密算法
  • 智能合约隐私计算之基于FO承诺的零知识证明

密码学承诺系列

  • Pedersen commitment
  • FO commitment

同态加密系列

  • 智能合约隐私保护技术之同态加密

安全多方计算系列

  • 基于同态加密体制的安全多方计算
  • 基于可验证密钥共享体制的安全多方计算
  • 基于混淆电路的安全多方计算(一)

其他密码学系列

  • 可验证随机函数(VRF)原理和应用浅析

10.参考资料

[0] https://en.wikipedia.org/wiki/Rainbow_table

[1] https://www.zhihu.com/question/19790488

[2] http://project-rainbowcrack.com/table.htm

[3] https://www.password-hashing.net/

[4] https://github.com/P-H-C/phc-winner-argon2/releases/tag/20190702

[5] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf

[6] https://dropbox.tech/security/how-dropbox-securely-stores-your-passwords

关注公众号VenusBlockChain

公众号VenusBlockChain,致力于区块链技术研究,传播区块链技术和解决方案、区块链应用落地、区块链行业动态等。

彩虹表(rainbow table)相关推荐

  1. (总结)密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解(附:120G彩虹表下载)

    以下内容为转载,来自这里 PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞 ...

  2. (总结)密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解

    PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞,这样安全性就大大提高.如 ...

  3. 转载:密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解(附:120G彩虹表下载)

    PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞,这样安全性就大大提高.如 ...

  4. 算法高级(23)-彩虹表(Rainbow Table)

    一.彩虹表的定义 [百度百科]彩虹表是一个用于加密散列函数逆运算的预先计算好的表, 为破解密码的散列值(或称哈希值.微缩图.摘要.指纹.哈希密文)而准备.一般主流的彩虹表都在100G以上. 这样的表常 ...

  5. 密码破解--Ophcrack Rainbow Tables彩虹表原理

    PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞,这样安全性就大大提高.如 ...

  6. Rainbow Crack在windows生成彩虹表并破解Hash值

    Windows生成彩虹表并破解Hash值 前言:因为自己也在这上面遇到很多问题,希望看到这篇博客的学习人可以顺利生成彩虹表. 彩虹表的格式 rtgen hash_algorithm charset p ...

  7. LM NTLM ophcrack RainBow table (转)

    Windows密码的加密方式: Windows 主要使用以下两种(包含但不限于)算法对用户名和密码进行加密: 分 别是LanManager(LM)和NTLM,LM只能存储小于等于14个字符的密码has ...

  8. 高效的彩虹表密码攻击法

    背景 为了保护账号安全,几乎所有网站都不会明文保存用户的密码,而是用哈希加密算法对密码进行计算,将得到的哈希串保存在数据库中.每次用户登录时会将用户提交的密码用同样的算法计算,并将结果与数据库中保存的 ...

  9. 彩虹表原理详解及工具介绍

    PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞,这样安全性就大大提高.如 ...

最新文章

  1. 怎么截取图片大小 html,详解html2canvas截图不能截取圆角图片的解决方案
  2. 20211108 微分跟踪器
  3. springboot获取静态图片路径_SpringBoot中的全局异常处理你确定你真的知道吗?
  4. linux Figlet 转换字符字
  5. jsp中获取当前项目名称
  6. 后缀的形容词_构词法(18)构成形容词的常见后缀 3
  7. 软件设计师 - 系统测试
  8. python装饰器_Python基础-装饰器
  9. python与大数据的关系论文_python与大数据的关系图
  10. redis设置密码和其它服务器连接
  11. QT+ 状态栏+核心控件+浮动窗口
  12. 西门子PID完整程序西门子PLC 1200和多台G120西门子变频器Modbud RTU通讯
  13. JavaScript中的数据类型判断
  14. 秉火429笔记之三GPIO框图剖析
  15. 【视频】线性回归中的贝叶斯推断与R语言预测工人工资数据|数据分享
  16. 【Linux】vi编辑器中:wq 、:wq!、:x、:q、:q!的详细区别
  17. c语言bzero函数头文件,嵌入q式c语言-文件操用.doc
  18. 加密解密五种算法的实现
  19. activeperl安装失败
  20. 【目标跟踪】算法C-COT中文翻译

热门文章

  1. “看到新同事的工资后,我退出了群聊”
  2. Matlab parfor函数详解
  3. uni-app引入iconfont字体成功后显示黑白色?怎么让其保留原本色彩,已解决!
  4. solidworks实体显示线框
  5. Python学习(十一)——matplotlib与可视化
  6. C++开发YDLidar-G4雷达
  7. numba加速python代码
  8. ubuntu下的Redis操作命令
  9. Flutter Web 近期重要更新和路线图发布
  10. Revit里轴网隐藏尺寸标注跟着消失?快速轴网距离标注