为什么 AES-256 无法描述一套 VPN 加密方案
一套方案要完成四项职责:批量加密、完整性、密钥建立与对端认证。一个密码名只覆盖其中一项,且只在一个层面。
问一个 VPN 用什么加密,答案往往只有一个词:AES-256,或者 ChaCha20,或者也许是 WireGuard。这个答案只点出一个层面的一个部件,而真正保护连接的是由四种不同职责共同构成的一组算法。把部件当成整体,是这类讨论中最常见的错误,它制造出根本无法得出结论的对比。
一条连接里的四件工作
批量加密把数据通道的明文变成密文,它的密钥是推导出来的,而不是传送过去的。完整性保护负责发现改动,即便同一种构造同时完成两件事,它仍是独立的工作。密钥建立产生共享的流量材料,而对端认证决定另一头究竟是谁。四项中缺任何一项,连接都不安全,剩下的部分再强也没用。
有些设计把两种职责合而为一。AES-GCM 与 ChaCha20-Poly1305 属于认证加密构造,机密性与完整性一并得到;AES-CBC 则不是,它需要一个带独立密钥的独立消息认证码。所以把提案当作一堆互不相关的数字来读,会误读那些成对设计的东西。
职责还分布在不同层面上,因此同一个词在两个产品里可能含义不同。ESP 里的分组密码与 TLS 里的分组密码,是不同协商中、要求不同的同一个原语。所以引用一个原语却不说明其模式与层面,可能比什么都不说更糟。
为什么一个密码名几乎说明不了什么
不妨认真对待 AES-256 这个说法:它指明一种分组密码和一个密钥长度。它没有说明工作模式,没有说明是否提供完整性,也没有说明密钥如何建立、对端如何认证。两个产品都可以宣传 AES-256,却在其余所有方面不同,其中一个把它与未认证的模式搭配,另一个把它用于带现代密钥交换的 AEAD 模式。
TLS 1.3 把这种分离写进了标准,对学过旧术语的人来说这是一处有用的更正。它的密码套件只命名 AEAD 与哈希,而密钥交换组与签名算法作为独立参数单独协商。因此 TLS 1.3 的套件名与 TLS 1.2 的套件名不能在同一基础上比较,尽管二者会出现在配置文件同一个字段里。直接比较两个字符串的审计者,会得出协议并不支持的结论。还要读协商出的组与签名参数,否则比较并不完整。
WireGuard 走了相反的路,几乎完全取消了协商:协议规定固定的算法集合,两套实现要么互通,要么不互通。这是合理的设计选择,也意味着 WireGuard 协商哪套算法这个问题没有值得比较的答案。如果你在审计它,把规范读一遍,然后去审计它周边的密钥管理,而不是协商过程。
层面决定术语
IPsec 部署会协商两次:控制通道的 IKE 提案与数据的 ESP 变换,二者可以合法地不同。读了前者就以为它描述后者,是审计中常见的困惑来源,因为配置文件两者都提到,而真正有意思的是后者。
| Layer | What is negotiated there | What it does not cover |
|---|---|---|
| IKE proposal | Algorithms and groups for the control channel that builds the tunnel | The algorithms protecting the data itself |
| ESP transform | Encryption and integrity for tunneled packets | Peer identity, which authentication already settled |
| TLS handshake | AEAD and hash, plus separately negotiated groups and signatures | Routing, authorization or retention policy |
| WireGuard | Nothing; the algorithm set is fixed by the protocol | Everything above the cryptographic arrangement |
某个库里存在的名字,不会自动在另一条数据路径上实现。所以我们的产品支持 AES-256 这句话比听起来要弱,也正因如此,互操作问题通常靠找出仍被维护的交集来解决,而不是在两边开启所有旧算法。
TLS 1.3 规范是这种分离最清晰的公开例子,因为它把套件定义为成对的东西,并把其余部分交给各自的协商。一旦熟悉这种形状,IPsec 提案与 WireGuard 唯一固定的集合,读起来就是同一想法的不同变体。
读协商出来的结果,然后停下
配置好的提案不是双方实际选择的证据。活着的会话才带着答案,任何主流实现都能在不抓包的情况下报告它。
openssl s_client -connect vpn.example.net:443 -brief
ipsec statusall
wg show
在输出里要读选中的算法,而不是被提议的清单。如果答案比策略意图更弱,修正落在某一侧的提案配置上,而在现代实现里,不一致通常表现为协商失败,而不是静默降级。
然后记住这套方案不覆盖什么。路由、应用权限、日志与留存是各自独立、各有评审的决策,兼容的密码学配置对它们什么也没说。关于密码的讨论值得进行,但它回答的问题,比大多数人真正问的要窄。
把术语保持精确,论证就会变短。一套方案是一个层面上的一组职责,一个密码是一个部件,而协商出的结果是唯一能描述你真正拥有的那条连接的东西。对比中其余的一切都是装饰。