密钥 —— 秘密的精华

在密码技术中,密钥扮演着十分重要的角色。如果窃听者能够获得用于解密的密钥,则密文的机密性就无法得到保证;如果攻击者能够获得用于数字签名的私钥,就可以发动伪装攻击。



密钥的分类
密钥其实分为很多种类,下面来整理一下。

对称密码的密钥与公钥密码的密钥
对称密码中,加密和解密使用同一个密钥。由于发送者和接收者之间需要共享密钥,因此对称密码又称为共享密钥密码。对称密码中所使用的密钥必须对发送者和接收者以外的人保密, 否则第三方就能够解密密文了。

公钥密码中,加密和解密使用的是不同的密钥。用于加密的密钥称为公钥,顾名思义它是可以被公开的;用于解密的密钥称为私钥,只有需要进行解密的接收者才持有私钥, 私钥也称为秘密密钥。相对应的公钥和私钥之间具有深刻的数学关系,因此也称为密钥对

消息认证码的密钥与数字签名的密钥
消息认证码中,发送者和接收者使用共享的密钥来进行认证。消息认证码只能由持有合法密钥的人计算出来。将消息认证码附加在通信报文后面,就可以识别通信内容是否被篡改或伪装。 由于“持有合法的密钥”就是发送者和接收者合法身份的证明,因此消息认证码的密钥必须对发送者和接收者以外的人保密,否则就会产生篡改和伪装的风险。

数字签名中,签名的生成和验证使用不同的密钥。只有持有私钥的本人才能够生成签名,但由于验证签名使用的是公钥, 因此任何人都能够验证签名。

用于确保机密性的密钥与用于认证的密钥
对称密码和公钥密码的密钥都是用于确保机密性的密钥。如果不知道用于解密的合法密钥,就无法得知明文的内容。

相对地,消息认证码和数字签名所使用的密钥,则是用于认证的密钥。如果不知道合法的密钥,就无法篡改数据,也无法伪装本人的身份。

会话密钥与主密钥
刚刚我们关注的是密钥的用途,下面我们来关注一下密钥被使用的次数。

当我们访问以 https:// 开头的网页时,Web 服务器和浏览器之间会进行基于 SSL/TLS 的加密通信。在这样的通信中所使用的密钥是仅限于本次通信的一次性密钥,下次通信时就不能使用了。 像这样每次通信只能使用一次的密钥称为会话密钥(session key)

只能一次性使用的密钥有哪些好处呢?由于会话密钥只在本次通信中有效,万一窃听者获取了本次通信的会话密钥,也只能破译本次通信的内容。由于在下次通信中会使用新的密钥,因此其他通信的机密性不会受到破坏。

虽然每次通信都会更换会话密钥,但如果用来生成密钥的伪随机数生成器品质不好,窃听者就有可能预测出下次生成的会话密钥,这样就会产生通信内容被破译的风险。

相对于每次通信都史换的会话密钥,一直被重复使用的密钥称为主密钥(master key)

用于加密内容的密钥与用于加密密钥的密钥
下面我们来关注一下使用密钥加密的对象。

一般来说,加密的对象是用户直接使用的信息(内容 ),这样的情况下所使用的密钥称为 CEK(Contents Encrypting Key, 内容加密密钥);相对地,用于加密密钥的密钥则称为 KEK(Key Encrypting Key,密钥加密密钥)。 下图展示了 CEK 和 KEK 的一种用法。


密钥的管理

生成密钥
用随机数生成密钥
生成密钥的最好方法就是使用随机数,因为密钥需要具备不易被他人推测的性质,详情请见:随机数介绍

用口令生成密钥
有时我们也会使用人类可以记住的口令(password 或 passphrase)。严格来说,我们很少直接用口令来作为密钥使用,一般都是将口令输人单向散列函数,然后将得到的散列值作为密钥使用。

在使用口令生成密钥时,为了防止字典攻击,需要在口令上面附加一串称的随机数,然后再将其输人单向散列函数。这种方法称为“基于口令的密码”(Password Based Encryption, PBE), 详情请见:口令

