简洁就是美。把问题说得简单、易懂是一种美德。
上文介绍了MD5和SHA-1函数,我现在来讲一讲这两个函数作为消息摘要函数的安全上的缺陷是什么。
一直到2005年,这两个函数都在国际密码学界被认为是理想的消息摘要函数,直到山东大学的王小云教授发现了这两个函数的致命缺陷:它们都易受冲撞攻击(collision attack)。
什么是冲撞攻击呢?
首先,摘要函数理想上应该符合:非常难找到两个不同的信息而他们的摘要是相同的。这里非常难是指实现上非常困难,理论上讲用穷举法当然可以做到,但是要求的运算量过大使得现实上是不可能的。所谓冲撞攻击是指一种相对“廉价”的方法能找到两个有相同摘要的不同信息。
实际上对于MD5来说,由于它的摘要信息位数比较短(128 bit),现在用普通的计算机可以在几小时甚至几分钟之内找到冲撞对,这就是相当“廉价”了。而对于SHA-1(160 bit)来说,王小云教授的成果证明可以在2的69次方次尝试后找到冲撞对(这个结果之后在被不断地被改进),但这个计算量仍然过大,以当代的计算机运算能力来说,现实上仍然很难实现(需要的运算量大意味着需要的资金大)。根据这篇文章https://www.schneier.com/blog/archives/2012/10/when_will_we_se.html,即使到2018年,找到一个SHA-1冲撞对所需要的资金是17万3千美元,现在的2016年需要的就更多了。
那么能找到冲撞对,意味着什么样的安全漏洞呢?比如可以利用MD5的这个漏洞来伪造数字签名,看https://en.wikipedia.org/wiki/Collision_attack#Digital_signatures。简单的说就是我造两份文件(一份正常文件,一份恶意文件)它们有着相同的MD5 hash,而一般数字签名是针对文件的消息摘要而不是文件全文来做的,我就可以拿着正常文件取得消息摘要的签名认证(证明这个文件是合法的),然后我拿着恶意文件和这个取得认证的消息摘要,受攻击者就会的会误认为这个恶意文件是取得签名认证的。
所以,对MD5的冲撞攻击是比较容易的,对SHA-1的冲撞攻击相对代价较大,但是随着机算机能力年年的发展正变得越来越容易实现。
上面我们讲的是冲撞攻击,这里我要讲一个误区,看到很多文章把冲撞攻击和预镜像攻击(preimage attack)混淆,这是两个本质上不同的安全漏洞。什么是预镜像攻击呢,就是对于一个预指定的消息摘要(哈希值),我可以造一段信息出来使得这段信息的消息摘要就等于这个预指定的值。注意,冲撞攻击不能针对一个预指定的消息摘要。
预镜像攻击的应用,比如针对消息摘要常用的一种场景:用户密码明文保护,就是用户密码的明文并不存储下来,而是只存储用户密码的消息摘要。比如用户的密码明文是mypass,实际存储在应用里的只是这个密码的消息摘要a029d0df84eb5549c641e04a9ef389e5。
如果预镜像攻击是可行的话,我只要拿到用户密码的消息摘要,我就可以造另一个密码(注意根据消息摘要的“不可逆”原则,理论上你无法算得用户明文密码”mypass”,但是你可以造出另一个字符串组合)出来而有同样的摘要值a029d0df84eb5549c641e04a9ef389e5,我就能欺骗系统取得这个用户身份认证了。
但是,目前理论界还没有发现现实可行的预镜像攻击,参见https://en.wikipedia.org/wiki/Preimage_attack#Applied_preimage_attacks。也就是要进行预镜像攻击需要宠大的运算量(也就是资金)的支持,现实上不可行。所以如果你的系统是在用MD5或SHA-1加密用户密码的话,在一定时期内你仍然是安全的。
最后,在互联网上你能找到这样的MD5的“解密”工具,你输入MD5的值它可以给你“解密”成原文,比如:
稍微观察一下就会发现,这些网络只是用穷举法算出来非常庞大(几十TB到几百TB数据量)的信息和摘要对,来匹配你输入的MD5值,所以它们能“解密”的原始信息只是固定模式的字符串:如8位以下的小写英文字母的组合,等等。
真正的解密MD5和SHA-1消息摘要的办法还不存在。