为什么使用 PGP 对电子邮件中的长行进行加密(或签名)有问题?

信息安全 电子邮件 pgp 编码 enigmail
2021-09-03 11:35:32

我正在将 Thunderbird 与 Enigmail 和 OpenPGP 一起使用来加密和/或签署电子邮件。在很多情况下,Enigmail 抱怨我的邮件中的行太长,并询问它应该如何包装它们。

然而,这似乎没有遵循任何合乎逻辑的趋势。有时它会抱怨,有时它不会。

然而,我的问题是:首先,一条线有多长有什么关系?换行符与字母 A 并没有太大的不同(好吧,在大多数情况下,它是一个 CR 和一个 LF),但加密算法无论如何只看到字节。

我也无法在文档中找到任何关于此的解释。

有人可以解释为什么换行符对于使用 PGP 进行签名/加密有问题吗?

3个回答

我不能让它比更简单

本质上,当 Enigmail 将内联 PGP 签名附加到 Thunderbird 的 HTML 消息编辑器中的电子邮件时,就会出现问题。HTML 编写器是与纯文本编写器不同的组件,它在用户点击发送后对消息正文执行一些“清理”。这是一个明显的麻烦,因为它发生在对消息计算签名之后。任何更改,包括对用户不可见的更改(例如空格更改或用 HTML 字符代码替换特殊字符)都将更改消息的哈希值,这是由发件人私人加密的签名元素钥匙。

在这种情况下,消息正文发生的更改是自动换行。Thunderbird 对 HTML 消息的换行会中断超过 79 个字符的行(或任何 mailnews.wraplength 首选项设置的值),因此并非每条消息都会受到影响。为了避免这个麻烦,Enigmail 在生成签名之前在邮件正文上执行自己的换行,在 mailnews.wraplength - 2。

然而,在某些情况下,单个“单词”的长度总是超过 77 个字符;最简单的例子是一个冗长的 URL。在这些情况下,在 Enigmail 处理完邮件后,Thunderbird 执行的自动换行会在发送邮件时在 mailnews.wraplength 点拆分长行,因此当电子邮件收件人的 PGP 客户端检查签名时,签名不再有效。

TL;DR:这是电子邮件遗留问题。

GnuPG、Thunderbird 以及任何其他 OpenPGP 实现都不会担心行长。但是整个电子邮件基础设施都可以。

电子邮件遗产

从历史上看,出现 78 个字符的限制 ( RFC 2822 ) 是因为通常限制每行适合屏幕的字符。这早已不复存在;虽然与 28 英寸 4K 屏幕从左到右的长行相比,这个字符数左右的字符,甚至有些发烧仍会导致更好的可读性,但我们有更智能和用户友好的软件,可以换行自动在合理的范围内。

但是电子邮件已经过时了,(仍在运行的)电子邮件服务器和客户端也是如此。仍然有一些不支持长行,因为它们从未被需要(因为它们不应该发生),并且它们(可能)无法处理此类邮件,或者它们自己添加任意换行符(这会破坏签名)。

在 OpenPGP 中处理长行

由于这个原因,OpenPGP 的“电子邮件安全”ASCII 铠装(基数转换)以(最大)安全的每行 76 个字符换行。另一方面,明文签名的消息不会在明文部分重新包装,因此 Thunderbird/Enigmail 记住您要遵守该字符限制。

OpenPGP/MIME 编码的邮件(以及一般的 MIME 编码的邮件)不知道这个问题,因为quoted-printable 编码负责添加所需的换行符,这些换行符在计算消息哈希以验证签名之前被删除。

在明确签名的情况下,签名的内容可能与您键入的内容不完全相同。

为了变得健壮(RFC4880):

  • 以“-”开头的行以“”为前缀<SP>-(防止误解)
  • 行尾,无论它们是什么,都替换为 <CR><LF>
  • 尾随空格被忽略

为了满足 SMTP 要求 ( RFC5322 ):

  • 消息行不应超过 78 个字符(加号<CR><LF>
  • 消息行不得超过 998 个字符(加号<CR><LF>
  • 消息行不能只包含一个“.”。(带内信号再次出现)并且可能在此过程中被“修复”(RFC5321

这里的要点是,一些修改可能会改变消息的语义,但假设改变行尾的空白数量不能。引入一些更改(额外的换行符或删除字符)会违反签名,因此 PGP 客户端必须确保这些事件不会发生。另请参阅 Enigmail 错误494

(一些猜测:如果您偶尔使用非 ASCII 字符,这可能会导致您的电子邮件客户端不使用 text/plain,而是使用 base64 编码的 UTF-8 来回避上述复杂性。)