配送密钥
在使用对称密码时,如何在发送者和接收者之间共享密钥是一个重要的问题(即密钥配送问题)。要解决密钥配送问题,可以采用事先共享密钥、使用密钥分配中心、使用公钥密码等方法。 除上述方法之外,还有一种解决密钥配送问题的方法称为 Diffie-Hellman 密钥交换,详情请见:Diffie-Hellman 密钥交换

更新密钥
有一种提高通信机密性的技术被称为密钥更新(key updating), 这种方法就是在使用共享密钥进行通信的过程中,定期(例如每发送 1000 个字)改变密钥。当然,发送者和接收者必须同时用同样的方法来改变密钥才行。

在更新密钥时,发送者和接收者使用单向散列函数计算当前密钥的散列值,并将这个散列值用作新的密钥。简单说,就是用当前密钥的散列值作为下一个密钥

进行密钥更新有哪些好处呢?我们假设在通信过程中的某个时间点上,密钥被窃听者获取了,那么窃听者就可以用这个密钥将之后的通信内容全部解密。但是,窃听者却无法解密更新密钥这个时间点之前的通信内容, 因为这需要用单向散列函数的输出(即当前密钥 )反算出单向散列函数的输人(即上一个密钥)。由于单向散列函数具有单向性,因此就保证了这样的反算是非常困难的。

这种防止破译过去的通信内容的机制,称为后向安全(backward security)

保存密钥
由于会话密钥在通信过程中仅限使用一次,因此我们不需要保存这种密钥。然而,当密钥需要重复使用时,就必须要考虑保存密钥的问题了。

人类无法记住密钥
人类是无法记住具有实用长度的密钥的,例如,像下面这样一个 AES 的 128 比特密钥,一般人是很难记住的。

    81 EC 4B 53 49 D3 AF 66 63 4F 5D A6 E1 C4 EC 88

就算咬咬牙勉强记住了,也只不过是记住了一个密钥而已。但如果要自如地记住多个密钥并且保证不忘记,实际上是不可能做到的。

对密钥加密的意义
我们记不住密钥,但如果将密钥保存下来又可能会被窃取。我们可以使用将密钥加密后保存的方法。当然,要将密钥加密,必然需要另一个密钥。像这样用于加密密钥的密钥,一般称为 KEK

既然加密密钥需要另一个密钥(KEK),那么另一个密钥(KEK)又要如何保存呢?对密钥进行加密的方法虽然没有完全解决机密性的问题,但在现实中却是一个非常有效的方法,因为这样做可以减少需要保管的密钥数量。

举个例子,假设计算机上有 100 万个文件,分别使用不同的密钥进行加密生成 100 万个密文,结果我们手上就产生了 100 万个密钥,而要保管 100 万个密钥是很困难的。于是,我们用一个密钥(KEK)将这 100 万个密钥进行加密, 那么现在我们只要保管这一个 KEK 就可以了。不过不要忘记,这一个 KEK 的价值相当于前面 100 万个密钥的价值的总和。

作废密钥
为什么要作废密钥
举个例子,假设帕蒂向鲍勃发送了一封加密的邮件。鲍勃在解密之后阅读了邮件的内容,这时本次通信所使用的密钥对于帕蒂和鲍勃来说就不再需要了。不再需要的密钥必须妥善删除,因为如果被窃听者获取,之前发送的加密邮件就会被解密。

如何作废密钥
如果密钥是计算机上的一个文件,那么仅仅删除这个文件是不足以删除密钥的,因为有一些技术能够让删除的文件 “复活”。此外,很多情况下文件的内容还会残留在计算机的内存中,因此必须将这些痕迹完全抹去。简而言之,要完全删除密钥, 不但要用到密码软件,还需要在设计计算机系统时对信息安全进行充分的考虑。

密钥丢了怎么办
如果丢失了对称密码的共享密钥,就无法解密密文了。如果丢失了消息认证码的秘钥,就无法向通信对象证明自己的身份了。

公钥密码中,一般不太会发生丢失公钥的情况,因为公钥是完全公开的,很有可能在其他电脑上存在副本。最大的问题是丢失了公钥密码的私钥。如果丢失了公钥密码的私钥,就无法解密用公钥密码加密的密文了。 此外,如果丢失了数字签名的私钥,就无法生成数字签名了。
+