怎么对一个大的文件进行签名,因为文件比较大,非对称签名很慢。那么想,我能把这个大的文件通过一种函数变换,变成一个和源文件唯一对应的的小的文件吗?答案是可以的。
Hash Function
这里任何的文件都抽象成一个字节流X。
Y就是变换后的结果,他和X有一一对应的关系,也称Y为X的特征码。
f就是一种变换关系,称为Hash Function,这种变换是不可以的,即给定X很容易得到Y;但是给定Y一般无法得到X。
并且这种Hash Function还有一个特性,就是对于输入的X,只要稍微改动,输出的Y就会发生很大的变化。
一旦Hash Function给定,其输出的Y的值的大小就固定了,常见的两种Hash Function分别是MD5和SHA1,他们的产生结果的大小分别为128bit和160bit。
MD5的小插曲
在Hash Function中有个属于叫做collision,冲突或者碰撞。也就是给两个不同的输入,结果输出的值竟然一样,这样的话这个特征码就不能唯一的代表一个东西了。原山东大学的密码学老师王晓云就在理论上证明了MD5的collision的存在,在理论上找到了一种构建冲突的方法,震惊密码学界啊。
Hash Function变换的实验
产生一个文件的MD5的特征码,上面的使用openssl提供的函数。下面的使用Linux自身带的MD5函数。
这样就能产生一个小的,能唯一代表这个文件的特征码。同时只要这个文件有任何的被修改,新的MD5码就会跟原来的产生巨大的变化。
SHA1的函数产生文件的特征码。
提示:
openssl dgst后面跟参数 -c 可以控制特征码的输出的形式,中间冒号隔开。
以openssl这个软件为例,产生他的特征码。这里产生的特征码和在其官方网站上的特征码是一样的,官网给出其特征码的目的也就是防止该安全软件被恶意的修改,防止安全问题出在安全软件本身。
在文件的加密中,有一种应用就是:我发布了一些软件在网站上供大家使用,但是这个文件有可能被黑客恶意的修改,比如所往文件里注入一些木马等病毒。那么用户增么才能有效的辨别呢?就是引入哈希函数。
哈希函数就是一种尽量做到唯一对应的一种映射关系。它的输入是一个大的文件,然后通过函数的映射关系,产生一个有限长度的字符串,这个字符串唯一的对应这个文件。这样的话,用户就能够通过比对软件的发布者公布的文件对应字符串和下载下来的文件对应的字符串来确定这个文件是否被恶意篡改过。
实现这种对应关系,需要复杂的算法支持,常见的算法是MD5和SHA1。
数字签名的完善
首先有一个明文,这个明文可大可小。通过一个Hash Function产生他的特征码,对明文不加密,因为这里是数字签名认证不是加密传输,所以不需要加密明文。
但是我们要对特征码进行签名(私钥加密) ,发送方对特征码签名了,所以他要对特征码的真实性负法律责任,同时特征码和原名文是一一对应的关系,所以发送方也要对明文的真实性负法律责任。但是前提是这个特征码是和明文有对应关系的。
也就是说任何人都可以看可以使用 这个明文,但是不能修改。一旦你修改了,别人也能很容易的看到这个不是原发送方的那个明文了,因为你没有原发送方的私钥,你无法对特征码签名,别人用原发送方的公钥验证的时候很容易就能发现你的明文是被修改过的。
遗留问题
在非对称加密中,我们想给谁发送信息就用谁的公钥加密文件,然后只有我们想要的发送方能解密文件。但是漏洞来了,我们怎么确认自己手里的公钥就是我们心中的数据接收方呢?会不会有个人冒充呢,会不会被钓鱼呢?
比如说我们想给习大大写一封信,然后有个人自称是习大大,然后他给出了自己的公钥(到处散发),我们用公钥加密然后把信息一股脑的都给了这个人。但是万一他不是习大大怎么办,我们的信息就被窃取了。