AES-GCM 还是 ChaCha20-Poly1305:为 VPN 选择数据加密算法
在有硬件加速的服务器上,AES-GCM 是显而易见的选择;ChaCha20-Poly1305 则是在没有硬件加速时依然跑得好的那一个。也许你的协议会替你做决定。
两个名字都是 AEAD 构造,两者都已标准化,而在当今的 x86 服务器上,无论哪一个都能毫不费力地占满千兆链路。一旦离开那台服务器,选择就不再随意:廉价路由器、旧手机和虚拟设备往往没有 AES 加速,那里的差别很大。所以比较的重点不是哪个密码更快,而是哪个密码在这组端点上跑得好,以及协议是否真的提供了选择。
同样的工作,不同的内核
两种构造都在一趟处理中同时给出机密性和完整性,并对关联数据进行认证,因此 VPN 协议用它们保护数据通道。差别在里面:AES-GCM 是计数器模式下的 AES 分组密码,配一个基于 GF(2^128) 的多项式认证器;ChaCha20-Poly1305 则是 256 位密钥的流密码,配一个独立的单次认证器。
运营上真正重要的是共同点:两者在 nonce 复用时都会灾难性失效,都需要按密钥管理 nonce 空间,也都不能修复一个认证了错误内容的对端。写着 AES-256-GCM 的配置并不比写着 CHACHA20-POLY1305 的更安全;只要实现正确,两者都很强。
AES-GCM 在哪里胜出
大多数现代 CPU 都有 AES 专用指令:x86 上的 AES-NI、ARMv8 上的加密扩展,以及较新的 POWER 与 RISC-V 设计中的对应物。有这些指令时,GCM 每个周期级可以并行处理多个分组,软件实现的好坏变得无关紧要。这是服务器、台式机和当前手机的常见情形,也是数据中心里"用 AES"成为合理默认值的原因。
问题出在二阶情形。没有专用指令时,软件 AES 很慢,而查表式的软件实现恰恰是长期存在缓存时序问题的那一类。运行在虚拟机里的 VPN 集中器,如果宿主机没有把 AES 标志透传给客户机,就正好属于这种情形;而且很容易被忽略,因为宿主机 CPU 确实具备该特性。
要检查进程实际看到什么,而不是 CPU 支持什么:在 Linux 上用 grep -o aes /proc/cpuinfo | head -1,或者查看 hypervisor 的 CPU 模型里对应的特性标志。
ChaCha20-Poly1305 在哪里胜出
ChaCha20 在可移植软件里很快,因为它只用加法、旋转和 XOR,其实现从设计上就避免了依赖密钥的表查找。在没有 AES 加速的设备上,这是实打实的优势,也正是 WireGuard 选择它的原因:WireGuard 协议说明把 ChaCha20-Poly1305 列为唯一的数据加密算法,没有备选。
这一个选择说明了一件有用的事:在 AES 有加速的硬件上,WireGuard 相比 AES-GCM 会损失一些吞吐,作者接受这一点,换取在手机、家用路由器和容器宿主机上可预期的表现。如果你的设备群主要是小型 ARM 盒子,这笔交换对你有利。
相反的情形是繁忙的 x86 集中器:那里带 AES-NI 的 AES-GCM 是更快、支持更好的路径,而 ChaCha20 每千兆要付出可观的 CPU。两种构造都不是弱点;问题在于你的硬件执行哪一个更便宜。
你的协议实际允许你选什么
| Protocol | What you get |
|---|---|
| WireGuard | ChaCha20-Poly1305 only; no negotiation |
| OpenVPN 2.5 and later | Data channel negotiated from data-ciphers: AES-256-GCM, AES-128-GCM, CHACHA20-POLY1305 |
| IPsec / IKEv2 | AES-GCM as a combined-mode transform, or ChaCha20-Poly1305 where both peers implement it |
| OpenVPN control channel | TLS decides; TLS 1.3 offers AES-GCM and ChaCha20-Poly1305 suites |
注意 OpenVPN 里的分离:控制通道和数据通道是分开协商的,所以你在 TLS 里看到的套件,并不能说明保护载荷的那个密码。会话摘要会同时报告两者,只读其中一个正是常见的困惑来源。
在 OpenVPN 里,数据通道的密码来自两端的 data-ciphers 列表。如果服务端和客户端的列表没有交集,连接要么回退到 data-ciphers-fallback 允许的算法,要么直接失败,而这种失败通常被归咎于错误的层次。两端设置同一份列表,然后在日志里确认协商结果,而不是假设列表顺序被遵守了。
依据关于部署的三个事实来决定
第一,端点有 AES 加速吗?如果每个对端都有,AES-GCM 是更便宜的选择,也是多数受维护配置的默认值。如果有相当比例是小型路由器或旧手机,ChaCha20-Poly1305 可以避免设备群的尾部成为容量瓶颈。
第二,协议到底给不给选择?用 WireGuard 时决定已经替你做了,有用的工作是确认周边工具没有悄悄替换成别的东西。用 OpenVPN 和 IPsec 时,答案是配置里的一行,以及一个需要记录的协商结果。
第三,两端能达成一致吗?某个对端不实现的密码不是性能问题,而是故障。这就是对端列表比任何基准测试都重要的原因:混合设备群需要能力的交集,而不是最快那台机器的偏好。
如果真要测量,就让设备、端点和负载保持一致,只改一个变量。比较不同区域两台服务器的测试测的是路由,不是密码;笔记本上的基准测试,对 CPU 标志被遮蔽的容器宿主机什么也说明不了。比较之后,把实际协商出的密码记下来:这份记录比基准测试更有价值。