「译」PGP的问题(上)– 问题
原文链接 ,原作者为 Latacora,一个国外安全团队。
几十年来(一点不夸张地),密码学工程师们一直为PGG的缺陷 困扰得拽头发。
当其他领域的工程师得知这个消息时, 他们会感到震惊 。啥? PGP不行? 那为啥人们总是告诉我用PGP?
答案是他们不应该告诉你, 因为PGP就是不行, 需要被淘汰。
正如你将要看到的,PGP有非常多的问题。
幸运的是, 如果你并不是病态地好奇, 它有一个简单的元问题:它是20世纪90年代设计的,在严肃的现代密码学诞生之前。
(如今)没有一个合格的密码工程师会设计一个像今天的PGP一样的系统, 也不会容忍它在其他设计中的大部分缺陷。
严肃的密码学家们在很大程度上已经放弃了PGP, 并不再花时间为它发表论文(有一个明显的例外)。
由于这个原因,PGP中被充分理解的问题已经有十多年没有得到解决了。
有两点要注意:: 第一, 我们这篇文章是为工程师写的, 不是为律师和活动家写的。
第二, “PGP “可以指一堆东西,从OpenPGP标准到GnuPG的参考实现。我们用 “PGP “这个词来涵盖所有这些东西。
问题
荒谬的复杂性
由于一些我们这些未来人都不理解的原因, PGP有一个基于数据包的结构。
PGP 信息(包含在“.asc”文件中)是类型化数据包的存档。 根据您使用的是“新”还是“旧”格式的数据包,至少有 8 种不同的方法可以对数据包的长度进行编码。
新格式的数据包长度是可变的,如 BER(尝试编写 PGP 实现,您可能会希望 ASN.1 的sweet release)。包可以有子包。某些数据包有重叠的变体。
最近发生的公钥服务器攻击是因为 GnuPG在解析密钥时意外出现指数级增长,这也是遵循这种发癫的格式。
以上只是编码的问题。
实际用起来的时候,系统并不会更简单: 有主密钥和子密钥,密钥ID、公钥服务器和密钥签名,只有签名的和只有加密的,多个 “密钥环”,撤销证书,三种不同的压缩格式。
这些还都是在我们谈到智能卡支持之前。
瑞士军刀式的设计
如果你被困在森林里里,我不清楚,需要修理你的牛仔裤袖口,如果你的多功能刀有一把剪刀,那就很方便了。但是,没有一个做正经工作的人经常使用他们的多功能刀的剪刀。
一把瑞士军刀能做一堆事情,但都做得很差:
- PGP在签名方面做得很平庸
- 在用密码加密方面做得相对较差
- 在用公钥加密方面做得相当糟糕
- PGP并不是一个安全传输文件的好方
- 它是一个笨拙的签名包的方式
- 它在保护备份方面不是很好
- 它是一种完全危险的安全信息交流方式
回到 PGP 起源的 MC Hammer 时代,“加密”只是“一件”特殊的事: 有一个工具用来(单纯地)发送文件,或只是备份一个目录,又用另外的工具来加密和签名文件。
而现代密码学不是这样运行的, (不同加密算法)有其专门的目的。 例如,安全地传递消息也需要加密,一种不同于安全备份或包签名的加密。
陷入兼容旧版的泥潭
PGP 早于现代密码学;比Hanson的专辑还要久远的年代。
如果幸运的话,您的本地 GnuPG 默认为 2048 位 RSA、CFB 中的 64 位块 CAST5 密码和 OpenPGP MDC 校验和(稍后会详细介绍)。
如果您使用密码而不是公钥进行加密,OpenPGP 协议会指定了PGP 的 S2K 密码 KDF。委婉地说,这些不是密码工程师为现代系统选择的原语。
自从 Steve Urkel 在 ABC 的 TGIF 节目中出现以来,我们学到了很多:
- 你应该验证你的密文(并避免 CFB 模式)将是一个明显的例子。
- 64 位分组密码并不好,我们可以做很多比 RSA 更好的事。
- 混合压缩和加密是危险的,而且 KDF 应该是时间和内存困难的。
无论 OpenPGP RFC 怎么说,如果您使用 PGP,您可能不会做任何这些事情,也无法预测何时会做。
以 AEAD 密码为例:Rust 语言的 Sequoia PGP 默认为 AES-EAX AEAD 模式,这很好,没有人可以阅读这些消息。 而因为大多数 PGP 安装者并不知道 EAX 模式是什么,这就不太好了。
每个众所周知的坏密码系统最终都会产生一个支持曲线或 AEAD 的 RFC 扩展,以便其支持者可以在留言板上声称他们支持现代密码学。
RFC 无关紧要:只有安装PGP的这些基本盘才重要。
我们已经搞了认证加密这一套20 年了,PGP 已经足够成熟了,它都能自己去超市给我买酒了。(抱歉
您可以选择兼容 1990 年代的旧版本,也可以选择拥有健全的密码学。 但你并不能同时拥有。
令人讨厌的用户体验
我们不能说得比 Ted Unangst 更好了:
几年前进行了一项 PGP 可用性研究,其中一组技术人员被安置在一个有计算机的房间里,并要求设置 PGP。 两个小时后,这些人没了,消失了,杳无音讯
如果您想要自己的经验数据来支持这一点,您可以进行以下实验:
- 找到一位移民律师,并与他们讨论让 Signal 在他们的手机上工作的过程
- 你可能不会马上体验到它的美味
- 现在尝试(把Signal换成) PGP 来做这件事
长期的密钥
PGP 请求用户保留与他们的身份相关联的几乎永久的根密钥。
它通过使 密钥生成和交换变得烦人、“密钥签署Party” , 以及创建一个 “信任网”(Web Of Trust), 使密钥依赖于其他密钥 ,来做到这一点。
长期密钥几乎从来都不是您想要的。如果您持续地使用密钥,它最终都会泄漏。
您希望妥协的爆炸半径尽可能小,而且同样重要的是,你不希望用户在对他们目前的密钥的安全有任何担心的情况下, 对启用新密钥的想法有任何犹豫。
PGP 氛围组马上就会回复:
“这就是为什么你要把密钥放在 Yubikey里~”
大致上来说,全世界没有人使用昂贵的 Yubikey 来做这个,而且你也别期待未来会发生。 (我们连U2F的推广都进行不动,而且这些密钥是一次性的)。
我们不能仅仅为了让 Unix 书呆子对他们的玩具感觉更好,而接受糟糕的密码系统。
身份验证的崩溃
更多关于 PGP 的古老原语:早在 2000 年,OpenPGP 工作组就意识到他们需要对密文进行身份验证,而 PGP 的签名并没有做到这一点。
因此 OpenPGP 发明了 MDC 系统:带有 MDC 的 PGP 消息将明文的 SHA-1 附加到明文,然后在 CFB 模式下加密(跟平常那样)。
如果您想知道当现代系统使用相对复杂的 AEAD 模式时 PGP 如何解决这个问题(为什么每个人都不能将 SHA-1 添加到他们的明文中),您并不孤单。
从哪里开始使用这个 Rube Goldberg 装置呢?PGP MDC 可以被剥离消息——它的编码方式是你可以简单地截掉密文的最后 22 个字节来做到这一点。
为了保持与不安全的旧信息的兼容性,PGP 引入了一种新的数据包类型来表示需要验证 MDC;如果您使用了错误的类型,则不会检查 MDC。
即使您这样做了,新的 SEIP 数据包格式也与不安全的 SE 格式非常接近,可能会诱使读取方降级;Trevor Perrin 将 SEIP 设计为 16 个完整的安全位。
最后,即使一切顺利,Reference的PGP 实现也会(等待它)向调用者发送未经身份验证的明文,即使 MDC 不匹配。
不连贯的身份
PGP 是一个应用程序 它是与其他应用程序的一组集成 它是一种文件格式 它也是一个社交网络 也是一种亚文化。
PGP 推动了加密身份的概念:
- 您生成一个密钥,将其保存在您的密钥环中,在您的名片上打印其指纹,然后将其发布到密钥服务器。
- 你在别人的密钥上签名。
- 他们反过来可能会也可能不会依赖您的签名来验证其他密钥。
- 有些人会特意亲自与其他 PGP 用户会面,以交换密钥并更安全地连接到这个“信任网络”。
- 还有一些人会组织“密钥签署Party”。
您现在在脑海中勾勒出的图像准确地解释了 PGP 的拥护者们切换到更新的东西有多难。
不过这种黏在一起的身份没啥用。
普通人会相信任何看起来像 PGP 密钥的东西,而不是密钥签名信任网络,不是密钥服务器,不是那些Party ,无论它来自哪儿——他们怎么可能不信? 即使是专家也很难阐明如何评估密钥。
专家不信任他们没有亲自交换过的密钥。其他所有的人都依赖一个中心化的机构来分发密钥。 PGP 的密钥分发机制是场闹剧。
泄露元数据
先不说电子邮件的问题(我们稍后会说到), PGP本身就泄露了元数据。
信息(在正常使用情况下)直接与密钥标识符相连,而密钥标识符在整个PGP的信任网中与用户身份相连。
此外, 很大一部分PGP用户使用密钥服务器,这些密钥服务器本身也会向网络泄露哪些PGP用户正在相互通信的身份。
无前向保密性
PGP的最后一个问题,有一个很好的例子:安全消息传递加密要求前向保密。
前向保密意味着,如果你今天向攻击者“Say Hi”,并丢了一只密钥,他们仍然不能去阅读到昨天的消息;他们必须在昨天带着密钥在那里才能阅读它们。
在现代密码学工程中,我们假设我们的对手正在将所有内容记录到无限存储中。PGP 声称的对手包括世界各国政府,其中许多政府确实在这样做。针对强大的对手并且没有前向保密,被破解是“何时”的问题,而不是“如果”的问题。
为了在实践中实现保密,您通常会保留两个密钥:一个短期会话密钥和一个长期可信密钥。 会话密钥是临时的(通常是 DH 交换的产物)并且受信任的密钥对其进行签名,因此中间人无法交换自己的密钥。
理论上,使用PGP提供的工具可以实现前向保密的雏形。当然,几乎没有人这样做。
笨拙的密钥
OpenBSD的 signify(1)
公钥是一个 Base64 字符串,短到可以放在电子邮件的句子中间;如果是私钥,不是交换格式,只比公钥长了一行左右。
PGP 公钥是一个巨大的 Base64 文档;如果您经常使用它们,那么您可能已经习惯于将它们添加到附件,而不是将它们粘贴到消息中,这样它们就不会被损坏。
Signify 的密钥是最先进的 Ed25519 密钥;PGP 是较弱的 RSA 密钥。
您可能认为这些东西无关紧要,但它很重要;使用 SSH 和管理 SSH 密钥的人比使用 PGP 的人多几个数量级。SSH 密钥处理起来很简单,而PGP 不是。
协商
PGP 支持 ElGamal。PGP 支持 RSA。PGP 支持 NIST P 曲线。PGP 支持 Brainpool。PGP 支持 Curve25519。PGP 支持 SHA-1。PGP 支持 SHA-2。PGP 支持 RIPEMD160。PGP 支持 IDEA。PGP 支持 3DES。PGP 支持 CAST5。PGP 支持 AES。这不可能是 PGP 支持的完整列表。
如果我们在过去 20 年中学到了关于密码学设计的 3 件重要的事情,其中至少 2 件是协商和兼容性是恶魔。密码系统中的缺陷往往出现在细枝末节中,而不是主干上,而广泛的密码兼容性增加了细节的数量。
像 TLS 1.3 这样的现代协议正在抛弃与 RSA 等东西的兼容性,而不是添加它。新系统只支持一套原语 和一个简单的版本号。如果这些原语之一失败,您会立即更改版本并放弃旧协议。
如果我们不走运,20 年后人们仍在使用 PGP,那么 PGP 将是任何地方的任何代码会包含 CAST5 的唯一原因。
我们不能说得再清楚或者再啰嗦了:您可以选择兼容 1990 年代的旧版本,也可以选择拥有健全的密码学。 但你并不能同时拥有。
简陋的代码
PGP 的实际标准实现是 GnuPG。GnuPG 不是精心构建的。
这是一个庞大的 C 语言代码库,具有重复的功能(例如,最近的 SKS 密钥解析DoS的记录指出它有多个密钥解析器)具有从内存损坏 到加密侧信道的 CVE 的长期跟踪记录。
有时可以在 GnuPG 不注意的情况下将身份验证器从消息中剥离。有可能在它没有注意到的情况下向它提供没有正确指纹的密钥。2018 Efail 漏洞是因为它向调用者发布未经身份验证的明文。
GnuPG 就是不行。
GnuPG 也是 PGP 的有效参考实现,也是集成 PGP 加密的大多数其他工具的基础。 它哪儿也不会去,依赖PGP就是依赖GPG。
【未完待续】