目录
鉴别(authentication) 是网络安全中一个很重要的问题。
一是要鉴别发信者,即验证通信的对方的确是自己所要通信的对象,而不是其他的冒充者。这就是实体鉴别。实体可以是发信的人,也可以是一个进程(客户端或服务器)。因此这也常称为端点鉴别。
二是要鉴别报文的完整性,即对方所传送的报文没有被他人篡改过。
1、报文鉴别
(1)使用数字签名进行鉴别
我们知道,书信或文件可根据亲笔签名或印章来鉴别其真实性。那么在计算机网络中传送的报文,则可使用数字签名进行鉴别。
为了进行数字签名,A 用其私钥 对报文 X 进行 D 运算。D 运算本来叫作解密运算,可是,还没有加密怎么就进行解密呢?其实 D 运算只是把报文变换为某种不可读的密文(扮演了加密角色)。A 把经过 D 运算得到的密文传送给 B。B 为了核实签名,用 A 的公钥进行 E 运算,还原出明文 X。//数字签名原理,只有私钥持有者才能进行签名
请注意,任何人用 A 的公钥 进行 E 运算后都可以得出 A 发送的明文。可见上述通信方式并非是为了保密,而是为了进行签名和核实签名,即确认此明文的确是 A 发送的。
所以,知道为什么数字签名具有不可否认性了吧?
因为除 A 外没有别人持有 A 的私钥 ,所以除 A 外没有别人能产生密文 。这样,B 确信报文 X 是 A 签名发送的。这就鉴别了报文的发送者。同理,其他人如果篡改过报文,但由于无法得到 A 的私钥 对篡改后的报文进行 D 运算,那么 B 对收到报文后,进行核实签名的 E 运算,将会得出不可读的明文,因而不会被欺骗。这样就保证了报文的完整性。
不过数字签名仅对报文进行了签名,却未对报文 X 本身保密。因为如果有人截获到密文,并知道发送者身份,若通过某种手段获得了发送者的公钥 ,就能解出报文的内容。
那如何才能同时实现保密通信和数字签名呢?
如上图所示,图中 和 分别为 A 和 B 的私钥,而 和 分别为 A 和 B 的公钥。
我们首先用 A 的私钥对明文 X 进行签名,得到 ,然后,再用 B 的公钥对此签名内容进行加密,得到 ,通过这种方式,就同时实现了保密通信和数字签名。
不过,上图所示的方法虽然在理论上是正确的,但很难用于现实生活中。这是因为要对报文(可能很长的报文)先后要进行两次 D 运算和两次 E 运算,这种运算量太大,要花费非常多的 CPU 时间,这在很多情况下是无法令人接受的。//非对称加密的计算量大
因此目前对网络上传送的大量报文,普遍都使用开销小得多的对称密钥加密。要实现数字签名当然必须使用公钥密码,但一定要设法减小公钥密码算法的开销,所以就有了密码散列函数和报文鉴别码。//减少算法开销,提高加密性能
(2)密码散列函数
散列函数(又称为杂凑函数,或哈希函数)在计算机领域中使用得很广泛。密码学对散列函数有非常高的要求,因此符合密码学要求的散列函数又常称为 密码散列函数(cryptographic hash function)。
散列函数 H(X) 一般具有以下四个特点:
(1)散列函数采用确定算法,因此相同的输入必定得出相同的输出。
(2)散列函数的输出不可避免的会产生碰撞现象。因此,精心挑选的密码散列函数应当非常不易发生碰撞,即应具有很好的抗碰撞性。//Hash冲突
(3)若给出散列值 H(X),则无人能找出输入的报文 X。也就是说,散列函数是一种单向函数(one-way function),即逆向变换是不可能的。//不可逆
(4)散列函数输出的每一个比特,都与输入的每一个比特有关;哪怕仅改动输入的一个比特,输出也会相差极大。
目前,比较出名的密码散列函数有 MD5 和 SHA-1。MD 就是 Message Digest 的缩写,意思是报文摘要,MD5 就是指报文摘要的第 5 个版本。不过随着技术的发展,MD5 的安全性产生了动摇,于是 MD5 最终被 安全散列算法SHA(Secure Hash Algorithm) 的标准所取代。//散列函数的历史
MD5 算法的大致过程如下:
- 先把任意长的报文按模 计算其余数(64位),追加在报文的后面。
- 在报文和余数之间填充 1~512 位,使得填充后的总长度是 512 的整数倍。填充的首位是 1,后面都是 0。
- 把追加和填充后的报文分割为许多 512 位的数据块,每个 512 位的报文数据再分成 4 个 128 位的数据块依次送到不同的散列函数进行 4 轮计算。每一轮又都按 32 位的小数据块进行复杂的运算。一直到最后计算出 MD5 报文摘要代码(128位)。
这样得出的 MD5 报文摘要代码中的每一位都与原来报文中的每一位有关。由此可见,像 MD5 这样的密码散列函数实际上已是个相当复杂的算法,而不是简单的函数了。
(3)报文鉴别码
使用报文鉴别码对报文进行鉴别的一般步骤:
- 用户 A 首先根据自己的明文 X 计算出散列 H(X)(例如,使用 MD5)。为简单起见,我们把得出的散列 H(X) 记为 H。//在明文后加散列值,确保内容不被更改
- 用户 A 把散列 H 拼接在明文 X 的后面,生成了扩展的报文 (X, H),然后发送给 B。
- 用户 B 收到了这个扩展的报文 (X,H)。因为散列的长度 H 是早已知道的固定值,因此很容易把收到的散列 H 和明文 X 分离开。B 通过散列函数的运算,计算出所收到的明文 X 的散列 H(X)。若 H(X) = H,则 B 就认为所收到的明文是 A 发送过来的。//一旦内容更改,散列值就对不上
但是,以上步骤有一个问题,如果某个入侵者创建了一个伪造的报文 M,然后也用同样的方法计算出其散列 H(M),并且冒充 A 把拼接有散列的扩展报文发送给 B。B 收到扩展的报文 (M,H(M)) 后,按照上面步骤的方法进行验证,发现一切都是正常的,就会误认为所收到的伪造报文就是 A 发送的。//也就是说,不改变部分报文,而是篡改整个报文,上述步骤就验不出来了,缺点就在于简单的散列并没有加入用户A的特有标记
那如何解决伪造整段报文的问题呢?
那就是给每一个报文都打上 A 特有的标记,办法可以是:A 把双方共享的密钥 K(K就是一串不太长的字符串)拼接到报文 X 后,进行散列运算。散列运算得出的结果为固定长度的 H(X+K),称为 报文鉴别码 MAC (Message Authentication Code)。A 把报文鉴别码 MAC 拼接在报文 X 后面,得到扩展的报文,发送给 B,如下图所示://加入A的密钥K进行散列
B 收到扩展的报文后,把报文鉴别码 MAC 与报文 X 进行分离。B 再用同样的密钥 K 与报文 X 拼接,进行散列运算,把得出的结果 H(X+K) 与分离出的报文鉴别码 MAC 进行比较。如相等,就可确认收到的报文 X 的确是 A 发送的。
所以,只要入侵者不掌握密钥 K,就无法伪造 A 的报文鉴别码 MAC,因而无法伪造 A 发送的报文。像这样的报文鉴别码称为数字签名,或数字指纹。
但是,又怎样安全有效的来分发通信双方共享的密钥 K 呢?
一种可行的方法是采用公钥系统,具体方式如下图所示:
用户 A 对报文 X 进行散列运算,得出固定长度的散列 H(X)。用自己的私钥对 H(X) 进行 D 运算(也就是用私钥进行加密),得出已签名的但非固定长度的报文鉴别码 MAC。
请注意,这里没有对报文 X 进行加密,而是对很短的散列 H(X) 进行 D 运算,因此这种运算仍然是很快的。A 把已签名的非固定长度的报文鉴别码 MAC,拼接在报文 X 后面,构成扩展的报文发送给 B。//原理:A用自己的私钥进行签名,B用A的公钥进行鉴别
B 收到扩展的报文后,先进行报文分离。虽然 B 不知道已签名的报文鉴别码的长度,但由于报文 X 是明文,其结束处可以设有标记,因此分离出 MAC 不困难。分离后,B 对报文 X 进行散列函数运算,同时用 A 的公钥对分离出的已签名的报文鉴别码 MAC 进行 E 运算(也就是用公钥进行解密)。最后对这两个运算结果 H(X) 进行比较。如相等,就说明一切正确。由于入侵者没有 A 的私钥,因此不可能伪造出 A 发出的报文。
所以,采用这种方法得到的扩展的报文,不仅是不可伪造的,也是不可否认的。
2、实体鉴别
实体鉴别和报文鉴别不同。报文鉴别是对每一个收到的报文都要鉴别报文的发送者,而实体鉴别是在系统接入的全部持续时间内对和自己通信的对方实体只需验证一次。//需要验证的次数不一样
简单的实体鉴别过程:
如下图,A 向远端的 B 发送带有自己身份(例如,A 的姓名)和口令的报文,并且使用双方约定好的共享对称密钥 进行加密。B 收到此报文后,用共享对称密钥 进行解密,从而鉴别实体 A 的身份。//给出系统的身份验证信息
那么问题来了,例如,入侵者 C 可以从网络上截获 A 发给 B 的报文,C 并不需要破译这个报文(因为破译可能很费时间),而是直接把这个由 A 加密的报文发送给 B,使 B 误认为 C 就是 A;然后 B 就向伪装成 A 的 C 发送许多本来应当发给 A 的报文。这就叫作重放攻击(replay attack)。C 甚至还可以截获 A 的 IP 地址,然后把 A 的 IP 地址冒充为自己的 IP 地址(这叫作 IP欺骗),使 B 更加容易受骗。//通信实体被中途替换了
那么如何应对,重放攻击呢?
为了对付重放攻击,可以使用 不重数(nonce)。不重数就是一个不重复使用的大随机数,即“一次一数”。在鉴别过程中不重数可以使 B 能够把重复的鉴别请求和新的鉴别请求区分开。
在上图中,A 首先用明文发送其身份 A 和一个不重数 给 B。接着,B 响应 A 的查问,用共享的密钥 对 加密后发回给 A,同时也给出了自己的不重数 。最后,A 再响应 B 的查问,用共享的密钥 对 加密后发回给 B。这里很重要的一点是 A 和 B 对不同的会话必须使用不同的不重数集。由于不重数不能重复使用,所以 C 在进行重放攻击时无法重复使用所截获的不重数。//即使C截获了之前的通信内容,也无法直接将其重放来冒充合法用户,所以,不重数的主要作用是使重放记录无法通过完整性检查
在使用公钥密码体制时,可以对不重数进行签名鉴别。例如,B 用其私钥对不重数 进行签名后发回给 A。A 用 B 的公钥核实签名,如能得出自己原来发送的不重数 ,就核实了和自己通信的对方的确是 B。同样,A 也用自己的私钥对不重数 进行签名后发送给 B。B 用 A 的公钥核实签名,鉴别了 A 的身份。//保证不重数不被篡改
至此,全文结束。