密码学实战-哈希函数(内容详细+视频 信息安全专业的必修课)
本节内容,我们主要探讨第2章节:哈希函数。包括,什么是哈希函数,哈希函数的安全属性,哈希函数的实际应用,以及标准化的哈希函数。
2.1 什么是哈希函数
哈希函数在密码学中随处可见!回想一下,上一节课中谈到密码体制的分类,按照是否能进行可逆的加密变换,将密码体制分为双向函数密码体制和单向函数密码体制。哈希函数就属于单向函数密码体制,其特点是:给定的任意长度的输入,总是产生全局唯一的字符串输出;相同的任意数据的输入,总是产生相同的唯一输出。这里的输出通常被称为摘要或者是哈希值。
在密码学中,包含很多哈希函数,其分类包括大家常见的MD5、SHA-1、SHA-2等,还包括SHA-3、SHAKE、cSHAKE、口令哈希等等。下面,我们通过文件完整性校验的示例,来初步了解下哈希函数的特性。
在oracle jdk的下载页面中,我们会看到每个下载包文件后面,有标识sha256的链接,sha256就是一种哈希算法名称,点击进去,可以看到一串字符串,这个字符串就是该jdk包文件的哈希值。我们将jdk包文件下载下来,使用指定sha256算法的openssl命令,对该文件包做哈希运算,得出的哈希值与网页中的哈希值一模一样。这个不是偶然的,而是必然的。这是哈希函数的特性决定的,相同的输入必然会产生相同的输出,且是全局唯一的。当然,我们也无法找出另外一个文件,通过相同的哈希函数,得到相同的输出。
文件完整性校验分析
接下来,让我们分析一下,文件完整性的校验过程。从刚才的示例中,我们可以得出,无论下载的文件来自哪里,绝不可能找出第二个jdk包文件,经过sha256算法哈希后,得出与网页中标识相同的哈希值。也就是说,必须是真实的jdk包文件,才可以与网页中的哈希值匹配,只有校验通过的文件才可以下载。但是,我们可以思考一下,如果网页中标识的哈希值被篡改了呢,攻击者可以提供一个恶意的文件并篡改网页中的哈希值,这样也可以通过哈希算法校验通过。
因此,整个文件完整性校验过程中,仅仅使用一个哈希函数并不能保证文件的完整性和真实性,还需要有信任基础,那就是包含摘要字符串的网页、网页所有者以及获取网页的机制,都是安全可靠的。这里的可靠机制,可以采用HTTPS协议机制,这在后面章节中会详细阐述。
最后,我们来总结下,哈希函数有哪些特性:
- 哈希函数的输入可以来自文件、消息或者视频等,输入可以是任意大小,而它的输出长度总是固定的。
- 哈希函数具备确定性,给定的相同的输入,总是产生相同的输出。像示例中介绍的sha256哈希算法,始终提供256位的输出,最终编码为64个16进制字符。
- 哈希函数是单向函数,具备不可逆性,无法从输出中导出输入。
2.2 哈希函数的安全属性
哈希函数具备三大基础属性,分别是抗一原像性、抗二原像性和抗碰撞性。接下来,我们来探讨这三个属性。
哈希函数的第一个安全属性是抗一原像性,也就是单向不可逆性。如图中所示,输入通过哈希函数可得出摘要,反之则不行。给定哈希函数的摘要,我们不可能推导出它的原始输入。这里的不可能有个前提,就是输入的空间不能太小,并且具有不可预测性。试想下,如果输入的值很小,比如abc、123等,那么很容易对所有的可能值进行枚举,这就很容易找出其哈希值与给定哈希值相同的输入。
哈希函数的第二个安全属性是抗二原像性,给定一个输入、哈希函数和摘要,无法找出哈希值相同的另外一个不同的输入。注意,这里的第一个输入是固定不变的,只有第二输入在变动。这与第三个安全属性有所区别。
哈希函数的第三个安全属性是抗碰撞性,给定哈希函数、摘要,无法找到哈希值相同的两个不同的输入。这里的两个输入都在变动。第二个安全属性和第三个安全属性容易混淆,我们可以花些时间,自己推敲下,感受这两者的不同之处。
安全性考量
我们来重点考量下,哈希函数的这三个安全属性。每个安全属性都有其对应的缺陷。首先,如前面讲解到,抗一原像性的前提是输入不能太小,要足够的随机,要具有不可预测性。太小的输入空间,比如简单字符串abc,很容易通过遍历的手段,找出给定哈希值的输入。
其次,抗二原像性,只是实践中很难找到第二个输入,其哈希值与第一个输入相同。理论上,只要输入足够多,输入空间足够大,并非不可能找到第二个输入。再来看看第三个安全属性,抗碰撞性,如果输出的摘要空间很小,比如仅仅是两个比特,那么,概率上,一个均匀随机的哈希函数,从时间的维度上,输出00、01、10、11这四个值,每个值都有四分之一的时间概率获得输出。因此,也就很快能找出两个不同的输入使其哈希值相同。因此,通常情况下,哈希函数的输出长度,要求不能低于256比特。
那么,这里的256比特,是怎么来的呢?我们来简单做个推算。在密码学中,算法的安全级别不能低于128比特,因为128比特的遍历空间是2的128次方,这么来说吧,如果使用100万个处理器并行的计算,每个处理器的算力是每秒中运算100万次,那么遍历2的128次方的所有空间,还需要宇宙年龄的10亿倍这么长时间。因此,128比特空间在现有算力的应用密码学中,已经足够安全。那么,256比特又是怎么产生的,概率论中有个生日悖论,就是一个房间中至少需要多少人,才能使得两个人的生日相同的概率至少达到50%,实际上,当从2的N次方种可能的空间中随机生成字符串时,在已经生成大约2的,2分之一N次方个字符串后,碰撞的概率会至少达到50%,也就是说,哈希函数产生256比特的随机输出,在生成2的128次方个摘要后,碰撞的概率就会很高了。而,2的128次方,又是密码学算法的安全目标,因此,才有了哈希函数的输出长度不能低于256比特的结论。
最后,我们来总结下,256比特是为了解决抗碰撞性的安全性,128比特是密码学算法要满足的安全级别。所以,为了满足抗碰撞性,摘要长度至少要是256比特。为了满足抗一和抗二原像性,摘要长度至少要是128比特。通常,在实际应用中,如果只是对文本输入做个散列运算,只需要输出长度为128位的哈希函数就可以了。比如MD5是128位的,SHA-1是160位的。
2.3 哈希函数的实际应用
在现实世界中,哈希函数的用途很多,我们来逐一看下,哈希函数具体都有哪些实际应用。
- 哈希函数可用于数据加密,如前所述,哈希函数是单向散列函数,通常可以计算文本、图片、视频的摘要,用于加密的哈希算法有SHA-256、SHA-512等等,MD5和SHA-1由于其算法本身构造问题和弱碰撞性,已经被破解,因此,只可应用其抗一和抗二原像性。使用SHA-256算法的数据加密,具有单向不可逆性,且散列冲突的概率极低,因此使用哈希函数加密数据以获取其散列值是密码学中常见的应用。
- 哈希函数可用于计算唯一标识,比如,从海量的图库中,搜索查找一张图是否存在其中,我们不能简单的用图片的名称来比对,因为可能存在同名但内容不同的图片,或者也有,名称不同,图片内容却相同的情况。那么我们该如何搜索查找呢?我们知道,任何文件,在计算机中,都可以表示成二进制码串,所以,比较直接的方式是,将要查找的图片的二进制码串,与图库中的所有图片的二进制码串,进行比对,如果相同,就说明图片存在。但是,每个图片大则几兆几十兆,这比对起来太过耗时,有没有比较快速的方法呢?实际上,可以使用哈希函数为图库
