8.4 验证密钥
当Bob收到密钥时,他如何知道这是Alice传送的而不是其他人伪装Alice传送的呢?如果是Alice亲自递给他的,那自然简单;如果Alice通过可靠的信使传送密钥,Bob必须相信信使;如果密钥由密钥加密密钥加密, Bob必须相信只有Alice才拥有那个加密密钥;如果Alice运用数字签名协议来给密钥签名,那么当Bob验证签名时就必须相信公开密钥数据库;如果某个密钥分配中心(KDC)在Alice的公钥上签名,Bob必须相信KDC的公开密钥副本不曾被窜改过。
结果,控制了Bob周围整个网络的人都能够使Bob认为控制者想干什么。Mallory可以传送一个加密和签名的消息而将它伪装成来自Alice,当Bob试图访问公钥数据库以验证Alice的签名时,Mallory可以用他自己的公钥来代替。他可以发明自己的假KDC,并把真正的KDC公钥换成她自己产生的公钥。Bob不会察觉。
利用该缺陷的一些人声称公钥密码体制是无用的。既然Alice与Bob保证他们密钥不被窜改的唯一方式是面对面交换,公钥体制对提高安全性一点用处也没有。
这种观点是幼稚的。理论上这种说法是错误的,但实际情况却复杂得多。采用数字签名和可信赖KDC的公钥体制,使得一个密钥代替另一个密钥变得非常困难,Bob从来都不能绝对肯定Mallory没有控制他的整个网络,但他相信那样做需要比Mallory能够访问到的大多数资源还要多。
Bob可以通过电话核实Alice的密钥,那样他可以听到她的声音。声音辨别是一个真正的好的鉴别方案。如果这是一个公钥,他可以当着大家的面通过电话安全的背诵出来。如果是一个秘密密钥,他就用一个单向Hash函数来核实密钥。PGP(参见24.12节)和AT&T TSD(参见24.18节)就是用这种方法对密钥进行验证的。
有时,核实一个公开密钥到底属于谁并不重要,核实它是否属于去年的同一个人或许是有必要的。如果某人送了一个签名提款的信息到银行,银行并不关心到底谁来提款,它仅关心是否与第一次来存款的人属同一个人。
密钥传输中的错误检测
有时密钥在传输中会发生错误。密钥错误就意味着大量的密文无法解密,所以这是个问题。所有的密钥必须附着一些检错和纠错位来传输。这样,密钥在传输中的错误很容易地被检查出来,并且如果需要,密钥可被重传。
最广泛采用的一种方法是用密钥加密一个常量,然后把密文的前2-4字节与密钥一起发送。在接收端,做同样的工作,如果接收端加密后的常数能与发端常数匹配,则传输无错。检查不出错误的机会是2-16到2-32之间。
密钥在解密过程中的错误检测
有时收方想检查他拥有的某个密钥是否是正确的对称解密密钥。如果明文与ASCII码类似,他就试着去解密,并阅读验证它,如果得到的明文是随机的,那么密钥就有问题。
最简单的方法是附加一个验证分组:加密之前给明文加一个已知的报头。在接收端,Bob解密报头,并验证它的正确性。这是可行的,但是它却给Eve提供了已知的明文来帮助分析密码系统。它也使得对DES这样的短密钥密文和对所有可出口的密码攻击变得容易。一旦对每个密钥的校验和进行了预计算,就可以用它来确定之后截取到的任何信息的密钥。这就是校验和的特性,它不包含随机的数据,至少在每一个校验和中没有随机的数据。当利用通行短语生成密钥时,它在概念上类似于使用 “salt”。
下面是更好的方法[821]:
(1)产生一个初始化向量IV(不用于消息)。
(2)用该初始化向量IV生成一个大的比特块:譬如,512比特。
(3)进行单向Hash运算
(4)使用Hash运算结果的相同固定位置上的比特位(如32比特)作为密钥校验和。
这种方法不可避免地给Eve提供一些信息,但非常少。如果她试图利用最后Hash值的低32比特采取穷举攻击的话,她必须进行多重加密并对每一个候选密钥作Hash运算;对密钥本身进行穷举攻击将更迅速。
再者,她也得不到更多的已知明文信息以供攻击,如果她能设法选择我们的随机值,那她永远也得不到我们的明文,因为它已经在她看到之前被Hash运算了。