之前讨论的问题是:信息保密。(通过加密的方式)
有时候,我们可能不需要对信息保密,而是希望接收者能够验证在传递过程中的消息有没被修改,即入侵者不能用假消息代替合法消息。(数据完整性)
一个生活中的问题:如何识别某个人的身份?身份证、指纹。
对应的,我们有数据指纹。
那么一个指纹函数需要满足什么条件?
指纹能处理不同人的身份识别
-》1.该指纹函数要能处理不同长度的数据(甚至是任意长度)
人的指纹是一个规模相对固定的信息
-》2.指纹函数的输出长度要固定
获取一个人的指纹非常容易
-》3.数据指纹的计算应该比较容易
已知一个指纹,不能知道指纹是谁(不使用指纹匹配查询的系统)
-》4.指纹函数的计算具有单向性
找到两个人的指纹完全一致是不可能的
-》5.给定一个消息,要找到另外一个消息的指纹与给定消息的指纹一致,是不可能的
在世界上找到任意两个人指纹完全一样是不可能的
-》6.找到任意两个指纹一致的消息,是不可能的(包含性质5)
具有上述性质的指纹函数为单向散列函数
记为h(x), 具有以下的性质:
1.h(x)的输入x为任意长度
2.h(x)的输出长度固定
3.h(x)的计算方便快捷
4.h(x)的计算具有单向性
5.对于给定x, 找到y<>x, 且h(y)=h(x)在计算不可行
6.找到一对数(x, y), h(x)=h(y)在计算上不可行(包含5)
这样的函数是满足特殊性质的Hash函数,后文简称Hash函数,产生的输出(消息指纹)称为消息摘要,简称摘要。
使用Hash函数进行完整性验证的模型:
Hash函数可以解决口令验证的问题:
一个用户想进入一个重要的计算机系统,如果计算机存储的是用户的口令,那么就会出现很多问题。问题的关键是,验证口令时,能不能不要知道具体的口令。
模型:
不同口令有不同的口令摘要
只有口令摘要不能恢复口令
但是这样会有问题,如果攻击者用暴力破解的方法,尝试n个口令,最终能够找到正确的口令,在这个过程中,如果他把口令和对象的口令摘要记录成一个字典,下次破解就只需要查找这个字典就可以了。
解决的办法是加入一个盐,成为一个含盐口令摘要,盐是一个随机数,在口令设置时预设,且不需要保密。
不需要保密的原因是:我们必须要盐存起来,以便验证时使用,就有可能泄漏盐,那么就不对盐进行保密了。
得到的好处:字典攻击失效,对同一口令,盐不同,摘要就不同,字典的空间变得很大,穷举的时间非常长。
模型变得更加合理:
在前面的文章,讲过PGP一个安全的邮件系统,它有对私钥文件保密的措施,私钥拥有者是用口令来获取私钥文件的,下面讲下它的工作原理:
可以看到,其原理是对口令(口令长度任意)进行Hash,输出长度固定的摘要,作为一个key,对私钥文件进行加密时,加入Key,使用对称加密器,得到加密后的私钥文件。
解密时同样输入一个口令,Hash一下,作为Key进行解密。
Hash函数解决数字签名的问题:
如果直接对明文进行数字签名,如果文件很长,签名的时间会很长。
使用Hash,即使文件很长,Hash后的摘要长度是固定的,签名的时间是个常数,验证签名的时间也是个常数。
签名过程:
验证签名过程: