[TOC]
PGP 简介
什么是 PGP
PGP 是 1990 年左右由 菲利普·齐墨尔曼(Phil Zimmermann)个人编写的密码软件,现在依然在世界上被广泛使用。 PGP 这个名字是 Pretty Good Privacy(很好的隐私)的缩写。
PGP 可以在 Windows、Mac OS X、Linux 等很多平台上运行,版本包括商用版和免费版。此为还有一个由 GNU 遵照 OpenPGP 规范编写的叫做 GnuPG 的自由软件。
以下内容摘自 https://www.wikiwand.com/zh-cn/菲爾·齊默爾曼、https://www.wikiwand.com/zh-cn/PGP
1991 年,菲利普·齐墨尔曼发表了良好隐私密码法(PGP)的程式,包括程式码与执行档,皆放在公开 FTP 站上,供人自由下载。第一个版本的 PGP 程式与其中使用的加密算法 BassOmatic 都是由齐默尔曼发展出来。
因为 PGP 中使用了 RSA 算法,侵犯了专利权,RSA Security 公司向美国政府提出报告。美国政府长期将密码学视为是军需品,需要管制。
根据美国出口管理法案中的定义,加密系统使用大于 40 位的密钥将被认为是军需品。PGP 从没有使用小于 128 位的密钥,因此在那时被如此认定。如果被判有罪,这将会是严重的罪行。
在美国政府启动调查之后,因为 PGP 中使用的密钥,齐默尔曼被指控违反了武器出口限制法案(Arms Export Control Act)。经过三年的调查,齐默尔曼最终并未被起诉。
齐默曼使用了一种富有想象力的方法来对抗这一规定。他将 PGP 的全套源代码出版成一本书,由 MIT 出版社(英语:MIT Press)发行,受到了广泛欢迎。任何想要构建自己的 PGP 版本的人只需买下这本 60 美元的书,切掉封面,分离页面,然后使用 OCR(文字扫描识别)程序进行扫描和文字识别(或者直接输入),生成一系列的源代码文本文档。接下来便可以使用自由分发的 GCC 来编译程序。PGP 就是这样在全世界变得可用。声明的原则很简单:对军需品 —— 枪支、炸药、飞机和软件的出口是被限制的,然而书本出口受到 第一修正案(言论自由部分)的保护。这个问题从未再在法庭中检查过。
在 1996 年,美国政府确定不起诉之后,齐默尔曼创立了 PGP 公司,并释出新的 PGP 程式版本。1997 年 12 月,PGP 公司被 Network Associates(NAI)并购。在并购后,接下来三年,齐默尔曼以资深成员的身份继续留在公司工作。
关于 OpenPGP
OpenPGP 是对密文和数字签名格式进行定义的标准规格。
1996 年的 RFC1991 中对 PGP 的消息格式进行了定义。
2007 年的 RFC4880 中新增了对 RSA 和 DSA 的支持。
2012 年的 RFC6637 新增了对椭圆曲线密码(ECC)的支持,并且还支持基于 Curve P-256、P-384 和 P-521 三种椭圆曲线的椭圆曲线 DSA 和椭圆曲线 DH 密钥交换。
RFC6637 中新增了用于比较密码学强度的平衡性的对照表。
由这张表可知,当我们选用 256 比特的椭圆曲线密码算法时,相应地应该选用 256 比特的散列算法以及密钥长度为 128 比特的对称密码算法。
密码学强度的平衡表
椭圆曲线名 | ECC | RSA | 散列 | 对称密码 |
---|---|---|---|---|
P-256 | 256 | 3072 | 256 | 128 |
P-384 | 384 | 7680 | 384 | 192 |
P-512 | 521 | 15360 | 512 | 256 |
关于 GNU Privacy Guard
GNU Privacy Guard(GnuPG)是一款基于 OpenPGP 标准开发的密码软件,支持加密、数字签名、密钥管理、S/MIME、ssh 等多种功能。
GnuPG 是基于 GNU GPL 协议发布的一款自由软件,因此任何人都可以自由使用它。GnuPG 本身是一款命令行工具,但它经常被集成到其他应用软件中。
Gnu Privacy Guard 官方网站:https://www.gnupg.org
GunPG 分为 stable、modern 和 classic 三个系列。
- GunPG stable:版本号为 2.0.x,支持 OpenPGP、S/MIME 和 ssh。
- GunPG modern:版本号是 2.1.x,在 stable 的基础上增加了对椭圆曲线密码的支持。它是比较新的版本,今后将会逐渐取代现在的 GnuPG stable 版本。
- GunPG classic:版本号 1.4.x,是比较旧的版本。
PGP 的功能
PGP 具备现代密码软件所必须的几乎全部功能。
对称密码
PGP 支持用对称密码进行加密和解密。对称密码可以单独使用,也可以和公钥密码组合成混合密码系统使用。
可以使用的对称密码算法包括 AES、IDEA、CAST、三重 DES、Blowfish、Twofish、Camellia 等。分组密码模式使用的是 CFB 模式。
公钥密码
PGP 支持生成公钥密码的密钥对,以及用公钥密码进行加密和解密。实际上并不是使用公钥密码直接对明文进行加密,而是使用混合密码系统来进行加密操作。
可以使用的公钥密码算法包括 RSA 和 ElGamal 等。
数字签名
PGP 支持数字签名的生成和验证,也可以将数字签名附加到文件中,或者从文件中分离出数字签名。
可以使用的数字签名算法包括 RSA、DSA、ECDSA(椭圆曲线 DSA)、EdDSA(爱德华兹曲线 DSA)等。
单向散列函数
PGP 可以用单向散列函数计算和显示消息的散列值。
可以使用的单向散列函数算法包括 MD5、SHA-1、SHA-224、SHA-256、SHA-384、SHA-512 和 RIPEMD-160 等。
MD5 依然可是使用,但并不推荐,因为 MD5 算法在实践中已经产生了碰撞,理论上不具备弱抗碰撞性。
证书
PGP 可以生成 OpenPGP 中规定格式的证书,以及与 X.509 规范兼容的证书。此外,还可以颁发公钥的作废证明,并可以使用 CRL 和 OSCP 对证书进行校验。
注:GnuPG 1.2.0 中无法颁发与 X.509 规范兼容的证书。
压缩
PGP 支持数据的压缩和解压缩,压缩采用 ZIP、ZLIB、BZIP2 等格式。
文本数据
PGP 可以将二进制数据和文本数据相互转换、例如,当不得不使用某些无法处理二进制数据软件进行通信时,可以将二进制数据转换成文本数据(ASCII radix-64 格式),这些软件就能够进行处理了。
radix-64 格式是在邮件等场合中经常使用的 base64 编码的基础上,增加了检测数据错误的校验和的版本。base64 编码是一种可以将任何二进制数据都用 AZ、az、0~9、+、/ 同 64 个字符再加上 =(用于末尾填充) 来表示的格式。
大文件的拆分和合并
在文件过大无法通过邮件进行发送的情况下,PGP 可以将一个大文件拆分成多个文件,反过来也可以将多个文件拼合成一个文件。
钥匙串管理
PGP 可以管理所生成的密钥对以及从外部获取的公钥,用于管理密钥的文件称为钥匙串(key ring)。
加密与解密
加密
PGP 的加密过程如下图,在这张图中,消息是经过混合密码系统进行加密,然后转换成报文数据(文本数据)。
PGP 加密过程
- 用伪随机数生成器生成会话密钥。
- 用公钥密码加密会话密钥。
- 压缩消息。
- 使用对称密码对压缩的消息进行加密,这里使用的密钥是步骤 1 中生成的会话密钥。
- 将加密的会话密钥(步骤 2)与加密的消息(步骤 4)拼合起来。
- 将步骤 5 的结果转换为文本数据,转换后的结果就是报文数据。
混合密码系统的特点:用公钥密码加密会话密钥,用对称密码加密消息。
解密
PGP 解密过程如下图,这张图展示了接收者在收到发送者生成的报文数据之后,解密得到原始消息的过程。
解密私钥
PGP 的私钥是保存在用户的钥匙串中的。为了防止钥匙串被盗,私钥都是以加密状态保存的,并在保存时使用了基于口令的密码(PBE)。口令是由多个单词组成的短语,没有正确的口令就无法使用相应的私钥。如果攻击者想要使用你的私钥,就必须先窃取保存私钥的钥匙串,然后再破译加密私钥的密码。
PGP 解密过程
- 接收者输入解密的口令。
- 求口令的散列值,生成用于解密私钥的密钥。
- 将钥匙串中经过加密的私钥进行解密,得到接收者的私钥。
- 将报文数据(文本数据)转换成二进制数据。
- 将二进制数据分解成两部分:加密的会话密钥、经过压缩和加密的消息。
- 用公钥密码解密会话密钥,这里使用步骤 3 中生成的接收者的私钥。
- 对步骤 5 中得到的经过压缩和加密的消息用对称密码进行解密,这里使用了步骤 6 中生成的会话密钥。
- 对步骤 7 中得到的经过压缩的消息进行解压缩。
- 得到原始消息。
下图展示了在加密和解密的过程中,会话密钥和消息进过了怎样的变化。
生成和验证数据签名
生成数字签名
下图展示了 PGP 中生成数字签名的过程。在这张图中,消息与相应的签名进行拼合,并最终转换成报文数据(文本数据)。顺便提一下,对于是否要将报文数据转换成文本数据,在 PGP 中是可以选择的。
生成数字签名的步骤
生成数字签名的步骤主要分为两步:解密私钥,生成数字签名。
- 发送者输入签名用的口令。
- 求口令的散列值,生成用于解密私钥的密钥。
- 将钥匙串中经过加密的私钥进行解密。
- 用单向散列函数计算消息的散列值
- 对步骤 4 中得到的散列值进行签名。这一步相对于使用步骤 3 中得到的私钥进行加密。
- 将步骤 5 中生成的数字签名与消息进行拼合。
- 将步骤 6 中的结果进行压缩。
- 将步骤 7 的结果转换为文本数据。
- 步骤 8 的结果就是报文数据。
验证数字签名
下图展示了用 PGP 验证数字签名的过程,即接受者在接收到报文数据后,得到原始数据并验证数字签名的过程。
验证数字签名的步骤
验证数字签名的步骤主要分为两步:恢复发送者发送的散列值,对比散列值。
- 将报文数据(文本数据)转换为二进制数据。
- 将经过压缩的数据进行解压缩。
- 将解压缩后的数据分解成经过签名的散列值和消息两部分。
- 将经过签名的散列值(经过加密的散列值)用发送者的公钥进行解密,恢复出发送者发送的散列值。
- 将步骤 3 中分解出的消息输入单向散列函数计算散列值。
- 将步骤 4 中得到的散列值与步骤 5 中得到的散列值进行对比。
- 如果步骤 6 的结果相等则数字签名验证成功,不相等则验证失败。这就是数字签名的验证结果。
- 步骤 3 中分解出的消息就是发送者发送的消息。
下图展示了在生成和验证数字签名的过程中,散列值和消息经过了怎样的变化。
生成数据签名并加密以及解密并验证数字签名
生成数据签名并加密
用 PGP 生成数字签名并加密的过程如下图,图中展示了对消息生成数字签名以及对消息进行压缩和加密这两个过程,并将两者的结果拼合在一起形成了报文数据(文本数据)。
对于是否要将报文数据转换成文本数据,在 PGP 中是可以选择的。
生成数据签名并加密步骤:
- 生成数字签名;
- 加密;
注:这里的加密对象并不仅仅是消息本身,而是将数字签名和消息拼合之后的数据。
解密并验证数字签名
用 PGP 解密并验证数字签名的过程如下图,图中展示了对接收到报文数据进行解密和解压缩,并对所得到的消息验证数字签名这两个过程。最终得到的结果包括消息本身以及对数字签名的验证结果。
⚠️ 图例勘误:左上角的「发送者」应该改为「接收者」,是接收者通过自己的口令计算出加密密钥的密钥(KEK),进而获取到接收者自己的私钥。
解密并验证数字签名步骤:
- 解密,这里解密所得到的数据并不仅仅是消息本身,而是将数字签名和消息拼合之后的数据。
- 验证数字签名
下图展示了在“生成数据签名并加密”和“解密并验证数字签名”的步骤中,散列值、会话密钥和消息分别经过了怎样的变化。
信任网
PGP 所采用的一种确认公钥合法性的方法 —— 信任网。
公钥合法性
在使用 PGP 时,确认自己所得到的公钥是否真的属于正确的人(公钥合法性)是非常重要的,因为公钥可能会通过中间人攻击被替换。
证书是确认公钥合法性的方法之一。证书就是由认证机构对公钥所施加的数字签名,通过验证这个数字签名就可以确认公钥的合法性。
然而,PGP 中却没有使用认证机构,而是采用了一种叫做信任网的方法。在这种方法中,PGP 用户会互相对对方的公钥进行数字签名。
信任网的要点是 “不依赖认证机构,而是建立每个人之间的信任关系”。换言之,就是能够自己决定要信任哪些公钥。
场景 1:通过自己的数字签名进行确认
Alce 和 Bob 约会,在告别的时候,Bob 给了 Alice 一张存储卡,并说 “这是我的公钥”。
Alice 回到家里,从存储卡中取出 Bob 的公钥,并存放到自己所使用的 PGP 公钥串中(导入公钥)。由于 Alice 确信刚刚导入的公钥确实是属于 Bob 本人的,因此 Alice 对这个公钥加上了自己的数字签名。
对 Bob 的公钥加上数字签名,就相对于 Alice 声明 “这个公钥属于 Bob 本人(即这个公钥是合法的)”。
随后,Alice 收到了来自 Bob 的邮件,由于这封邮件带有 Bob 的数字签名,因此 Alice 想用 PGP 来验证 Bob 的数字签名。
PGP 将执行下面这些操作:
- 为了验证 Bob 的数字签名,PGP 需要从 Alice 的公钥串中寻找 Bob 的公钥。
- Alice 的公钥串中包含 Bob 的公钥,因为前几天约会之后 Alice 导入了 Bob 的公钥。
- PGP 发现 Bob 的公钥带有 Alice 的数字签名,这是因为前几天约会之后 Alice 对 Bob 的公钥加上了数字签名。
- 为了验证 Alice 的数字签名,PGP 需要从 Alice 的公钥串中寻找 Alice 自己公钥。
- 当然,Alice 的公钥串中也包含 Alice 自己的公钥。
- PGP 使用 Alice 的对 Bob 公钥上 Alice 的数字签名进行验证。如果验证成功,则可以确认这的确是 Bob 的公钥。
- PGP 使用合法的 Bob 的公钥对邮件上附带的 Bob 的之前签名进行验证。
通过上述步骤,就完成了对 Bob 的数字签名的验证,Alice 确认这封信就是前几天和她约会的 Bob 所发送文档,她终于可以放心了。
场景 2:通过自己完全信任的人的数字签名进行确认
Alice 有一个叫 Trent 的男朋友。在 Alice 的公钥串中,也包含了带有 Alice 的数字签名的 Trent 的公钥。
Alice 非常信任 Trent,她想:“Trent 很了解密码和数字签名,也了解对公钥施加自己的数字签名所代表的意义,因此经过他签名的公钥一定是合法的。”
使用 PGP 可以表现 Alice 对 Trent 的信任程度,也就是说,Alice 可以对 Trent 的公钥设置 “我完全信任 Trent 的数字签名” 这一状态,并加上自己的数字签名。
在 PGP 中,用户可以设置对每个公钥所有者的所有者信任级别。Alice 对 Trent 的所有者信任级别设置为 “完全信任”。
所有者信任级别 | 描述 |
---|---|
I trust ultimately | 绝对信任(是持有私钥的本人) |
I trust fully | 完全信任 |
I trust marginally | 有限信任 |
I do Not trust | 不信任 |
Unknow | 未知密钥 |
Undefined | 未设置 |
我们假设这次 Alice 收到了一封来自 Carrol 的邮件,这封邮件带有 Carrol 的公钥,而且这个公钥带有 Trent 的数字签名。当 Alice 将 Carrol 公钥导入自己的公钥串时,Alice 的 PGP 会认为 Carrol 的公钥是合法的,因为 Carrol 的公钥带有 Alice “完全信任” 的 Trent 的数字签名。
在这个场景中,Trent 对于 Alice 来说是可信的 “介绍人”。Trent 对 Carrol 的公钥加上数字签名,就相对于 Trent 写了一封 “介绍信”。
场景 3:通过自己有限信任的多个人的数字签名进行确认
最后,介绍一个通过多个所有者信任的总和来确定公钥合法性的方法。
假设 Alice 有两个男朋友,他们分别叫 Dave 和 Fred。她想:“Dave 和 Fred 了解对公钥施加自己数字签名所代表的意义,当然,他们没有 Trent 那样可信,不过只要是 Dava 和 Fred 两个人都签过名的公钥,就一定是合法的。”
在这样的场景中,Alice 可以将对 Dava 和 Fred 的所有者信任级别设置为 “有限信任”。
某天,Alice 收到了来自 George 的公钥,其中带有 Dave 的数字签名和 Fred 的数字签名。如果只有 Dava 一个人的签名是不可信的,只有 Fred 一个人的签名也是一样,但两个有限信任的人的签名加在一起,Alice 的 PGP 就会认为这个公钥的确属于 George 本人。
某天,Alice 又收到了来自 Harrold 的公钥,这次上面只带有 Fred 一个人的数字签名。这时,Alice 的 PGP 就会认为这个公钥不一定属于 Harrold 本人。
上面我们是通过两个人的数字签名来判断公钥的合法性,用户还可以自行设定判断公钥合法需要多少个数字签名。
公钥合法性与所有者信任是不同的
“公钥是否合法” 与 “所有者是否可信” 是两个不同的问题,因为尽管公钥合法,其所有者也可以是不可信的。
例如,Alice 从 Bob 那获得的公钥是合法的,因为这个公钥是 Bob 当面交给 Alice 的。
但是 Alice 不信任 Bob 在数字签名上的判断能力,即便 Bob 对其他公钥进行了数字签名,Alice 也会怀疑 Bob 是否真的进行了本人确认。因此,Alice 对 Bob 所有者信任级别设置为 “不信任”。
这样做的结果是,Alice 收到了一个叫 Inge 人的公钥,即便这个公钥带有 Bob 的签名(这个公钥是合法的,它是被签名的),Alice 的 PGP 也不会认为这个公钥是合法的(但我不信任这个公钥)。
所有者信任级别是因人而异的
Alice 的公钥串中所存放的这些公钥之间形成了一张信任网。
- Alice 对自己公钥加上数字签名(所有者信任级别为 “绝对信任”)
- Alice 对 Bob 的公钥加上数字签名(所有者信任级别为 “不信任”)
- Alice 对 Trent 的公钥加上数字签名(所有者信任级别为 “完全信任”)
- Alice 对 Dava 的公钥加上数字签名(所有者信任级别为 “有限信任”)
- Alice 对 Fred 的公钥加上数字签名(所有者信任级别为 “有限信任”)
- Trent 对 Carrol 的公钥加上数字签名
- Dava 对 George 的公钥加上数字签名
- Fred 对 George 的公钥加上数字签名
- Fred 对 Harrold 的公钥加上数字签名
- Bob 对 Inge 的公钥加上数字签名
结果,Alice 所使用的 PGP 会认为 Alice、Bob、Trent、Dava、Fred、Carrol 和 George 的公钥是合法的,而不会认为 Harrold 和 Inge 的公钥是合法的方。
我们可以将上述关系总结成下面这张图。这就是信任网,也叫 “信任数据库” 或者 “信任网络”。
在这里需要注意的是,“对哪个密钥的所有者进行哪种级别的信任” 是因人而异的。
Alice 完全信任 Trent,但别人有可能只是部分信任 Trent,也有人完全不信任 Trent,PGP 的用户可以自行设置对谁进行哪种程度的信任,PGP 就是根据信任数据库中设置来判断所得到的公钥是否属于本人。
PGP 当初的设计目的是连国家都不可信的情况下依然能够使用,因此它并不关心有没有可信的认证机构,而是采用了 “由用户自己来决定信任谁” 这样的设计。
参考
- 《图解密码技术》结城浩[日]著
- PGP 中国