彩虹表(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 彩虹表
上图一展示了一个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)相关推荐
- (总结)密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解(附:120G彩虹表下载)
以下内容为转载,来自这里 PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞 ...
- (总结)密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解
PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞,这样安全性就大大提高.如 ...
- 转载:密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解(附:120G彩虹表下载)
PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞,这样安全性就大大提高.如 ...
- 算法高级(23)-彩虹表(Rainbow Table)
一.彩虹表的定义 [百度百科]彩虹表是一个用于加密散列函数逆运算的预先计算好的表, 为破解密码的散列值(或称哈希值.微缩图.摘要.指纹.哈希密文)而准备.一般主流的彩虹表都在100G以上. 这样的表常 ...
- 密码破解--Ophcrack Rainbow Tables彩虹表原理
PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞,这样安全性就大大提高.如 ...
- Rainbow Crack在windows生成彩虹表并破解Hash值
Windows生成彩虹表并破解Hash值 前言:因为自己也在这上面遇到很多问题,希望看到这篇博客的学习人可以顺利生成彩虹表. 彩虹表的格式 rtgen hash_algorithm charset p ...
- LM NTLM ophcrack RainBow table (转)
Windows密码的加密方式: Windows 主要使用以下两种(包含但不限于)算法对用户名和密码进行加密: 分 别是LanManager(LM)和NTLM,LM只能存储小于等于14个字符的密码has ...
- 高效的彩虹表密码攻击法
背景 为了保护账号安全,几乎所有网站都不会明文保存用户的密码,而是用哈希加密算法对密码进行计算,将得到的哈希串保存在数据库中.每次用户登录时会将用户提交的密码用同样的算法计算,并将结果与数据库中保存的 ...
- 彩虹表原理详解及工具介绍
PS:这玩意偶前几天用了一下,确实强悍无比,在这个表面前,md5等公开的加密算法不堪一击啊.记得我之前的公司开发的游戏账号都用修改过的特有MD5加密算法,建议开发人员都这样搞,这样安全性就大大提高.如 ...
最新文章
- 怎么截取图片大小 html,详解html2canvas截图不能截取圆角图片的解决方案
- 20211108 微分跟踪器
- springboot获取静态图片路径_SpringBoot中的全局异常处理你确定你真的知道吗?
- linux Figlet 转换字符字
- jsp中获取当前项目名称
- 后缀的形容词_构词法(18)构成形容词的常见后缀 3
- 软件设计师 - 系统测试
- python装饰器_Python基础-装饰器
- python与大数据的关系论文_python与大数据的关系图
- redis设置密码和其它服务器连接
- QT+ 状态栏+核心控件+浮动窗口
- 西门子PID完整程序西门子PLC 1200和多台G120西门子变频器Modbud RTU通讯
- JavaScript中的数据类型判断
- 秉火429笔记之三GPIO框图剖析
- 【视频】线性回归中的贝叶斯推断与R语言预测工人工资数据|数据分享
- 【Linux】vi编辑器中:wq 、:wq!、:x、:q、:q!的详细区别
- c语言bzero函数头文件,嵌入q式c语言-文件操用.doc
- 加密解密五种算法的实现
- activeperl安装失败
- 【目标跟踪】算法C-COT中文翻译