MD5和SHA-1

Posted kuroniko

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MD5和SHA-1相关的知识,希望对你有一定的参考价值。

MD5和SHA-1都是我们耳熟能详的术语了,很多人可能知道他们跟加密有关系,但是他们是怎么做到加密的,他们各自的特点又是什么。我来简单的讲一讲。

MD5和SHA-1都被称作哈希(Hash)函数,用过Java语言的人对这个术语应该相当熟悉。Java类库里的Object类定义了hashCode这个函数,但是java的概念略有不同。正式的哈希函数的定义是“把任意长度的数据计算成固定长度的数据”。也就是说函数的输入是任意长的,输出总是固定长度的。MD5和SHA-1是两种加密用哈希函数,MD5的返回值总是128bit的,SHA-1的返回值是160bit,都是固定长度。MD5如果按十六进制表示的话是32位十六进制的数,SHA-1是40位十六进制的数。

你可以用下面两个网站试用这两个函数,这样有个感性认识:

MD5:http://md5-hash-online.waraxe.us/

SHA-1:http://sha1-hash-online.waraxe.us/

你输入任意长度的字符串,都会返回给你相应固定长度的十六进制返回值。这两个函数的返回值都被称为信息摘要(Message Digest,实际上MD就是Message Digest的缩写)。

 

那么两个函数为什么可以用在加密上呢?因为他们都有这几个特性

  1. 都是“不可逆”的函数。不存在一个算法能够由哈希值倒算出原始信息。
  2. 对原始信息的任何一点改变都会导致结果的哈希值巨大的不同。举个例子,假如原始数据是几百万字的文章,你在其中哪怕改动一个标点,计算出的哈希值都会有很大的变化。
  3. 运算代价是相对较低的。普通的AMDOpteron 2.2GHz的芯片,每秒可以计算出335MB数据的MD5值,可以计算192MB数据的SHA-1值。   参见https://en.wikipedia.org/wiki/SHA-1#Comparison_of_SHA_functions
  4. 类似于1,除非通过蛮力的穷举法,否则无法找到两段不同的信息而有相同的哈希值。(这一点现在已被证明是不成立的了,请看后文)

 那么这两个函数的特点在哪里呢?特点在于都能“通过哈希值唯一标识原信息”。这个怎么讲,就是比如原始信息是A,我知道原始信息的哈希值Ha,如果我有另一段信息,这段信息的哈希值也是Ha的话,我就能“以极大的可靠性”断定这另一段信息就是A。也就是说哈希值能“唯一”标识原始信息。原因是什么呢?

  1. 两段不同信息“碰巧”有着相同的哈希值的概率是很低的,对于MD5来说是2的128次方分之一,这个数字是多小呢:太阳的表面积是6万亿平方公里,一个原子的截面积大约是1平方纳米,假设你是一个原子,把你放在56个太阳中任意一个的表面,这个概率是我在这56个太阳上随意指定一点,正好点中你的概率,而你是一个小小小的原子。对SHA-1来说,这个概率就更低了。
  2. 那么有没有办法人工伪造一段信息正好有Ha这个哈希值呢?根据上面的1和4,这个可能性是很低的,要通过穷举法的巨大的运算量才能做到。

 

那么他们通常有什么应用呢?

1.      密码加密(很常用的一种用法)

比如我有一个网站,用户注册的时候会输入用户名密码,大家都知道如果密码是明文的方式存储在数据库里的话,如果这个数据泄漏或者内部人员作恶的话,会造成信息安全问题。所以通用的做法是把用户输入的密码做MD5或SHA-1的运算,把返回的固定长度的哈希值存储在数据库中。比如用户的密码是”bigcat”,实际存储在数据库中的值是它的SHA-1的值a748bf7fee2289b22d448ed8efde10a68f7d1cf9。因为这两个函数的“不可逆”性,所以任何人拿到这个hash值是无法知道用户的明文密码的。

2.      文件校验

在网上下载大尺寸文件的时候常见到网站同时会提供这个文件的MD5的值,它的作用是用户下载后可以在下载文件基础上计算MD5的值,如果和网站提供的MD5是相同的说明文件在下载过程中没有损坏或者说文件没有被恶意网站修改。

3.      工作量证明(Proof ofWork)

上面两种应用比较常见,工作量证明就不那么常见了。这里有一篇关于工作量证明的很好的文章:http://www.zhihu.com/question/22369364/answer/23600737

 

 曾经(在2005年之前),这两个哈希函数被认为是很好的Message Digest(信息摘要)函数,它们的返回值能够“唯一”标识原始信息,而在2005年,中国山东大学的王小云教授的惊天动地的发现颠覆了这一国际加密学的基础。详情请看我后续文章。

 

 

 

上文介绍了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的值它可以给你“解密”成原文,比如:

http://www.ttmd5.com/

http://www.cmd5.com/

稍微观察一下就会发现,这些网络只是用穷举法算出来非常庞大(几十TB到几百TB数据量)的信息和摘要对,来匹配你输入的MD5值,所以它们能“解密”的原始信息只是固定模式的字符串:如8位以下的小写英文字母的组合,等等。

真正的解密MD5和SHA-1消息摘要的办法还不存在。

以上是关于MD5和SHA-1的主要内容,如果未能解决你的问题,请参考以下文章

python 中md5 和 sha1 加密, md5 + os.urandom 生成全局唯一ID

校验文件MD5_SHA1_SHA256值

128 位的 SHA-1 散列是不是比 MD5 散列更安全?

iOS 中MD5和sha1加密

MD5/SHA1/Hmac_SHA1

PHP 之sha256 sha512封装