你在地址栏敲下一个域名,几十毫秒之后,你的浏览器和一台从未见过的机器已经共享了一串只有它们两个知道的字节。中间隔着你家的路由器、运营商的骨干网、若干个数据中心的负载均衡器,任何一环都能读到全部流量,也能篡改全部流量。
这里其实是两个完全不同的问题被塞进了同一次握手。
第一个问题是数学问题:两个人在一条被窃听的信道上,能不能商量出一个窃听者不知道的秘密?1976 年 Diffie 与 Hellman 给出了肯定回答,这个问题在纯数学层面已经解决了。
第二个问题不是数学问题:你怎么知道跟你商量秘密的这台机器,就是 bank.example.com 而不是中间某个路由器?密钥交换本身对身份一无所知——它能保证"我和某人建立了安全信道",但那个"某人"是谁,密码学无法凭空回答。这个问题必须引入信息之外的东西:一套由人和机构组成的、可以被贿赂、被攻破、被政府命令的现实系统。
这篇文章要讲清楚握手的三层协商到底在做什么,TLS 1.3 靠删掉什么把往返砍了一半,证书链和信任库的真实结构长什么样,证书透明度为什么只能是事后审计,Let's Encrypt 如何把证书从一件年费商品改造成一条自动化管线——以及为什么这整套东西最深的裂缝,是一个从设计第一天就存在、至今没有被真正修好的结构性事实。
破除误解
误解一:地址栏的锁头意味着"这个网站是安全的、可信的"。
不是。今天绝大多数证书是 DV 证书(Domain Validation,域名验证型),CA 在签发前只确认一件事:在签发的那一刻,申请者能够控制这个域名——能在这个域名的网站上放一个指定文件,或者能改它的 DNS 记录。CA 不审查申请者是谁、公司是否真实存在、网站在卖什么。所以一个精心仿冒的钓鱼站点拿到一张完全合法的证书是常态而非例外,它的锁头和真银行的锁头在浏览器里长得一模一样。证书断言的命题非常窄:"某个能控制这个域名的实体,在某个时刻持有这个公钥。" 它对这个实体的诚信度一个字也没说。
误解二:证书里的公钥用来加密会话密钥。
在 TLS 1.3 里完全不是。证书里的公钥根本不参与密钥交换,它一次会话中只被用来做一件事:验证服务器对握手记录的一次签名(CertificateVerify)。真正的会话密钥来自一对临时生成、用完即弃的椭圆曲线密钥(ECDHE),它们从不写进证书,也从不落盘。"客户端生成随机数、用服务器 RSA 公钥加密后送过去"那套流程叫 RSA 密钥传输,它是 TLS 1.2 及更早的一个可选模式,在 TLS 1.3 里被彻底删除了——因为它没有前向保密:谁将来拿到那把 RSA 私钥,就能解密之前录下来的所有流量。
误解三:证书被吊销之后浏览器就不认了。
吊销机制在现实中基本是失效的。传统的 OCSP(在线证书状态协议)在浏览器里是软失败的:查询超时或者响应器宕机,浏览器就当作"没问题"放行——而一个能中间人劫持你流量的攻击者,正好也有能力让你的 OCSP 查询超时。Adam Langley 那句被反复引用的判断"吊销检查是无用的安全带"说的就是这件事。这不是理论:2025 年 5 月 7 日起 Let's Encrypt 停止在证书里写入 OCSP 地址,2025 年 8 月 6 日直接关掉了 OCSP 响应器。整个行业的应对方式不是修好吊销,而是换一条路——把证书有效期压短到几十天,让"来不及吊销"这件事本身不再要命。
一次握手在协商三件互不相干的事
TLS 握手常被当成一件事,实际上它同时完成三项彼此独立的任务,理解它们的独立性是理解 1.3 的前提。
第一项:密钥协商。 双方各自生成一对临时的椭圆曲线密钥,交换公钥部分,各自算出同一个共享秘密。今天绝大多数握手用的曲线是 X25519(基于 Daniel J. Bernstein 2006 年设计的 Curve25519),其次是 secp256r1。因为私钥是临时的、握手完就丢弃,即使服务器的长期私钥日后泄露,也解不开历史流量——这就是前向保密(forward secrecy)。
第二项:身份认证。 服务器发来证书链,客户端验证这条链能上溯到自己信任的根。但这里有个容易被忽略的分工:
- 证书证明的是一个绑定关系:
bank.example.com这个名字对应这把公钥。它是一份可以被任何人复制的公开文件。 - 持有权必须另外证明。服务器紧接着发一条
CertificateVerify:用证书对应的私钥,对到此刻为止全部握手消息的哈希(transcript hash)做一次签名。
只有第二步才排除了"攻击者把别人的证书原样转发一遍"这种攻击。签的是 transcript 而不是一个固定字符串,意味着这个签名跟这一次会话的随机数、密钥交换参数全部绑死,无法被搬到另一次会话里复用。
第三项:加密套件。 确定用什么算法保护后续的应用数据。
TLS 1.2 的做法是把这三件事编码进一个字符串。看这个典型套件:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
└───┬──┘ └┬┘ └─────┬─────┘ └───┬──┘
密钥交换 身份认证 对称加密+模式 PRF 哈希
```四段全绑在一起,任意一段变了就是另一个套件。后果是组合爆炸:IANA 的 TLS 套件注册表里有三百多条记录,其中相当一部分是今天已知不安全的组合(RC4、CBC 模式、导出级弱密钥、乃至 NULL 加密)。而"可协商"本身就是攻击面——只要一个弱选项还留在协商表里,就存在把双方骗回那个选项的降级攻击。
TLS 1.3 的做法是把三件事拆开。套件字符串只剩下 AEAD 算法加哈希函数两段,密钥交换算法移到 supported_groups 扩展、签名算法移到 signature_algorithms 扩展。整个 TLS 1.3 只定义了 5 个套件:
| TLS 1.2 | TLS 1.3 | |
|---|---|---|
| 套件包含的信息 | 密钥交换 + 认证 + 加密 + MAC | 仅 AEAD + 哈希 |
| 注册套件数量 | 三百多条 | 5 条 |
| 密钥交换方式 | RSA 传输 / DHE / ECDHE,均可协商 | 只有(EC)DHE |
| 加密模式 | CBC、GCM、CCM、RC4 流密码 | 只有 AEAD |
| 完整握手往返 | 2-RTT | 1-RTT(恢复可 0-RTT) |
| 证书是否加密传输 | 否,明文可见 | 是 |
把三件事拆开之后,还有一层把它们重新缝合的机制:密钥派生贯穿整段对话。TLS 1.3 用 HKDF 构造一条派生链(Early Secret → Handshake Secret → Master Secret),每一步的输入都掺入当前的 transcript hash。握手最后双方各发一条 Finished,本质是对整段握手记录的 MAC。任何一个比特被中间人改过——包括"把版本号改低"或"把 supported_groups 里的强曲线删掉"——两边算出的 MAC 就对不上,握手当场失败。TLS 1.3 额外加了一道保险:一台支持 1.3 的服务器如果被迫降到 1.2,必须把 ServerHello.random 的最后 8 字节设成 DOWNGRD\x01 这个特定值,客户端见到就知道有人在中间动了手脚。
1.3 为什么能把往返砍一半
TLS 1.2 需要 2-RTT,原因是一条依赖链,不是实现效率问题。
客户端发出 ClientHello 时列出自己支持的所有套件。它此刻不可能发送任何密钥材料——因为密钥交换算法藏在套件字符串里,而选哪个套件是服务器的权力。选中 TLS_RSA_...,客户端要发的是用服务器 RSA 公钥加密的 premaster secret;选中 TLS_ECDHE_...,客户端要发的是某条特定曲线上的公钥;选中 DHE,客户端还得等服务器先把 DH 群参数发过来。三种情况要发的东西完全不同,所以只能等。 于是流程被钉死成:
RTT 1: ClientHello ──────────────────▶
◀── ServerHello, Certificate, ServerKeyExchange, ServerHelloDone
RTT 2: ClientKeyExchange, CCS, Finished ─▶
◀── CCS, Finished
应用数据(再叠加 TCP 的 1-RTT,总共 3-RTT 才发出第一个字节)
```TLS 1.3 打断这条依赖链的手法是解耦加投机。既然密钥交换算法不再由套件决定,客户端要猜的东西就从"三百多个套件"缩小成"用哪条曲线"——而实践中的答案高度集中,X25519 和 secp256r1 两条覆盖了绝大多数服务器。于是客户端干脆在 ClientHello 里直接把猜中那条曲线的公钥(key_share)附上。服务器一收到 ClientHello,两边的密钥交换材料就齐了,它当场算出握手密钥,从 ServerHello 之后的所有内容——包括证书本身——都是加密的:
RTT 1: ClientHello + key_share ────────▶
◀── ServerHello + key_share, {EncryptedExtensions,
Certificate, CertificateVerify, Finished}
{Finished} + 应用数据 ─────────▶
```这是一笔明确的交易,代价写在明处:
- 猜错的成本。服务器不支持客户端猜的那条曲线,就回一条
HelloRetryRequest指定它要的曲线,客户端重发——退回 2-RTT,而且比 1.2 多花了一轮无用的计算和带宽。协议押的是"猜中概率极高"这个经验分布,而不是最坏情况。 - 带宽换延迟。每次握手都要多带一份可能没用的公钥。X25519 的公钥只有 32 字节时这笔账无关痛痒,但后量子迁移把赔率改了:混合密钥交换 X25519MLKEM768 的
key_share是 1216 字节(ML-KEM-768 的封装公钥 1184 字节加 X25519 的 32 字节),ClientHello因此经常撑破一个以太网 MTU,需要拆成多个初始包。Chrome 自 124 版(2024 年 4 月)、Firefox 自 132 版(2024 年 11 月)默认启用它,到 2026 年,带后量子key_share的握手已经是主流形态。投机式握手在后量子时代的边际成本明显高于 2018 年设计它的时候。
0-RTT 是这个思路的极端版本,也是 1.3 里唯一带明确安全折扣的特性。 会话恢复时客户端用上次握手留下的 PSK,把应用数据和 ClientHello 一起发出去,延迟归零。但这份 early data:一没有前向保密(它用的是上次会话派生的密钥),二可被重放——网络上的攻击者原样录下来再发一遍,服务器无法从密码学上分辨。RFC 8446 为此专门写了一个附录警告,实践中的纪律是只允许幂等请求走 early data,POST /transfer 这类操作绝不能放进去。
但 1.3 最重要的成果不是加了什么,而是删了什么。 每一项删除背后都有一个具体的、已经造成过损失的攻击:
| 被删掉的东西 | 为什么删 |
|---|---|
| RSA 密钥传输 | 无前向保密;PKCS#1 v1.5 填充预言机,Bleichenbacher 1998 提出,2017 年 ROBOT 证明二十年后仍在大量服务器上可用 |
| 自定义 DH 群参数 | Logjam(2015):对常用的 512/1024 位群做一次性预计算,之后每次握手都能快速破解 |
| CBC 分组模式 | BEAST(2011)、Lucky 13(2013):MAC-then-Encrypt 结构的填充预言机与时序侧信道 |
| RC4 流密码 | 密钥流统计偏差可恢复明文,RFC 7465(2015)正式禁用 |
| TLS 层压缩 | CRIME(2012):压缩率随明文与已知内容的相似度变化,可逐字节猜出 Cookie |
| 重协商 | 2009 年的前缀注入攻击;改用 KeyUpdate 与握手后认证替代 |
| 导出级弱套件 | FREAK(2015):可被强制降级到九十年代出口管制留下的 512 位密钥 |
| MD5 / SHA-1 签名 | 碰撞构造已属实际可行 |
这份清单指向一个反直觉的结论:协议的灵活性本身是一种负债。TLS 1.2 的可协商项越多,它能兼容的老设备越多,它能被骗回的坑也越多。TLS 1.3 做的事情,是把大量"可协商"改成"不可协商"。
代价同样具体,而且相当难看。TLS 1.3 的 ClientHello 里,版本字段仍旧写着 0x0303(TLS 1.2 的编号),真实版本藏在 supported_versions 扩展里;握手中间还要发一条毫无作用的 ChangeCipherSpec,并且把客户端的 session_id 原样回显。这些全是中间盒兼容模式:早期部署时发现,大量企业防火墙、DPI 设备、老式负载均衡器一看到没见过的版本号就直接掐断连接。协议不得不伪装成 TLS 1.2 的样子才能穿过互联网。这是一份很清楚的证据——一个协议一旦部署到十亿台设备上,它的演进空间就被那些设备的实现 bug 锁死了。
证书链与信任库:那份文件到底是什么
握手里的身份认证那一半,落到实处是三层结构。
叶子证书(终端实体证书)写着域名和公钥,由中间 CA 的私钥签名。中间证书由根 CA 签名。根证书是自签名的——它的签名用自己的私钥做,验证也用自己的公钥,在密码学上等于什么都没证明。
根证书的可信度不来自任何签名,而来自一个事实:它被写进了你设备上的一份名单。这份名单就是信任库。整条链的信任,最终锚定在"你的操作系统或浏览器的发行方决定把谁放进那份文件"这个纯粹的人为决策上。
一张 X.509 v3 证书(格式由 RFC 5280 规定)真正决定验证结果的是几个扩展字段:
basicConstraints:CA:TRUE才允许签发下级证书,pathLenConstraint限制它下面还能再套几层。这个字段被漏检就是灾难——2002 年和 2011 年的多起实现漏洞里,验证代码没检查它,于是任何一张普通网站证书都能拿来给别的域名签证书。keyUsage/extendedKeyUsage:前者标明这把密钥能否用于签证书(keyCertSign),后者限定用途,serverAuth(OID1.3.6.1.5.5.7.3.1)才是网站证书。subjectAltName(SAN):域名的唯一合法来源。老式的CN(Common Name)字段自 Chrome 58(2017 年 4 月)起彻底不再被采信。authorityInfoAccess(AIA):指出上级证书和 OCSP 响应器在哪里。- SCT 列表扩展(OID
1.3.6.1.4.1.11129.2.4.2):证书透明度的凭据,下一节详述。
为什么要有中间证书这一层? 因为根私钥的更换成本是无穷大。根证书写在几十亿台设备的固件、系统镜像、Java 运行时里,其中很大一部分永远不会再收到更新。所以根私钥被放进离线的硬件安全模块,锁在有物理门禁的房间里,一年只上线几次用来签中间证书。中间证书出事可以第二天换一张,根出事只能等设备被淘汰。 这一层隔离是整个 PKI 里最实用的工程决策。
这里有一个几乎所有人都会搞错的地方:客户端不是在"验证服务器发来的那条链",而是自己重新构建一条路径(路径构建,见 RFC 4158)。服务器发的中间证书只是提示。由于交叉签名——同一份公钥可以被多个不同的上级签名——信任关系是一张有向无环图而不是一棵树,同一张叶子证书往往存在多条通向不同根的路径。谁能验证通过,取决于客户端的路径搜索算法有多聪明。
这个抽象的说法有一次代价极高的具体化。Let's Encrypt 的根 ISRG Root X1 早年不被老设备信任,于是它同时被老牌根 DST Root CA X3 交叉签名了一份。2021 年 9 月 30 日,DST Root CA X3 到期。新版客户端毫无影响——它们发现这条路径过期后,会回头找到直连 ISRG Root X1 的另一条路径。但 OpenSSL 1.0.2 及更早版本不做真正的路径搜索:它顺着服务器给的链一路走到过期的那张根,然后直接判定失败,不会回溯。那一天全球大量嵌入式设备、老 Android 机、未升级的服务器脚本集体报证书错误。(为了照顾老 Android,Let's Encrypt 又用一种"故意忽略过期字段"的技巧把兼容链续到了 2024 年 9 月 30 日。)
信任库还不止一个。 Mozilla NSS、Microsoft、Apple、Android 各有一份,Chrome 从 105 版(2022 年)起在桌面端启用自带的 Chrome Root Store 而不再跟随操作系统。这些名单互不相同。更麻烦的是补链行为也不同:Windows 和 macOS 会顺着 AIA 字段去网上抓缺失的中间证书,Firefox 不抓,改用预先下载的中间证书库。于是"在我的 Chrome 上是好的,在客户的 Android App 里报错"成了运维日常——服务器漏配中间证书时,能不能救回来完全取决于客户端。
| 根证书 | 中间证书 | 叶子证书 | |
|---|---|---|---|
| 签名者 | 自己 | 根或上级中间 | 中间 CA |
| 私钥存放 | 离线 HSM,物理隔离 | 联机 HSM | 服务器磁盘 |
| 典型有效期 | 20–25 年 | 5–10 年 | 200 天以内(2026 年上限) |
| 出事后如何更换 | 无法主动更换,等设备淘汰 | 吊销并换发,数日内完成 | 自动续期,数分钟 |
| 主流信任库中的数量级 | 一百多个,来自数十家机构 | 数千张 | 数亿张 |
证书透明度:为什么它只能是事后审计
2011 年发生了两件事。3 月,Comodo 的一家注册代理被攻破,签出 9 张伪造证书。7 月,荷兰 CA DigiNotar 被入侵,事后调查确认了 531 张伪造证书,其中 *.google.com 那张被用于在伊朗境内拦截约 30 万人的 Gmail 流量。DigiNotar 于 9 月 20 日破产。
真正值得注意的是它是怎么被发现的:Chrome 里对 Google 自家域名硬编码了公钥固定(pinning),伪造证书触发了这条规则,一个伊朗用户把报错贴到了论坛上。这个发现路径完全不可推广——总不能给全世界每个域名都在浏览器里硬编码一条规则。
证书透明度(CT,Ben Laurie、Adam Langley、Emilia Kasper 提出,RFC 6962,2013 年 6 月;2.0 版为 RFC 9162,2021 年 12 月)就是对这个问题的回答,而它的答案是一个明确的降级:放弃"阻止伪造签发",改为保证"伪造签发一定会被看见"。
机制上,CT 日志是一棵只能追加的 Merkle 哈希树。每张证书是一片叶子,向上两两哈希直到根。这个结构提供两种密码学证明:
- 包含性证明:证明某张证书确实在树里,只需 O(log n) 个哈希值。一百万条记录只要二十个哈希。
- 一致性证明:证明新版本的树是旧版本纯粹追加得到的——旧记录一条都没被删改。这是"只能追加"的强制手段,日志运营方想偷偷删掉一条记录,任何持有旧树根的观察者都能当场发现不一致。
CA 在签发前先把证书提交给日志(提交的是一份带毒药扩展 OID 1.3.6.1.4.1.11129.2.4.3 的预证书,这个关键扩展让它无法被当成真证书使用)。日志返回一张 SCT(Signed Certificate Timestamp),CA 把它嵌进最终证书。
SCT 是一张承诺书,不是一张批准书——理解这一点就理解了 CT 的性质。SCT 的含义是"我这个日志承诺在最大合并延迟(MMD,通常 24 小时)内把这条记录并进树里"。日志不做任何判断:它不知道 bank.example.com 应该由谁签发,也没有拒绝的权力和依据。日志是记账员,不是审批员。
所以控制点被推到了下游:监控者(monitor,包括域名所有者自己、Cloudflare、各 CA、安全厂商)持续扫描全部日志,看到自己域名下出现没申请过的证书就告警;浏览器厂商拿着日志作为证据链去追责。CT 的威慑力来自"一定会被记录",不来自"发不出来"。
Chrome 自 2018 年 4 月 30 日起要求所有新签发的证书必须带 SCT,规则随证书有效期变化:有效期 180 天以内的证书至少要 2 个来自不同日志的 SCT,超过 180 天要 3 个;且其中至少 2 个必须来自不同的日志运营方。 要求运营方多样性,是为了让"串通"这件事需要拉拢多个独立组织。
必须诚实说清 CT 的漏洞:包含性这个闭环并没有真正合上。 浏览器拿到 SCT 之后,通常不会去日志在线查询"这张证书真的进树了吗"——那样做等于把用户的浏览历史逐条报告给日志运营方,还要为每次握手多付一个往返。用于让客户端之间互相交换所见树根、从而检测日志给不同人看不同版本的 gossip 协议,从未大规模部署。结果是,"日志签了 SCT 却根本不入树"这种分裂视图攻击,实际防线是日志运营方的声誉、独立监控者的抽查和运营方多样性要求——是制度性的,不是密码学强制的。
即便如此,成效是可查的。近十年几乎所有 CA 除名事件的证据链都来自 CT 日志:Symantec 因大量误签(含 2015 年被 CT 抓到的 google.com 测试证书)在 Chrome 70(2018 年 10 月)被全面不信任;Entrust 因长期的合规问题,其 2024 年 11 月 11 日之后签发的证书不再被 Chrome 默认信任,随后它把公共证书业务出售;2025 年 5 月 30 日,Chrome 宣布对中华电信与 NetLock 撤销默认信任,覆盖 2025 年 7 月 31 日之后签发的证书。在 CT 之前,这类判决缺的从来不是意愿,而是证据。
ACME 与 Let's Encrypt:把证书从年费商品改造成基础设施
2014 年之前拿一张证书的流程是这样的:生成 CSR、填一张网页表单、上传、付几十到几百美元、等一到三个工作日的人工审核、可能还要接一个确认电话、下载一个 zip 包、手动拼装中间证书、手动装到服务器上——一年重来一次。
这个流程有两个后果。第一,HTTPS 在小网站上的覆盖率长期上不去。第二,证书过期成了一类常规事故:一年一次的手动操作,负责的人早换了岗,日历提醒早失效了。
Internet Security Research Group(ISRG) 于 2015 年 12 月 3 日开放 Let's Encrypt 公测,2016 年 4 月 12 日正式运营。它做对的关键不是"免费",是把上面那段人工流程整个换成了一个协议:ACME(RFC 8555,2019 年 3 月)。
ACME 的核心是把"证明你控制这个域名"变成一次机器可完成的挑战—应答。客户端先生成一对账户密钥(与证书密钥不同),此后所有请求都用它做 JWS 签名。要证明对域名的控制权,从三种挑战里选一种:
http-01:CA 给一个随机 token,客户端把token.<账户公钥指纹>这个串(key authorization)写到http://<域名>/.well-known/acme-challenge/<token>,CA 来取。最简单,但要求 80 端口可达,且不能签通配符。dns-01:把 key authorization 的 SHA-256 值做 base64url 编码,写进_acme-challenge.<域名>的 TXT 记录。唯一能签通配符证书的方式,代价是客户端需要持有 DNS 服务商的 API 凭据——这把一个高权限密钥引进了 Web 服务器。tls-alpn-01(RFC 8737):只用 443 端口,在 ALPN 协商到acme-tls/1时返回一张带特定扩展的自签证书。为不能开 80 端口的环境设计。
完整流程是:创建订单 → 拿到每个域名的授权 → 完成挑战 → CA 复验 → finalize 提交 CSR → 下载证书。一次 certbot certonly --webroot -w /var/www/html -d example.com 把这些全部跑完,包括把中间证书拼好。
90 天有效期是这套设计里最被误读的一个参数。 它不是一个安全强度参数,它是强制自动化的手段:90 天短到让人无法靠人工维持(一年四次,任何组织都会漏),又长到出问题时有足够时间修。这个设计把"自动续期"从一个可选的最佳实践,变成了唯一能活下去的方式。
这条路线现在还在继续收紧,而且两端同时在动。行业底线方面,CA/Browser Forum 于 2025 年 4 月 11 日通过 SC-081v3,把证书有效期上限从 398 天分三步压缩:2026 年 3 月 15 日起 200 天,2027 年 3 月 15 日起 100 天,2029 年 3 月 15 日起 47 天。Let's Encrypt 自身走得更前:2025 年 1 月引入 ACME 证书配置档(profile)选择,2025 年 2 月 20 日签出第一张短期证书,2026 年 1 月 15 日短期证书(有效期 160 小时,略超 6 天)与 IP 地址证书正式开放;默认档的寿命计划在 2027 年 2 月 10 日降到 64 天、2028 年 2 月 16 日降到 45 天。
代价必须说清楚,这套体系换来的不是纯收益:
- 续期链路成了新的单点故障。 cron 任务被误删、DNS 服务商的 API 令牌过期、撞上按注册域计算的速率限制——站点会在无人操作的情况下自己过期。故障模式从"人忘了"变成了"自动化静默失败",后者更难被发现,因为不再有人在看日历。
- 免费 DV 让钓鱼站拿到同样的锁头。 过去几十美元的价格门槛顺带过滤掉了一部分低成本欺诈,现在这个副作用没有了。这实际上是把开篇的"误解一"从一个模糊的认知偏差,变成了一个显而易见的事实。
- 集中化。 Let's Encrypt 今天覆盖的域名数量级远超任何单个商业 CA,它的一次运维事故或根证书问题的爆炸半径也相应更大——2021 年那次交叉签名到期就是预演。为了修复"信任分散在太多 CA 手里"的问题,我们造出了一个体量前所未有的单一 CA。
- 吊销进一步退化。 OCSP 被放弃有两个原因:隐私(CA 能实时看到哪个 IP 在访问哪个网站——这是一条真实的全网监控通道)和成本。取而代之的是 CRL 名单分发加上短寿命证书。这等于承认:吊销做不到实时,那就让证书本身活得比事故响应时间还短。
最脆弱的地方:任何一个受信任 CA 都能为任何域名签发证书
前面所有机制加起来,都没有触碰这套体系的地基缺陷。
验证逻辑是"或"关系。 你的浏览器接受一百多个根中任意一个签出的合法链。你的银行域名可以由某个你从未听说过的、注册在另一个司法辖区的 CA 签发一张完全合法的证书,你的浏览器会毫不犹豫地显示锁头。
这个"或"决定了风险的算术方向。在"与"结构里(比如多重签名),增加环节会降低失败概率;在"或"结构里,增加环节只会提高失败概率。系统的安全性等于最弱的那个 CA,而不是所有 CA 的平均水平。而这一百多个 CA 里,有的资金紧张,有的运营团队只有几个人,有的可以被所在国政府依法要求配合。
围绕这个缺陷打过的补丁,各自的性质和结局值得逐条摆开:
| 机制 | 想做什么 | 实际效果与失败之处 |
|---|---|---|
| HPKP(RFC 7469, 2015) | 站点用 HTTP 头声明只接受特定公钥的证书 | 已废弃。 自锁风险致命:配错一次加上长 max-age,站点会把自己封锁数月且无法自救;还能被攻击者用作勒索工具。Chrome 72(2019 年 1 月)移除支持 |
| CAA(RFC 6844/8659) | DNS 记录声明"只有这几家 CA 可以给我签" | 有效但只约束守规矩的 CA。 2017 年 9 月 8 日起 CA 必须检查,但被攻破或恶意的 CA 可以直接无视——它是一条自律规范,不是技术强制;而且它依赖 DNS,DNS 本身也可能被劫持 |
| CT(RFC 6962/9162) | 让所有签发行为公开可查 | 只提供事后可见性,不阻止任何一次签发 |
| MPIC(SC-067v3, 2024 通过) | 域名验证与 CAA 检查必须从多个地理分散的网络位置各做一遍,结果一致才签发 | 2025 年 3 月 15 日起强制,2025 年 9 月 15 日起必须按结果拒发。唯一真正降低了攻击成功率的一条——针对 BGP 等价前缀劫持,攻击者只能污染部分网络路径时就骗不过多视角复验。但它只挡网络层攻击,挡不住 CA 自身被攻破或被行政命令强制 |
| 缩短有效期 | 压缩伤害窗口 | 不阻止签发,只把一张伪造证书的可用时长从 398 天压到几十天。这是对"吊销不可靠"的正面承认 |
症结在于一个从未被填上的表达能力空白:域名所有者无法说出"我的域名只该由 X 签发,并且这条声明必须被强制执行"。 CAA 说出了前半句,但强制执行的是 CA 自己——等于让被约束者自我约束。
理论上做对了的方案是 DANE(RFC 6698):把证书或公钥的指纹直接放进受 DNSSEC 保护的 TLSA 记录里。这样域名所有者通过 DNS 层直接宣告自己的密钥,绕开 CA 体系。没有任何一家主流浏览器采纳它。 原因有三:DNSSEC 全球部署率长期偏低;额外的 DNS 查询链条给每次连接增加延迟和失败点;以及一个尴尬的事实——DNSSEC 的信任模型同样是层级式的,它只是把"某个第三方能替你说话"这个权力从一百多家 CA 转移给了根区与顶级域运营方,并没有消灭这个结构本身。
于是今天这套体系的真实形态是一次明确的取舍:用"事前无差别授权 + 事后全局审计 + 短寿命",替换掉了"事前精确授权"。 后者从未被造出来过,因为它要求全球每一个域名所有者都持续、正确地维护一份自己的授权声明,并要求全球每一个客户端都能可靠地取到它——这在四亿多个已注册域名的规模上不成立。而前者可以运维、可以自动化、可以扩展。
CT 加上有效期压缩再加上 MPIC 的组合,本质是一句话:我们防不住伪造签发,所以我们让它藏不住,也用不久。 这个判断在工程上是清醒的,但它意味着一件事——你今天访问银行网站时的那份安全保证,最终依赖的不是一条数学定理,而是一群互相监视的组织愿意继续互相监视。
跨域连接
- 市场失灵与公共品:Let's Encrypt 不是慈善,它是一次教科书式的公共品补位。证书带有强烈的正外部性:加密一个站点,收益的很大一部分落在访问它的陌生人和整个网络的整体安全水位上,而成本全部由站点所有者承担。这种收益与成本的错配必然导致供给不足——2015 年之前 HTTPS 覆盖率长期停在低位,正是外部性未被内部化的典型症状。更麻烦的是激励结构:付钱的是网站,承担风险的是用户,而 CA 的收入与它的审慎程度几乎无关,于是"低价快速签发"在竞争中反而占优——这是一种委托代理错配,也解释了为什么单靠市场竞争无法自发提高 CA 质量。ISRG 的解法是把这项服务改成非营利供给并将边际价格降为零,同时用协议把交易成本压到接近零。这一步同时揭示了另一件事:这个市场原本的高价维持的不是安全性,而是人工审核环节的行政成本。
- 公共池塘资源治理:根信任库是一件典型的公共池塘资源,而 CA/Browser Forum 是围绕它长出的治理机构。Ostrom 归纳的自治规则在这里几乎逐条对应:清晰的边界(谁能进入根信任库由基线要求界定)、集体选择安排(浏览器厂商与 CA 共同投票通过 SC-081v3 这类提案)、监督(CT 日志让所有成员的行为对所有人可见)、以及分级制裁(从要求整改、到限制新证书受信、到 Entrust 与中华电信那样的完全除名)。资源的"可枯竭性"也很实在:每多信任一家 CA,全体用户承担的风险就增加一分,而收益只归那家 CA——这是标准的公地悲剧激励结构。真正让制裁可执行的是退出成本的不对称:浏览器厂商可以单方面把一家 CA 移出名单,而 CA 一旦被移出就失去全部业务,DigiNotar 在破产前只撑了三周。治理有效不是因为规则写得好,是因为惩罚的可信度极高。
- 工业工程与质量管理:CT 与短寿命证书这两步,正好复刻了质量管理从终检走向过程控制、再走向小批量的完整路径。Shewhart 与 Deming 的核心论断是"质量不能靠事后检验保证",而 PKI 走的恰恰是它的对偶版本:既然事前的签发控制无法保证(任何 CA 都能签任何域名),那就把全部签发行为纳入一条可追溯的记录流,用统计式的持续监控代替不可能实现的准入审批——CT 日志在功能上就是一张覆盖全行业的控制图,monitor 扫描日志等价于对异常点的持续侦测。缩短有效期则是另一条独立的工业原理:批量越大,缺陷被发现时已经流入下游的数量越多。把证书有效期从 398 天压到 47 天,就是把批量缩小到约十分之一,让"从缺陷产生到被清出系统"的窗口同比例收缩。这也解释了为什么行业选择缩短寿命而不是修好吊销——精益生产早就得出过同样结论:与其改进不良品的召回流程,不如把批量缩小到召回不再是主要手段。
- 网络科学:把信任关系画成图,这套体系的脆弱性就变成了一个可以计算的拓扑性质。验证是析取("或")关系:叶子节点只要存在一条通往任意可信根的路径即可,因此攻击面随根的数量线性增长——这与合取型系统(每个环节都必须通过)的可靠性方向完全相反,也是"信任库越大越不安全"这个反直觉结论的来源。交叉签名进一步把这张图从树变成有向无环图,同一叶子存在多条到不同根的路径,验证从此不是"检查一条链"而是一次图搜索,而不同客户端的搜索算法差异直接造成了 2021 年 DST Root CA X3 到期时"有的设备正常有的全崩"的分裂结果。度分布同样关键:签发量高度集中于少数节点,Let's Encrypt 这类超级枢纽的失效影响面与一家小 CA 相差数个数量级,因此"随机故障影响有限、针对枢纽的攻击后果严重"这条无标度网络的经典结论,在这里是可以直接用来做风险排序的。
- 数字权利与隐私:隐私不是这套体系的附加考量,它是近年几个关键设计改动的直接驱动因素。OCSP 的废弃就是完整案例:为了检查一张证书是否被吊销,浏览器必须实时告诉 CA "某个 IP 正在访问某个网站",这条链路在结构上就是一条覆盖全网的浏览行为监控通道,无论 CA 是否真的记录。Let's Encrypt 在 2025 年关闭 OCSP 响应器时把隐私列为首要理由,行业转向 CRL 名单分发与短寿命证书——这是一次明确的取舍:牺牲吊销的实时性,换取查询行为不再外泄。同样的逻辑在握手层重演:TLS 1.3 把证书移入加密段,使被动监听者再也看不到你访问的是哪个站点,但 SNI 字段为了让一个 IP 上的多个站点共存,仍然明文暴露域名,Encrypted Client Hello 正是为堵上这个最后缺口而生。这条线索还揭示了一个反复出现的结构性张力:安全机制往往需要一个第三方"知道你在做什么"才能生效,而每一次这样的机制都会成为潜在的审查与监控基础设施——这正是 DANE 未被采纳、以及各国对 CA 施加管辖权之所以令人不安的真正原因。
参考文献
- Rescorla, E. The Transport Layer Security (TLS) Protocol Version 1.3. RFC 8446, IETF, 2018 年 8 月.(1-RTT 握手流程、密钥派生链、被移除特性清单、0-RTT 重放风险警告的一手出处)
- Laurie, B., Langley, A., Kasper, E. Certificate Transparency. RFC 6962, IETF, 2013 年 6 月;及 Laurie, B. 等. Certificate Transparency Version 2.0. RFC 9162, IETF, 2021 年 12 月.(Merkle 日志结构、SCT 语义、包含性与一致性证明)
- Barnes, R., Hoffman-Andrews, J., McCarney, D., Kasten, J. Automatic Certificate Management Environment (ACME). RFC 8555, IETF, 2019 年 3 月.(账户密钥、订单与授权状态机、http-01 与 dns-01 挑战的规范定义)
- Cooper, D. 等. Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. RFC 5280, IETF, 2008 年 5 月.(
basicConstraints、keyUsage、SAN 等扩展的权威语义) - Fox-IT. Black Tulip: Report of the Investigation into the DigiNotar Certificate Authority Breach. 荷兰政府委托调查报告, 2012 年 8 月.(531 张伪造证书、入侵时间线与对伊朗用户的实际影响)
- CA/Browser Forum. Ballot SC-081v3: Introduce Schedule of Reducing Validity and Data Reuse Periods, 2025 年 4 月 11 日通过;Ballot SC-067v3: Require Domain Validation and CAA Checks to Be Performed from Multiple Network Perspectives, 2024 年 8 月通过.(200/100/47 天时间表与 MPIC 强制生效日期)
延伸阅读
- Ristić, I. Bulletproof TLS and PKI, Second Edition. Feisty Duck, 2022——目前最完整的一本实务参考,把协议细节、历史攻击与服务器配置串成一条线,适合在读完协议 RFC 之后补上"这些设计在真实部署里怎么塌的"。
- Let's Encrypt 官方博客:《Ending OCSP Support in 2025》(2024 年 12 月) 与《Decreasing Certificate Lifetimes to 45 Days》(2025 年 12 月)——两篇公告把"为什么放弃吊销、为什么改用短寿命"的推理写得非常直白,是观察一项基础设施如何主动淘汰自己旧机制的一手材料。
- Google Chrome Root Program Policy 与 Chrome Certificate Transparency Policy(持续更新的在线文档)——想知道一家 CA 究竟凭什么被信任、又凭什么被除名,规则全部写在这两份文件里,包括 SCT 数量要求随证书有效期变化的具体条款。