目录
13.7.4场景3:通过自己有限信任的多个人的数字签名进行确认
第十三章
无论出于何种目的,你都不希望自己的私密电子邮件和机密文件被别人读取。主张自己的隐私永远没错。--节选自菲利普·季默曼《PGP用户手册》
13.1 本章学习的内容
本章中,我们将以密码软件PGP ( Pretty Good Privacy)为题材,思考一下将前面章节中学习的密码技术进行组合的方法。
本章的讲解将按照下列顺序进行。
⚪PGP 简介
⚪生成密钥对
⚪加密与解密
⚪生成和验证数字签名
⚪“生成数字签名并加密”以及“解密并验证数字签名”
⚪信任网
本章中会出现大量的图示,图示中出现的密码技术基本上都是我们之前已经介绍过的,希望大家注意观察各种密码技术是如何组合在一起的。
此外,在本章的最后,我们还将介绍PGP中用于确认公钥合法性的信任网方法。
13.2 PGP 简介
13.2.1 什么是 PGP
PGP 是于1990年左右由菲利普·季默曼(Philip Zimmermann)个人编写的密码软件,现在依然在世界上被广泛使用。PGP这个名字是 Pretty Good Privary(很好的隐私)的缩写。
你有没有过发送“性命攸关”的邮件的经历呢?自己发送的邮件如果能够平安到达指定的接收者就能活命,相反,如果万一被人窃听到就没命了。出于政治等原因,世界上有很多人都处于这样一种状况之中,而 PGP 就是为了保护处于这样极端状况下的人们的隐私而开发的密码软件。PGP 的历史可谓是一波三折,让人感觉像是在读一部谍战小说。如果想了解 PGP 幕后的故事,可以读一读 Garfinkel 所著的 PGP: Pretty Good Privacy一书。
PGP 可以在 Windows、Mac OS X、Linux 等很多平台上运行,版本包括商用版和免费版。此外还有一个由GNU遵照OpenGPG ( RFC4880 )规范编写的叫作GnuPG (GNU PrivacyGuard)的自由软件。关于GnuPG我们将在下一节详细介绍。
本章的内容主要是根据 PGP Command Line User's Guide 10.3 以及 GnuPG 2.1.4 的内容编写的。在详细功能以及所支持的算法方面,PGP 和 GnuPG 有所区别,而且不同的版本之间也会有所不同,本章中的介绍统一以PGP为准。
13.2.2 关于 OpenPGP
OpenPGP是对密文和数字签名格式进行定义的标准规格(RFC1991、RFC2440、RFC4880、RFC5581、RFC6637)。
1996年的RFC1991中对PGP的消息格式进行了定义。2007年的RFC4880中新增了对RSA和DSA的支持。2012年的RFC6637中新增了对椭圆曲线密码(ECC)的支持,并且还支持基于Curve P-256, P-384和P-521三种椭圆曲线的椭圆曲线DSA (Elliptic Curve DigitalSignature Algorithm, ECDSA)和椭圆曲线Diffie-Hellman密钥交换( Elliptic Curve DiffieHellman, ECDH)。
RFC6637中新增了用于比较密码学强度的平衡性的对照表。由这张表可知,例如当我们选用256比特的椭圆曲线密码算法时,相应地应该选用256比特的散列算法以及密钥长度为128比特的对称密码算法。
13.2.3关于GNU Privacy Guard
GNU Privacy Guard ( GnuPG、 GPG )是一款基于OpenPGP 标准开发的密码学软件①,支持加密、数字签名、密钥管理、S/MIME、ssh等多种功能。GnuPG是基于GNU GPL协议发布的一款自由软件,因此任何人都可以自由使用它。GnuPG 本身是一款命令行工具,但它也经常被集成到其他应用软件中。
GnuPG 分为 stable、modern 和 classic 三个系列。
⚪GnuPG stable的版本号为2.0.x,支持OpenPGP, S/MIME和ssh
⚪GnuPG modern的版本号为2.1.x,在stable的基础上增加了对椭圆曲线密码的支持。
⚪GnuPG modern是比较新的版本,今后将会逐渐取代现在的GnuPG stable版本GnuPG classic的版本号为1.4.x,是比较旧的版本
13.2.4 PGP 的功能
PGP 具备现代密码软件所必需的几乎全部功能,下面我们来列举一些,如下所示。对称密码PGP支持用对称密码进行加密和解密。对称密码可以单独使用,也可以和公钥密码组合成混合密码系统(第6章)使用。
可以使用的对称密码算法包括AES、IDEA、CAST、三重DES、Blowfish、Twofish、Camellia 等。
公钥密码
PGP 支持生成公钥密码的密钥对,以及用公钥密码进行加密和解密。实际上并不是使用公钥密码直接对明文进行加密,而是使用混合密码系统来进行加密操作。可以使用的公钥密码算法包括RSA和ElGamal等。数字签名PGP 支持数字签名的生成和验证,也可以将数字签名附加到文件中,或者从文件中分离出数字签名。
可以使用的数字签名算法包括RSA、 DSA、 ECDSA (椭圆曲线DSA)、EdDSA (爱德华兹曲线 DSA)等。
数字签名
PGP支持数字签名的生成和验证,也可以将数字签名附加到文件中,或者从文件中分离出数字签名。
可以使用的数字签名算法包括RSA, DSA, ECDSA (椭圆曲线DSA), EdDSA (爱德华兹曲线 DSA)等。
单向散列函数
PGP可以用单向散列函数计算和显示消息的散列值。可以使用的单向散列函数算法包括SHA-1、SHA-224、 SHA-256, SHA-384、 SHA-512和RIPEMD-160 等。MD5也依然可以使用,但并不推荐。
证书
PGP可以生成OpenGPG中规定格式的证书,以及与X.509规范兼容的证书。此外,还可以颁发公钥的作废证明( revocation certificate ),并可以使用CRL和OSCP对证书进行校验。
压缩
PGP支持数据的压缩和解压缩,压缩采用ZIP、ZLIB、BZIPZ等格式。
文本数据
PGP 可以将二进制数据和文本数据相互转换。例如,当不得不使用某些无法处理二进制数据据的软件进行通信时,可以将二进制数据转换成文本数据(ASCII radix-64格式),这些软件就能够进行处理了。
radix-64 格式是在邮件等场合中经常使用的 base64 编码的基础上,增加了检测数据错误的校验和的版本。base64编码是一种可以将任何二进制数据都用A~Z、a~z、0~9、+、/共64个字符再加上=(用于末尾填充)来表示的格式。
大文件的拆分和拼合
在文件过大无法通过邮件发送的情况下, PGP可以将一个大文件拆分成多个文件,反过来也可以将多个文件拼合成一个文件。钥匙串管理PGP可以管理所生成的密钥对以及从外部获取的公钥。用于管理密钥的文件称为钥匙串(key ring)。
13.3 生成密钥对
要在 PGP 中进行加密和数字签名,需要先生成自己的密钥对。图 13-1 展示了用 GnuPG2.1.4 从命令行生成密钥对的过程。
接下来我们不会讲解 PGP 的使用方法,而是介绍一下 PGP 内部的处理流程。关于 PGP 的具体使用方法,可参考PGP的相关文档。
13.4 加密与解密
13.4.1 加密
PGP 的加密过程如图 13-4 所示。在这张图中,消息经过混合密码系统进行加密,然后转换成报文数据(文本数据)。
这里的内容和第 6章的混合密码系统的结构基本上是一样的,差异在于这里还包括了消息的压缩以及二进制→文本转换(转换为ASCII radix-64 格式)这两个步骤。
生成和加密会话密钥
(1)用伪随机数生成器生成会话密钥。
(2)用公钥密码加密会话密钥,这里使用的密钥是接收者的公钥。
压缩和加密消息
(3) 压缩消息。
(4)使用对称密码对压缩的消息进行加密,这里使用的密钥是步骤(1)中生成的会话密钥。
(5)将加密的会话密钥(步骤(2))与加密的消息(步骤(4))拼合起来。
(6)将步骤(5)的结果转换为文本数据,转换后的结果就是报文数据。
正如下图所示,用公钥密码加密会话密钥,用对称密码加密消息就是混合密码系统的特点。
13.4.2 解密
PGP 的解密过程如图 13-5所示。这张图展示了接受者在收到上一节中生成的报文数据之后,得到原始消息的过程。
解密私钥
PGP 的私钥是保存在用户的钥匙串中的。为了防止钥匙串被盗,私钥都是以加密状态保存的,并在保存时使用了基于口令的密码(PBE)(11.6节)。口令是由多个单词组成的短语,没有正确的口令就无法使用相应的私钥。如果攻击者想要使用你的私钥,就必须先窃取保存私钥的钥匙串,然后再破译加密私钥的密码。
解密私钥的步骤如下。
(1)接收者输入解密的口令。
(2)求口令的散列值,生成用于解密私钥的密钥。
(3)将钥匙串中经过加密的私钥进行解密。解密会话密钥
(4)将报文数据(文本数据)转换成二进制数据。
(5)将二进制数据分解成两部分:加密的会话密钥、经过压缩和加密的消息。
(6)用公钥密码解密会话密钥,这里使用步骤(3)中生成的接收者的私钥。解密和解压缩消息
(7)对步骤(5)中得到的经过压缩和加密的消息用对称密码进行解密。这里使用步骤(6)中生成的会话密钥。
(8)对步骤(7)中得到的经过压缩的消息进行解压缩。
(9) 得到原始消息。图13-6展示了在加密和解密的过程中,会话密钥和消息经过了怎样的变化。
上面我们介绍了 PGP的加密和解密过程,尽管有点复杂,但是只要理解了混合密码系统的结构,应该还是可以看懂的。
小测验 1 压缩和加密的顺序 (答案见 13.9 节)
从图 13-4中可以看出,消息是先进行压缩然后再加密的,为什么一定要按照压缩→加密这样的顺序来处理呢?
13.5 生成和验证数字签名
下面我们来看看生成和验证数字签名的过程。看起来有点复杂,大家要努力读懂哦。有必要的话,重新复习一下第9章的内容可能会有所帮助。
13.5.1 生成数字签名
图 13-7 展示了 PGP中生成数字签名的过程。在这张图中,消息与相对应的签名进行拼合,并最终转换成报文数据(文本数据)。顺便提一下,对于是否要将报文数据转换成文本数据,在PGP 中是可以选择的。
解密私钥
在钥匙串中,私钥是通过口令进行加密保存的,因此不知道口令的人就无法使用相应的私钥。
(1) 发送者输入签名用的口令。
(2)求口令的散列值,生成用于解密私钥的密钥。
(3)将钥匙串中经过加密的私钥进行解密。
生成数字签名
(4)用单向散列函数计算消息的散列值。
(5)对步骤(4)中得到的散列值进行签名。这一步相当于使用步骤(3)中得到的私钥进行加密。
(6)将步骤(5)中生成的数字签名与消息进行拼合。
(7)将步骤(6)的结果进行压缩。
(8)将步骤(7)的结果转换为文本数据。
(9)步骤(8)的结果就是报文数据。
13.5.2 验证数字签名
图 13-8 展示了用 PGP 验证数字签名的过程,即接收者在接收到上一节中生成的报文数据后,得到原始消息并验证数字签名的过程。
恢复发送者发送的散列值
(1)将报文数据(文本数据)转换为二进制数据。
(2)对经过压缩的数据进行解压缩。
(3)将解压缩后的数据分解成经过签名的散列值和消息两部分。
(4)将经过签名的散列值(经过加密的散列值)用发送者的公钥进行解密,恢复出发送者发送的散列值。对比散列值
(5)将步骤(3)中分解出的消息输入单向散列函数计算散列值。
(6)将步骤(4)中得到的散列值与步骤(5)中得到的散列值进行对比。
(7)如果步骤(6)的结果相等则数字签名验证成功,不相等则验证失败。这就是数字签名的验证结果。
(8)步骤(3)中分解出的消息就是发送者发送的消息。
图13-9展示了在生成和验证数字签名的过程中,散列值和消息经过了怎样的变化。
上面就是使用PGP生成和验证数字签名的过程。
13.6 生成数字签名并加密以及解密并验证数字签名
最后,我们来看一下如何将密码和数字签名进行组合。本节中的图示是整本书中最复杂的,但它只不过是将之前讲解的内容组合起来了而已。
13.6.1 生成数字签名并加密
用PGP 生成数字签名并加密的过程如图 13-10 所示,图中展示了对消息生成数字签名以及对消息进行压缩和加密这两个过程,并将两者的结果拼合在一起形成了报文数据(文本数据)。对于是否要将报文数据转换成文本数据,在 PGP 中是可以选择的。
生成数字签名
生成数字签名的过程和 13.5.1 节中介绍的步骤是相同的。
加密
加密的过程和 13.4.1 节中介绍的步骤是相同的。不过,这里的加密对象并不仅仅是消息本身,而是将数字签名和消息拼合之后的数据。
13.6.2 解密并验证数字签名
用 PGP 解密并验证数字签名的过程如图 13-11 所示,图中展示了对接收到的报文数据进行解密和解压缩,并对所得到的消息验证数字签名这两个过程。最终得到的结果包括消息本身以及对数字签名的验证结果。
解密
解密的过程和 13.4.2 节中介绍的步骤是相同的。不过,这里解密所得到的并不仅仅是消息本身,而是将数字签名和消息拼合之后的数据。
验证数字签名
验证数字签名的过程和 13.5.2 节中介绍的步骤是相同的。图 13-12展示了在“生成数字签名并加密”和“解密并验证数字签名”这一连串的过程中,散列值、会话密钥和消息分别经过了怎样的变化。
13.7信任网
本节中,我们将介绍PGP所采用的一种确认公钥合法性的方法——信任网。
13.7.1 公钥合法性
在使用PGP时,确认自己所得到的公钥是否真的属于正确的人(公钥合法性)是非常重要的,因为公钥可能会通过中间人攻击被替换(参见5.7.4节)。
第 10 章中介绍的证书就是确认公钥合法性的方法之一。证书就是由认证机构对公钥所施加的数字签名,通过验证这个数字签名就可以确认公钥合法性。
然而,PGP中却没有使用认证机构,而是采用了一种叫作信任网(web of trust)的方法。在这种方法中,PGP 用户会互相对对方的公钥进行数字签名。
信任网的要点是“不依赖认证机构,而是建立每个人之间的信任关系”。换言之,就是能够自己决定要信任哪些公钥。
下面的几节中,我们将通过下列3个场景,来介绍一下PGP的信任网是如何建立起来的。
场景 1:通过自己的数字签名进行确认
场景 2:通过自己完全信任的人的数字签名进行确认
场景3:通过自己有限信任的多个人的数字签名进行确认
当然,这里所介绍的只是一个概况,关于详细内容请参见PGP 的用户手册。
13.7.2 场景1:通过自己的数字签名进行确认
Alice 和 Bob 约会,在告别的时候,Bob 给了 Alice 一张存储卡,并说“这是我的公钥”。
Alice 回到家里,从存储卡中取出 Bob 的公钥,并存放到自己所使用的PGP 的公钥串中(导入公钥)。由于 Alice 确信刚刚导入的公钥确实是属于 Bob 本人的,因此 Alice 对这个公钥加上了自己的数字签名。
对 Bob 的公钥加上数字签名,就相当于 Alice 声明“这个公钥属于 Bob 本人(即这个公钥是合法的)”。
随后,Alice 收到了来自 Bob 的邮件,由于这封邮件带有 Bob 的数字签名,因此 Alice 想用GPG来验证 Bob的数字签名。PGP将执行下面这些操作:
(1)为了验证 Bob 的数字签名,PGP 需要从 Alice 的公钥串中寻找 Bob 的公钥。
(2) Alice 的公钥串中包含Bob的公钥,因为前几天约会之后Alice 导入了Bob 的公钥。
(3) PGP发现Bob的公钥带有Alice的数字签名,这是因为前几天约会之后Alice对Bob的公钥加上了数字签名。
(4)为了验证Alice的数字签名,PGP需要从Alice的公钥串中寻找Alice自己的公钥。
(5)当然,Alice的公钥串中也包含Alice自己的公钥。
(6) PGP使用Alice的公钥对Bob的公钥上的Alice的数字签名进行验证。如果验证成功,则可以确认这的确就是 Bob 的公钥。
(7) PGP 使用合法的 Bob 的公钥对邮件上附带的Bob 的数字签名进行验证。
通过上述步骤,就完成了对 Bob 的数字签名的验证,Alice 确认这封邮件就是前几天和她约会的 Bob 所发送的,她终于可以放心了。
小测验 2 确认公钥合法性的手段 (答案见 13.9 节)
Alice有一个好朋友叫Elma,两人经常煲电话粥。有一天,她收到了一封来自Elma的邮件,里面说“这是我的公钥”,并附带了一个公钥。
Alice考虑到这封邮件可能经过了主动攻击者 Mallory 的篡改,于是她打算给 Elma 打电话以便确认自己所收到的公钥是否来自Elma本人。
可是,由于收到的公钥文件太大,不可能一个字节一个字节地通过电话来口头确认,这可怎么办呢?
13.7.3场景2:通过自己完全信任的人的数字签名进行确认
Alice 有一个叫 Trent 的男朋友。在 Alice 的公钥串中,也包含带有 Alice 的数字签名的Trent 的公钥。
Alice 非常信任 Trent,她想:“Trent很了解密码和数字签名,也了解对公钥施加自己的数字签名所代表的意义,因此经过他签名的公钥一定是合法的。”
使用PGP可以表现Alice对 Trent的信任程度,也就是说, Alice 可以对Trent的公钥设置“我完全信任Trent的数字签名”这一状态,并加上自己的数字签名。
在 PGP 中,用户可以设置对每个公钥所有者的所有者信任(owner trust)级别(参见表 13-2)。Alice 将对 Trent 的所有者信任级别设置为“完全信任”(Fully trusted)。
我们假设这次 Alice 收到了一封来自 Carrol 的邮件,这封邮件中带有 Carrol 的公钥,而且这个公钥上带有 Trent 的数字签名。当 Alice将 Carrol的公钥导入自己的公钥串时,Alice 的PGP 会认为Carrol 的公钥是合法的,因为 Carrol 的公钥上带有 Alice“完全信任”的Trent 的数字签名。
在这个场景中,Trent 对于 Alice 来说是可信的“介绍人”。Trent 对 Carrol 的公钥加上数字签名,就相当于Trent写了一封“介绍信”。
13.7.4场景3:通过自己有限信任的多个人的数字签名进行确认
最后,我们来介绍一个通过多个所有者信任的总和来确认公钥合法性的方法。
假设 Alice有两个男朋友,他们分别叫 Dave 和 Fred。在 Alice 的公钥串中,包含带有 Alice的数字签名的上述两人的公钥。
Alice 一定程度上信任 Dave 和 Fred。她想:“Dave 和 Fred了解对公钥施加自己的数字签名所代表的意义,当然,他们没有 Trent 那样可信,不过只要是 Dave 和 Fred 两个人都签过名的公钥,就一定是合法的。”
在这样的场景中, Alice可以将对Dave和Fred的所有者信任级别设置为“有限信任”(Marginally trusted )。
某天, Alice收到了来自George的公钥,其中带有Dave的数字签名和Fred的数字签名。如果只有 Dave 一个人的签名是不可信的,只有 Fred一个人的签名也是一样,但两个有限信任的人的签名加在一起, Alice的GPG就会认为这个公钥的确属于George本人。
某天,Alice 又收到了来自 Harrold 的公钥,这次上面只带有 Fred 一个人的数字签名。这时, Alice的PGP就会认为这个公钥不一定属于Harrold本人。
上面我们是通过两个人的数字签名来判断公钥合法性的,用户还可以自行设定判断公钥合法需要多少个数字签名。
13.7.5 公钥合法性与所有者信任是不同的
请大家注意,“公钥是否合法”与“所有者是否可信”是两个不同的问题,因为尽管公钥合法,其所有者也可以是不可信的。
例如, Alice认为从Bob那获得的公钥是合法的,因为这个公钥是Bob当面交给Alice的。但是 Alice 不信任 Bob 在数字签名上的判断能力,即便 Bob 对其他的公钥进行了数字签名,Alice也会怀疑Bob是否真的进行了本人确认。因此, Alice将对Bob的所有者信任级别设置为“不信任”( Never trust this key )。
这样做的结果是,Alice 收到了一个叫 Inge 的人的公钥,即便这个公钥带有 Bob 的签名,Alice的PGP也不会认为这个公钥是合法的。
13.7.6 所有者信任级别是因人而异的
通过上面的讲解,我们应该已经可以想象出 Alice 的公钥串中所存放的这些公钥之间可以形成一张信任网。
结果, Alice所使用的PGP会认为Alice、 Bob、Trent、 Dave、 Fred、Carrol和George的公钥是合法的,而不会认为Harrold和Inge的公钥是合法的。
我们可以将上述关系总结成一张图,如图 13-13 所示。这就是信任网,也叫“信任网络”或者“信任数据库”。
在这里需要大家注意的是,“对哪个密钥的所有者进行哪种级别的信任”是因人而异的。Alice完全信任Trent,但别人有可能只是部分信任Trent,也有人完全不信任Trent。 PGP的用户可以自行设置对谁进行何种程度的信任,PGP就是根据信任数据库中的设置来判断所得到的公钥是否属于本人的。PGP 当初的设计目的是在连国家都不可信的情况下依然能够使用,因此它并不关心有没有可信的认证机构,而是采用了“由用户自己来决定信任谁”这样的设计。
小测验 3 大量的数字签名 (答案见 13.9 节)
Alice收到了来自Jerry的公钥,这个公钥上带有 10个合法的数字签名, Alice能判断这个公钥是合法的吗?
13.8本章小结
本章中,我们以 PGP为例讲解了对多种密码技术的组合,并学习了加密、解密、生成和验证数字签名等知识。大家是否已经懂得如何将单独的密码技术组合起来进行运用了呢?
大家应该可以感受到,每个密码技术本身就很复杂,经过组合之后所形成的密码软件则更加复杂。
为了确认公钥合法性, PGP采用了信任网这一方法。这种方法不依赖特定的认证机构,而是通过每个用户对公钥进行相互签名来构建一个信任的网络。
在下一章中,我们将介绍 Web 中广泛使用的 SSL/TLS。
小测验 4 PGP的基础知识 (答案见 13.9 节)
下列说法中,请在正确的旁边画⚪,错误的旁边画×。
(1) PGP中是先对数据进行压缩,然后再进行加密的。
(2) PGP的用户使用http://www.pgp.com/上设立的认证机构。
(3)使用PGP可以生成自己的公钥密钥对。
(4)在用PGP进行加密时,不使用对称密码算法,而是使用公钥密码算法。
(5)在用 PGP 验证数字签名时,需要输入口令。
(6) 在用 PGP 生成数字签名并加密时,需要输入发送者的口令。
13.9 小测验的答案
小测验 1 的答案:压缩和加密的顺序 (13.4.2 节)
这是因为在加密之后,比特序列的冗余性消失,基本上无法进行压缩了。在加密前进行压缩的做法不仅限于混合密码系统,而是对所有密码都适用的。
小测验 2 的答案:确认公钥合法性的手段 (13.7.2 节)
无需读出公钥的内容本身,只要将公钥的内容输入单向散列函数,并通过电话读出并对比所得到的散列值就可以了。对散列值进行对比,事实上就相当于对公钥内容本身进行对比,这是因为单向散列函数可以用来确认完整性。
为了确认完整性,PGP可以显示一串被称为密钥指纹( key fingerprint )的字节序列,这其实就是密钥的散列值。
小测验3的答案:大量的数字签名 (13.7.6 节)
不能。
仅通过数字签名的数量是无法判断公钥合法性的,必须通过对数字签名的“所有者信任等级"来判断带有该签名的公钥是否合法。
小测验 4 的答案:PGP 的基础知识 (13.8 节)
⚪(1) PGP 中是先对数据进行压缩,然后再进行加密的。
× (2) PGP 的用户使用 http://www.pgp.com/上设立的认证机构。PGP中不使用认证机构。
⚪ (3)使用 PGP 可以生成自己的公钥密钥对。
× (4)在用 PGP 进行加密时,不使用对称密码算法,而是使用公钥密码算法。由于 PGP 使用混合密码系统,因此必然会同时使用对称密码和公钥密码。
× (5)在用 PGP 验证数字签名时,需要输入口令。因为只需要对发送者的公钥进行验证,所以不需要口令。
⚪(6)在用 PGP 生成数字签名并加密时,需要输入发送者的口令。要生成数字签名,需要发送者的私钥。由于私钥本身是加密存储的,因此需要输入口令对私钥进行解密。