电子邮件是计算机网络中最普及、最持久的技术之一,早在 20 世纪 60 年代就已在十多个地方、由数十个人分别发明出来。要给这项技术梳理出一条清晰的历史并不容易,因为它实在太显而易见了——几乎只要不止一个人能使用同一台计算机,就会出现某种邮件功能。这些系统五花八门:从以大型机为中心、单台计算机的所有用户都能互相写信的系统,到以 PC 为中心、工作站通过挂载网络共享来存储和检索邮件的系统。凡是你能想到的消息传递方案,几乎都可能在 20 世纪 60 年代到 90 年代之间的某个地方被使用过;到那时,源自 ARPANET 的电子邮件实现家族已经站稳了脚跟。
这种形式的电子邮件有更清晰的谱系,可追溯到 Ray Tomlinson:他提出了一个核心想法,即地址既能标识用户,也能标识主机,并且在需要时可以使用某种开放协议把消息发送到另一台主机。随着时间推移,Tomlinson 的设计经过多次修订,最终演变为 SMTP,并与 IMAP 等协议一起,构成了今天我们使用的电子邮件形态。从某种意义上说,它是去中心化的(任何用户都可以自由选择主机);而从另一方面看,它又是中心化的(每台主机都被假定为持续在线,为自己的用户存储并转发消息)。Tomlinson 的设计足够灵活,以至于我们至今仍不必把它完全抛弃,但现代互联网已经发生了足够多的变化,迫使我们采取一种新的方法。
电子邮件有许多令人头疼的局限,都是它所处年代留下的遗迹。比如,不能假定邮件处理过程是“8 位干净”的——电子邮件协议最初是在 7 位 ASCII 上定义的,而且许多机器会把第 8 位当作校验位。这些机器往往会把每个字节的最后一位改掉,或者以其他方式错误处理包含 8 位内容的邮件。在文本完全局限于 7 位字符集时,这不是问题;但 Unicode 的出现,以及发送二进制文件的需求,使 7 位电子邮件变得不可行。于是 MIME 被开发出来作为变通方案,这是一种编码技术,通过把电子邮件中所有非 ASCII 内容都编码成 ASCII 字符的形式,一次性解决了几个问题。
这相当不优雅。MIME 的 ASCII 编码,无论是 quoted-printable 还是 base64,都让人类难以阅读,而且在消息体积方面效率低下。和所有类似 base64 的编码一样,它都算是一种 可疑的迹象,说明我们是在给过去的错误打补丁。电子邮件里到处都是这种东西。再来看一个:安全性。
“互联网电子邮件”这个术语,是为了明确指代从 ARPANET 继承下来的 SMTP 式电子邮件系统。它采用的是一种简单设计,属于一个网络计算机的操作者彼此都认识的年代。虽然当时也有别的选择,但大多数邮件都是直接投递到收件人的计算机上,而且在很多情况下,当时主机层面的安全性也不太好。别人可能读到你的私人邮件,这种可能性大家心知肚明,但你也没什么太好的办法。互联网存在于一种信任的语境之中。
今天我们已经不再延续这种信任了。电子邮件通常由两端的第三方邮件服务处理,这些服务未必值得信赖;而在这两个第三方邮件服务之间传递时,还必须经过一系列同样安全性存疑的互联网链路。电子邮件成了大规模计算机网络最早、也很可能是 第一个 令人信服的应用之一。它也可能是这个领域最早出现的、长期存在的安全失败之一。这个系统在设计时完全没有考虑消息保密性或完整性,而今天它的很大一部分仍然是这样运作的。
尽管如此,改进电子邮件安全性的努力一直延续了很长时间,而我们大概应该从其中最重要的一项开始讲起:不只是某种电子邮件协议,而是一整套本应让整个互联网都更好的协议栈——OSI 套件。
现代互联网诞生于一个常被称为“协议战争”的时代。今天我们讲互联网历史时,往往会把它简化成一条很顺的线性故事:ARPANET 被创造出来,人人都觉得这是个好主意,于是它逐渐普及。这并不完全错,但遗漏了许多其他参与者。众所周知,电信行业对分组交换模型颇有异议;这种模型起源于计算机行业而非通信行业,这一点也体现在它身上。20 世纪 70 到 80 年代,电信行业定义了自己的一套网络协议,以及计算机网络的基本方法,这套体系后来被称为 OSI 协议套件。
如今,OSI 协议的现实意义很有限,主要体现在现代网络教材令人烦恼地执意用 “OSI 模型” 来解释互联网;而这个模型现在更多是推测性的,而非真正实用的,它描述的是一个与互联网不兼容的不同系统。学界之所以执着于用一套失败互联网的设计文档,来解释另一套成功互联网那截然不同的架构……嗯,这本身就是协议战争的余波。历史或许由胜利者书写,但失败者仍能决定理论。
尽管我一直在推动不要用 OSI 模型来学习网络,但我们确实可以从 OSI 协议中学到东西。TCP/IP 协议栈之所以能战胜 OSI 协议栈,原因很多,其中之一就是 OSI 的“委员会设计”方式造就了一套考虑得非常周全、但也相当复杂的协议。这与互联网协议的设计哲学形成了鲜明对比,后者更接近“现在够用就行”。
当我们看应用层协议时,这种哲学差异尤其明显。通常意义上的“互联网协议套件”根本不包含应用协议,这一点本身就很能说明问题。OSI 套件则包含。互联网电子邮件最初只是 FTP 的一种特殊用途,之后又演变为一组松散的 Telnet 命令,最终才正式化(或者说,按有些人的说法,逐渐僵化)为 SMTP。
到 1984 年 OSI 标准发布时,电子邮件已被广泛认定为“杀手级应用”之一——SMTP 的第一个修订版发布于 1982 年,是对互联网电子邮件流行度的事后回应;而且早在 20 世纪 70 年代,电子邮件就已经是大多数专有网络系统的关键功能。因此,OSI 给出的解决方案是:X.400。
X.400 是 OSI 套件中的“消息处理系统”部分,它提供的功能既像电子邮件,但又更为通用。就大多数方面而言,X.400 是失败的。它几乎没能在任何环境中取代互联网电子邮件。不过,X.400 的确产生了重要影响。曾有一段时间,虽然很短,但人们认为各国政府在未来采购中会要求兼容 X.400。这和后来政府要求 POSIX 兼容的那段时期很相似,产生的效果也类似:许多厂商为了满足要求而设计产品,后来政府失去兴趣,这项要求便成了一个有些奇特的历史遗产。在电子邮件领域,这一点最明显地体现在 Microsoft Exchange 上:Exchange 起初就是一个 X.400 实现,主要是出于政府方面的原因,而它至今仍保留了大量 X.400 功能。
X.400 比互联网电子邮件复杂得多。比如,X.400 消息采用 ASN.1 编码,这是一种二进制序列化格式,比 MIME 更高效、能力更强,但也复杂得多。X.400 的复杂性层层叠加,这有助于理解为什么它最吸引人的功能之一并没有真正普及:加密。
如果你要给别人发邮件,又不希望别人读到它,最直接的方法就是端到端加密。出于许多实际原因,你会想使用非对称加密。先找到收件人的公钥,把消息用那个密钥加密,然后照常在网络上传输;收件人再用自己的私钥解密即可。听起来很简单,但这个过程的每一步都充满复杂性。
为了说明这一点,我们来看看 X.400 本身——1988 年的“蓝皮书”版本,这似乎最能代表电子邮件开始僵化的那个时期。
为支持上述功能,非对称密钥管理方案的相关方面由目录系统认证框架提供,其内容见建议 X.509。目录保存 MHS 用户公钥的经认证副本,可用于提供认证,并促进用于数据保密和数据完整性机制的密钥交换。证书可通过建议 X.519 所述的目录访问协议从目录中读取。
关于其他类型的密钥管理方案,包括对称加密,以支持这些安全功能的建议,仍有待进一步研究。
端到端加密的电子邮件需要两个基本部分:
第一,必须有一种技术格式,能让加密消息穿过消息传输系统。X.400 通过 ASN.1 定义巧妙地解决了这一点,允许消息体以加密形式存在,从而把大部分麻烦推给了别人。X.400 实际上在安全特性上设想得更多,比如投递不可抵赖性之类的功能,这些都需要在消息传输中加入更多复杂性,但最终没有进入现代世界。这里我们先忽略它们。
第二,必须有一套密钥基础设施。你需要某种方式获取你想发信对象的公钥,并且要确保它确实属于对方。这对于加密发出的邮件和验证收到的邮件都很重要,因为端到端加密通常会与端到端认证一起部署,而两者共用同一套密码学基础设施。在 X.400 的情况下,这个问题整体被推给了 X.500 系列协议。
X.500 是什么?是我们的老朋友,目录访问协议。X.500 目录标准正是 LDAP 用来对比自己“轻量级”的对象;这里也有一条平行的故事线:LDAP 是那个更灵活的互联网协议,最终击败了 X.500 这个巨人。
所以,X.400 电子邮件安全的要点就是:用目录查找收件人的公钥,然后用该密钥加密 ASN.1 消息对象的正文。实际上,细节要更不同、更复杂,但这对 OSI 来说都是老问题,而这里的简化轮廓已经足够说明意思了。思路很直接。
只有两个问题:作为消息格式,ASN.1 没有成功;而全球目录这个概念也从未真正成形。
在 X.400 取得一定成功的范围内,它的安全特性其实是很重要的推动因素。ISODE Consortium 当年做出了某种 OSI 应用套件的参考实现,如今仍以 Isode Ltd 的形式存在,并继续销售消息处理系统。还有少数其他 X.400 后裔系统也在维护之中。其最大的客户群之一是军方:虽然在美国不那么常见(请记住,互联网电子邮件 最初是在美国军方的主持下开发的),但不少欧洲国家把 X.400 作为安全消息解决方案,并至今仍在军事和情报机构中高度依赖它。X.400 另一个长期据点包括全球航空业(ICAO 的消息系统就是基于 X.400 的)以及电子数据交换,即 EDI,这是一套在 ERP 之间进行金融和供应链消息传递的标准化系统。
这并非巧合:这些正是 X.25 等协议异常持久地存活下来的那类应用场景(这表明它们与长期运行的遗留系统高度契合),而且这些场景中的参与者和消息传递通常都受某个中心实体管辖。这意味着目录是存在的,也就意味着密钥分发问题大大简化了。这还意味着所使用的软件,无论是传输代理(例如服务器)还是客户端,都是标准化的,而且通常都是从专门为 X.400 环境而设计得较好的厂商那里采购的。
换句话说,这些场景与电子邮件非常不同。在电子邮件里,人们要在大量组织之间交换消息,而许多用户只是使用所谓的“邮件服务商”,这些服务商在传统意义上并不算一个组织。这意味着电子邮件系统里并不存在有意义的目录能力。电子邮件还要面对极其多样化的客户端生态,而“需要与复杂目录系统交互的复杂消息编码”这一设计部分,对此要付出很高的代价。
既然 X.400 在 大多数 电子邮件世界里都没有成功,那么对其余人来说,加密该怎么办?嗯,这个局面就变得复杂而又令人遗憾了。
首先,有必要稍微展开讲讲 MIME,也就是多用途互联网邮件扩展(Multipurpose Internet Mail Extensions)。MIME 起初是为了解决互联网电子邮件的 8 位问题而提出的:一种能以一致、可靠的方式编码非 ASCII 文本和二进制文件的方法。在实现这个目标的过程中,它引入了“多部分”(multipart)消息的概念,也就是一个消息体里可以包含多个不同对象,而不只是单一的文本字符串。如今我们大量使用这一特性:既包括文件附件这类显而易见的用途,也包括提供纯文本版本的 HTML 邮件这类更细微的用途。我觉得把 MIME 概括为“电子邮件 2.0”并不算离谱,因为虽然它的范围只限于消息格式(并不改变传输协议),但 MIME 为电子邮件增加了很多如今已被视为消息系统基本需求的新功能。
MIME 的历史比你想象的要曲折得多,这也反映出要对像互联网电子邮件这样分布式且异构的系统做重大改动有多困难。不过,MIME 的作者似乎也持类似看法:他们认为 MIME 通过标准化消息体并为未来基于这一标准的扩展铺路,确实推动了电子邮件的重要演进。RFC 1521(1993),也就是第一个 MIME 标准中的这段话,很能说明问题:
STD 11、RFC 822 定义了一种消息表示协议,对消息头做了相当详细的规定,但把消息内容,也就是消息体,保留为平面的 ASCII 文本。本文重新定义了消息体格式,使多部分的文本和非文本消息体能够在不丢失信息的情况下表示和交换。这一工作基于 RFC 934 和 STD 11、RFC 1049 中记录的早期工作,但在此基础上进行了扩展和修订。由于 RFC 822 对消息体几乎没有什么规定,本文与 RFC 822 在很大程度上是正交的(而不是对其修订)。
换句话说,现有的电子邮件标准解决了消息如何在主机之间传递的问题,但对消息里实际装的是什么却几乎没有规定。MIME 通过为消息体创建一个正式标准来弥补这一点,这个标准既增加了功能,又要应对许多 MIME 之前的电子邮件实现所带来的糟糕限制。围绕 MIME 这一广义主题的众多 RFC(以及其他关于电子邮件正文格式的提案)花了大量篇幅讨论:当邮件客户端不认识这些新消息类型时,它们应该如何处理。电子邮件技术通常很简单,电子邮件标准却很难。
随着这些标准化工作不断推进,快速发展的计算机密码学领域也有自己的想法。第一件大事是密码学家 Phil Zimmerman 在 1991 年不加修饰地发布了一款名为 PGP 的工具,即 Pretty Good Privacy。PGP 的故事很长:它从一次随意发布,经过一个活跃的 Usenet 组织、刑事指控,最后到成立 PGP Inc 将系统商业化。
有趣的是,就 PGP 本身而言,PGP 并没有那么重要。尽管以这个名字命名的公司抱有商业雄心,但 PGP 最初更像是一个学术或行动主义色彩较强的松散项目;而从长远看,随着开源克隆版 GnuPG(GPG)在市场上取代 PGP,它最终也回到了类似的轨道。PGP Inc 后来并入赛门铁克(Symantec),并像大多数赛门铁克产品那样逐渐淡出人们视野。一路上,PGP 和 GPG 的实现搭上了 20 世纪 90 年代密码学这趟过山车,在各种算法之间来回切换,并在此过程中发展出一套复杂的密码选择系统。
PGP 是一种通用加密工具,可用于任何类型的文件或消息,但电子邮件是它的关键应用之一。那么,经过 PGP 加密的邮件到底是如何传输的?嗯,谈不上好看,但和我们前面见过的那些乱局很一致。PGP 通常会把密文输出为二进制数据,或者输出为一种叫做“ASCII 盔甲”(ASCII-armored)的格式——本质上就是 base64,只是额外带了一个可选的 CRC 校验尾部(这项功能几十年前就已废弃)。这和现代密码学应用中广泛使用的 PEM 格式非常相似,而且并非巧合:PEM 是 Privacy-Enhanced Mail 的缩写,本身就是一个失败的电子邮件加密标准留下的产物,它还催生了相当多的 RFC。PGP 的邮件应用与 PEM 基本上是同时开发的,两者之间肯定也有思想上的相互影响。最终是 PGP 赢了,但它并没有把 PEM 的痕迹完全甩掉。
在实践中,ASCII 盔甲化的 PGP 载荷通常有两种发送方式:第一种是“内嵌”(inline)格式,在这种格式中,MIME 编码邮件的每个部分都会单独加密,并保留原本常见的 MIME 类型(例如 application/octet-stream),这样不支持 PGP 的邮件客户端就会把它们当作普通的二进制文件,用户可以另存后再用单独工具处理。第二种是“MIME”格式,在这种格式中,整个 MIME 编码后的邮件会整体加密,然后作为新的 MIME 文档放入类型为“application/pgp-encrypted”的消息中。后者在安全性上更好(元数据泄露更少),而且在以 PGP 为中心设计的客户端里通常也更友好、更优雅;但在不支持 PGP 的客户端里,它的表现会非常糟糕,甚至连附件都无法分辨。你当然还是可以借助外部 PGP 工具来处理邮件:先把整段正文保存下来,再做 MIME 解码、解密,然后再做一次 MIME 解码——光是读到这里,你是不是都已经有点烦了?
到了今天,这种混乱已经成了人们批评 PGP 的两大主要理由之一。PGP 并不是像 X.400 那样经过庞大、多方参与的标准化工程产物,而是少数人采取务实路径的结果。尽管如此,它成长于同样的环境,因此也保留了大体相同的伤痕。从底到顶,PGP 都非常复杂。几乎 PGP 加密邮件的每一个环节都有多个选项,其中一些已知是不安全的。现代工具大多采用了合理默认值,但仍有大量旧工具在继续使用。像 gpg 本身这样的关键工具,其界面之不友好,几乎到了设计史上的最差之列。PGP 用户面临的巨大困难,正是 1999 年开创性的“可用性安全”论文《Why Johnny Can't Encrypt》的研究对象(这篇论文在很大程度上开创了“可用性安全”这一领域),而其中提出的大多数批评,在 27 年后的今天对 PGP 实现仍然成立。
这就引出了 PGP 的第二个方面:密钥分发。我们已经大致看过 PGP 邮件是如何传输的,也就是加密邮件的第一个难题。但第二个难题呢——PGP 是否依赖目录系统?实际上,PGP 最早的事实使用方式是依赖的,因为它根本没有解决密钥分发问题。可是很早之后,PGP 发展出了一个新概念,叫做“信任网”(web of trust)。信任网,或 WOT,既是计算机安全领域最引人入胜、最迷人的概念之一,也是最荒唐、最愚蠢的概念之一。我试着简明扼要地解释一下。
你是 Alice,你想给 Bob 发一封邮件。至于“为什么”并不重要——这两个名字是密码学解释中永恒的角色,他们永远需要安全地交换消息。如果你在现实中认识 Bob,比如你们是同一机构的同事,那么密钥分发问题就很简单。你可以对一个密钥做一些计算,比如校验和,生成一个“指纹”;这个指纹对该密钥来说是唯一的,而且长度足够短,勉强可以靠肉眼读出来。你,Alice,走到 Bob 的办公室, попросила(此处应为“请求”)看一下他的密钥指纹。你把它记在便签纸上,然后在未来确保自己给 Bob 发邮件时使用那个指纹正确的公钥加密。到目前为止都很容易,但这并不能很好地扩展到 Bob 不在步行可达范围内的情况。
于是“网”就出现了:Bob 也许不方便让 Alice 直接接触到,因为比如他在别的地方工作,但 Alice 的同事 Charlie 可能几个月前参加过一个和 Bob 同场的会议。如果 Charlie 记录下了 Bob 的密钥指纹,回去之后就可以把副本给 Alice。既然 Alice 认识 Charlie,并且相信他是可信的,这就相当于不必亲自从本人那里拿到指纹的一个不错替代方案。
PGP 的 WOT 模型把这种“蹭网传密钥”(sneakernet)式的密钥分发方式编码进了软件实现。PGP 用户可以“签名”另一个用户的密钥,这相当于用密码学方式证明自己认为那就是正确的密钥。这些签名会上传到公开的“密钥服务器”(keyserver),任何人都可以查询某个密钥及其收到的签名集合。如果有足够多的密钥、足够多的签名,你就可以把整个系统看作一张图,并尝试在 Alice 和 Bob 之间找到“信任路径”,即使这需要六度分隔1。用于验证这些密钥和签名的缠结关系构成了一张网:信任网。
实践中,到 2010 年代,WOT 模型似乎就已经逐渐失势,而今天它则完全被抛弃了。它并没有像支持者希望的那样良好扩展,工具的可用性问题也打击了人们参与的积极性,而且实现与概念本身都复杂到足以让用户理解不足,从而削弱其优势。如今,WOT 存在一些根本性问题(主要与开放式密钥服务器有关),已经使它几乎无法使用,我认为把它称作一次失败的实验是公平的。再公平一点说,我们也应该注意到,WOT 多少启发了如今大多数现代端到端加密即时通讯工具里那些大幅简化的密钥验证方案。
从杂乱的学术起源,到演变为一个开放项目,PGP 在 20 世纪 90 年代和 2000 年代的学术圈与“密码朋克”社群中享有很高声望,但在企业环境中就没那么常见了。WOT 模型只有在不存在中心化维护目录的前提下才说得通;虽然 PGP 也可以与目录配合使用,但这并不是其倡导者所推崇的路径。PGP 主要被研究人员和爱好者,也就是密码学圈内人士使用。在企业世界里,还有另一个玩家:S/MIME。
S/MIME 起源于 RSA Security——这家公司是为了将 RSA 加密算法商业化而成立的。RSA Security 今天仍作为教师养老金基金的子公司存在,但其行业影响力整体上已经下降。回到 20 世纪 90 年代,RSA 正处于前沿地位,因此 1996 年他们推出面向电子邮件加密的解决方案时,很快引起了业界关注。
在接下来的两年里,RSA 的产品演进为 IETF 标准,名为 S/MIME,即 Secure MIME。S/MIME 之后又经历了多个版本,延续至今;在学术界和爱好者圈子里极为少见,但在企业和政府环境中相当常见,尤其是在 Microsoft Exchange 中更是如此(在 X.400 没能接管组织间邮件之后,Exchange 便把 S/MIME 作为首选安全邮件选项)。下面我们来看看 S/MIME 如何处理加密电子邮件的第一个难题:消息的传输编码。
正如名字所暗示的,这里面涉及 MIME。简单来说,流程是这样的:先把邮件准备成一个 MIME 文档,然后将其加密成 PKCS#7 文档。PKCS,即公钥密码学标准(Public Key Cryptography Standards),指的是 RSA Security 发布的一系列开放标准备忘录。PKCS#7 描述的是“密码消息语法”(Cryptographic Message Syntax,CMS),也就是一种标准容器,用于装载加密载荷以及各种元数据。在当时的术语中,S/MIME 被说成是用 PKCS#7 的“安全服务”来“增强”消息。今天我们仍在使用 PKCS#7 这个术语,主要是指按该格式序列化的密码证书。至于电子邮件,PKCS#7 已经被 IETF 的一个标准取代,它的名字很简单:CMS。
CMS 版本的邮件——记住,它本质上就是一个加密过的 MIME 文档加上一些密码系统相关元数据——接着会被编码为 PEM(功能上就是 Base64),并作为类型为“application/pkcs7-mime”的 MIME 邮件正文(是的,我刚刚说过 PKCS#7 在这个应用里已经没了,但这个名字自然还保留着)。这基本上等同于 PGP 邮件的 MIME 版本,优缺点也几乎相同:它相对优雅,能避免支持它的客户端里很多奇怪的边缘情况,但对不支持 S/MIME 的客户端则非常不友好,后者根本无法理解这条消息。它也保留了 MIME 的许多通用缺点;例如,RFC 甚至得专门写几段来解释为什么二进制数据要先 base64 编码,再转回二进制,然后又 base64 编码一次。不加这一层额外 base64,会破坏与非 S/MIME 工具的互操作场景!
总体来说,S/MIME 在这方面与 PGP 并没有那么不同,虽然我会说它整体上更简单、标准化程度更高。但这并不意味着它“简单”或“标准化得很好”,这些都只是相对而言。S/MIME 的实现仍然相当复杂,即便在运行同一软件的组织之间,也可能因为各种配置选项过多而出现互操作性问题。RFC 2311 里有这么一段,足以体现这种味道:
S/MIME 为仅封装数据提供一种格式,为仅签名数据提供若干格式,为既签名又封装的数据提供若干格式。之所以需要若干格式,是为了适应多种环境,尤其是签名消息。本文还描述了在这些格式之间进行选择的标准。
“需要若干格式以适应多种环境”——这几乎就是电子邮件的缩影……如果不是整个计算领域的缩影的话。
那么我们再来看加密电子邮件问题的第二个方面:密钥分发。在这里,S/MIME 采取了非常 X.400 式的迂回策略。据我所知,原始的 S/MIME 标准文档几乎完全没有以任何方式处理密钥分发,除了诸如“将证书验证到信任锚”之类含糊、顺带提及的话。这种做法看起来很奇怪,但如果放在 S/MIME 的发展背景下——它出自 RSA Security,后来又成为 IETF 标准,而再往后又由 Netscape 参与推动——就不奇怪了;Netscape 正是 SSL 的诞生地。S/MIME 本意是配合 PKI(公钥基础设施)使用的,而 PKI 的历史既微妙又有时相当模糊,但它是由 X.500 概念与包括 RSA Security 和 Netscape 在内的公司所做的实现工作共同促成的。换句话说,S/MIME 是和 SSL/TLS 一起成长起来的,并采用了相同的密钥分发架构。
S/MIME 邮件预期会附带所用密钥对应的证书(这也是采用 CMS 容器格式的原因之一),而这些证书则应由证书颁发机构签名。
S/MIME 邮件被预期要提供与所使用密钥相配套的证书(这也是 CMS 容器格式存在的原因之一),而这些证书据说应当由证书颁发机构(Certificate Authority)签名。
我在写这篇文章上花了很多时间,希望你读得愉快。如果你愿意资助我几美元,可以考虑在 ko-fi 上支持我。你将偶尔收到额外的、仅限订阅者的文章,也能分担一些提供这种手工打造、亲手搭建的万维网服务的成本,而这些服务是我直接从新墨西哥州阿尔伯克基提供的。
这并不完全等同于说密钥会从目录服务中检索,但如果你还记得,给我们带来这些概念的 X.500 本身原本就应该是_那个目录_,你就会发现二者是密切相关的想法。实际上,它们常常几乎就是一回事:S/MIME 一个经典的现实应用场景是微软 Active Directory 环境,在那里域控制器既充当目录(LDAP),也充当证书颁发机构,为填充该目录的用户签发证书。这意味着,从 LDAP 中检索密钥与对(AD)CA 进行证书验证,几乎是同一件事;而且你对“会有某种中央权威机构来维护目录”这一点的假设也完全相同。
这意味着,S/MIME 在与 X.400 曾经更成功的那些地方同样能够蓬勃发展。互联网电子邮件的诞生地——美国军方——选择用 S/MIME 来加密邮件。为此,他们拥有一个真正庞大的 Exchange 和 Active Directory 环境。一旦这些邮件离开军方,整套机制就会变得极其麻烦,因为要正确使用 S/MIME,就需要与军方的 Active Directory 域建立某种联邦关系……或者至少把他们的 CA 导入为受信任的 CA,而这对大多数邮件客户端来说都不太容易。
于是,这里就是经典的电子邮件加密版图:主要有两种方案,PGP 和 S/MIME;而它们各自都因为自己特有的原因,不适合大多数用户。正是在这种令人沮丧的僵局中,又出现了若干其他现象。
首先,我们先简要谈谈“现代”电子邮件加密,这里的“现代”有时几乎成了“专有”的委婉说法。如今出现了一批新的邮件服务提供商,提供某种内置的、托管式的端到端加密(E2E)。其中最知名的是 Protonmail。Protonmail 的主导性 E2E 加密实现是一套专有的、简化的系统,依赖 Protonmail 作为密钥目录和密码学实现。这与其他邮件服务商不互操作,因此我不认为这是真正意义上的“电子邮件加密”,而更像是一款随邮件附带提供的专有加密消息产品。Protonmail 确实提供了两个面向非 Protonmail 收件人的安全邮件发送功能:其一本质上是与 PGP 兼容的兼容层,让 Protonmail 的加密能够与 PGP 工具协同工作;其二则是一个传统的、由合规要求驱动的“安全邮件”产品,收件人实际上会收到一个网站链接,可以在网站上输入密码来取回消息——这同样并不是真正的电子邮件,而是一个与邮件 loosely 协同工作的独立产品。
其次,我们来稍微谈谈现实中电子邮件到底是如何被加密的,因为人们谈论电子邮件加密的方式,与现实世界实际发生的情况之间,存在着一种巨大得像大峡谷一样的脱节。我们先从区分几个术语开始:到目前为止,我讨论的是端到端(E2E)加密,这并不是一个严格定义清晰的技术术语,但通常指的是一段单一的加密载荷从一个人类用户到另一个人类用户之间传递时,始终保持加密、不被修改,也不被解密。与之相对的是非 E2E 加密,在这种情况下,一条消息可能会被加密和解密多次,而且使用的密钥可能由发送方和接收方之外的人所控制。我们还应该注意“静态加密”(encryption at rest)与“传输中加密”(encryption in transit)之间的区别:前者指数据在存储时是否加密(例如在磁盘上),后者指数据在网络上传输时是否加密。
电子邮件在邮件服务器之间通过 SMTP 交换,在邮件服务器与客户端之间通过 IMAP 交换 2。这两种协议如今都广泛通过加密来使用,要么使用 STARTTLS 方法,要么使用“真正的”TLS;这一区别我这里就不展开了。虽然我没有确凿的数据,但我几乎可以肯定,现实世界中的绝大多数电子邮件在传输过程中都是加密的,因为至少我能接触到的邮件服务器日志显示,绝大多数邮件服务器都在使用 STARTTLS 来保护它们的传输连接。客户端配置则是个更复杂的话题,但除非使用 TLS 保护的 IMAP,否则如今一般都被视为大错特错,而现代客户端应当积极引导用户走这条路。
这听起来很矛盾:我们前面花了这么长时间、这么无聊地讨论电子邮件加密为何一直没能真正普及。然后我却告诉你,几乎所有电子邮件其实都加密了。到底怎么回事?
首先,回想一下我们关于“传输中 vs. 静态”和“E2E vs. 非 E2E”的区分。邮件参与方之间的网络连接通常是加密的,这确实给我们带来了很多安全优势,但它并不能满足 PGP 和 S/MIME 所试图覆盖的全部需求。你的邮件并不能免受邮件服务提供商的窥视,收件方的邮件服务提供商同样也不行,因为电子邮件通常并不会在静态存储时加密,而服务提供商手里本来就掌握着所有密钥。它也不能提供完整性保护、不可否认性,或者许多其他有用的安全属性。
更糟糕的是技术现实。我前面指出,PGP 的一大批评就是它过于复杂,选项太多。这些年来,这导致 PGP 实现里出现了大量缺陷,也因为可用性不足而诱发了不少不安全的用户行为。传输中的邮件加密也有非常类似的问题。比如说,STARTTLS 本质上是一种机会主义机制。在其原始形式下,试图拦截 SMTP 会话的链路中攻击者,只需劫持会话并压制双方发出的 STARTTLS 提示,就能阻止它们协商切换到加密。这个简单的“降级攻击”是一个普遍存在的问题,也正是我说“只要不是真正的 TLS,就是错误做法”的主要原因。遗憾的是,在服务提供商之间传送邮件时,STARTTLS 恰恰是最广泛可用的选项。
话虽如此,还是有办法解决这个问题的。比如说,DANE 这种基于 DNS 的 TLS 证书分发方案,在 HTTP 领域已经失败,但在邮件传输中却有相当不错的采用率(虽然远未普及)。它很好地为邮件服务器提供了一种机制,让它们发现对端具备加密能力,而不需要通过 SMTP 通道本身来完成。即便没有 DNSSEC 去完整保护 DANE 通道,这也依然是一种改进,能够阻止许多常见攻击场景。还有一种更流行的方法,虽然比较笨拙,但它避免依赖 DNSSEC,从而防止对密钥通道的_第二次_链路中攻击:MTA-STS。MTA-STS 与 DANE 类似,它为邮件服务器提供一条独立通道,用来发现对端是否支持 TLS,但它使用 HTTPS 作为这条第二通道,因此继承了由 CA 根信任的 TLS 所提供的保护。
DANE 和 MTA-STS 都是在“提示”邮件服务器:某个对端支持 STARTTLS;一旦收到这样的提示,邮件服务器就知道自己应该_只_通过 STARTTLS 连接,即便实际 SMTP 通道上的邮件服务器声称不支持它。虽然这些额外组件令人遗憾,但它们在很大程度上缩小了降级攻击的窗口,而在支持 DANE 或 MTA-STS 的邮件服务提供商之间传输的邮件,其安全性其实相当不错,至少与大多数即时通讯方案不相上下。
这也意味着,你只要手动固定一些主要对端,就能大幅提升邮件安全性——例如,把你的邮件服务器配置成:无论其他情况如何,连接到 gmail.com 这类主要提供商时_必须加密_。这在某些行业里其实是相当常见的做法,包括内部维护一份“安全邮件目的地”列表,把业务伙伴和其他高频收件人都纳入其中。
在一些行业里,这种做法甚至被推到了极致:比如在医疗行业,存在一些医疗信息交换平台,它们运行的安全消息系统,实际上大多只是普通的邮件服务器,只不过被配置为拒绝任何非 TLS 的 SMTP 交换。这就足以满足 NIST 800-43 的建议,而这又足以满足 NIST 针对医疗信息的安全架构要求。你可能会对此感到惊讶,但这恰好说明了这个话题为什么会令人困惑:我们都知道“电子邮件不安全”,但这其实更多是“公共”邮件系统的_配置问题_,而不是技术层面的根本限制。真正要求 E2E 的合规标准其实很少;而一旦你不再要求 E2E,仅仅把邮件在传输中和静态状态下加密,就变得极其容易,甚至有时只要 SMTP 服务器支持 STARTTLS,再加上磁盘加密,就会在默认情况下自动实现。
如果你去看医疗行业的营销材料,有时会看到 STARTTLS 和 S/MIME 被描述为_彼此替代_的方案。从技术角度看,这说不太通,但你必须结合语境来理解。如果你必须通过那些你无法控制配置(或者至少无法了解其配置)的邮件服务器通信,那么除非你使用像 S/MIME 这样的 E2E 加密,否则你就没有办法确保消息在传输过程中一定会被加密。但如果你是在自己_可控_的服务器之间发信,那么你可以通过配置这些邮件服务器来确保传输加密,而在这一特定目标上,你就_不需要_ E2E 加密。这样来看,E2E 加密几乎像是对电子邮件设计缺陷的一种变通修补;如果你从这段比预期更长的旅程中带走了一点什么,我希望会是这一点:加密电子邮件的历史之所以如此古怪、充满各种失败的尝试,根本原因就在于,它本质上是在用 E2E 加密这一层“补丁”,去弥补电子邮件天生缺乏新一代消息方案开箱即用的那种安全水平。
这也有助于解释为什么它一直难以普及:问题其实不在于我们不会给电子邮件加密,我们_确实_在加密电子邮件。只是和大多数通信技术一样,“安全层”已经被推到了服务提供商身上,而不是用户身上。这当然有明显缺点,因为它要求用户信任这些服务提供商;但也有一个巨大的、显而易见的优点:如果加密对用户来说是透明的,人们就真的会去用它。