4、密码套件选择:对称加密、非对称加密与哈希算法对性能的影响
密码套件的选择,说白了就是给 TLS 握手选「工具包」。工具用对了,连接快如闪电;用错了,CPU 烧得发烫,用户还在那转圈圈。我见过太多团队把全部精力放在网络延迟上,结果一查,问题出在密码套件上。
这一节,咱们把密码套件拆开揉碎。从对称加密、非对称加密到哈希算法,逐个看它们怎么影响性能。
4.1 对称加密:AES-GCM vs ChaCha20
对称加密是数据传输阶段的「主力」。握手完成后,所有应用数据都用它加密。它的性能直接决定了吞吐量。
AES-GCM 是主流选择。硬件加速是它的王牌。现代 x86 处理器都有 AES-NI 指令集,加解密几乎不耗 CPU。我在项目中测过,开启 AES-NI 后,AES-128-GCM 的吞吐量能到 10 Gbps 以上。
ChaCha20-Poly1305 是 Google 力推的流密码。它不依赖硬件加速,纯软件实现就很快。移动端和 ARM 设备上,它经常反超 AES-GCM。
核心结论:
- 服务器端(x86):优先选 AES-GCM,硬件加速优势明显。
- 移动端 / IoT(ARM):ChaCha20 更省电、更快。
- 兼容性:两者都支持,建议同时启用,让客户端协商。
我踩过一个坑。有一次线上服务 CPU 飙升,查了半天发现是密码套件列表里把 AES-GCM 排在了后面,客户端协商到了 CBC 模式。CBC 没有硬件加速,还容易受时序攻击。嗯,从那以后我强制要求 GCM 或 ChaCha20 优先。
| 特性 | AES-GCM | ChaCha20-Poly1305 |
|---|---|---|
| 硬件加速 | 支持(AES-NI) | 不支持 |
| 软件性能 | 一般 | 优秀 |
| 移动端表现 | 中等 | 优秀 |
| 安全性 | 高 | 高 |
| 推荐场景 | 服务器、x86 环境 | 移动端、ARM、IoT |
4.2 非对称加密:RSA vs ECDHE
非对称加密用在握手阶段,交换密钥或验证身份。它的计算开销比对称加密大得多,是性能瓶颈的「重灾区」。
RSA 是传统方案。握手时客户端用服务器公钥加密预主密钥,服务器用私钥解密。RSA 的私钥操作(解密、签名)非常慢。2048 位的 RSA 解密,一次就要几毫秒。高并发下,CPU 直接被打满。
ECDHE(椭圆曲线 Diffie-Hellman 密钥交换)是现代方案。它支持前向安全性,即使私钥泄露,历史会话也不受影响。性能上,ECDHE 的密钥交换比 RSA 快得多。尤其是使用 Curve25519 或 P-256 曲线时。
注意:ECDHE 虽然快,但曲线选择很重要。P-384 比 P-256 慢 2-3 倍,安全性提升却有限。我个人习惯,默认用 P-256 或 Curve25519。
我曾经帮一个客户优化 API 网关。他们用了 RSA 2048 做握手,每秒只能处理 2000 个新连接。换成 ECDHE P-256 后,直接飙到 8000。你想想看,同样的硬件,性能差了 4 倍。
| 特性 | RSA 2048 | ECDHE P-256 |
|---|---|---|
| 握手延迟 | 高(私钥操作慢) | 低 |
| 前向安全性 | 不支持 | 支持 |
| CPU 开销 | 高 | 低 |
| 推荐场景 | 兼容旧设备 | 所有新部署 |
4.3 哈希算法:SHA-256 vs SHA-384 vs SHA-1
哈希算法用在握手消息的完整性校验和证书签名中。它的性能影响相对小,但也不能忽视。
SHA-256 是当前主流。安全性足够,性能均衡。TLS 1.3 默认使用 SHA-256。
SHA-384 是 SHA-256 的升级版,输出更长,安全性更高。但计算开销也更大,大约慢 30-50%。
SHA-1 已经被淘汰。浏览器会警告,安全性也有问题。千万别用。
建议:
- 证书签名:用 SHA-256,别用 SHA-1。
- TLS 1.3 握手:默认 SHA-256,不用改。
- 如果合规要求 SHA-384,确认硬件是否支持加速。
哈希算法的性能差异,在单次握手中几乎感觉不到。但在高并发场景下,积少成多。我记得有一次压测,把证书从 SHA-384 换成 SHA-256,CPU 使用率降了 5%。虽然不多,但免费的性能优化,何乐而不为?
4.4 知识体系:密码套件选择全景图
下面这张图,把密码套件的三个核心维度串起来了。你可以看到,对称加密、非对称加密、哈希算法各自影响哪个阶段,以及推荐的选择路径。
4.5 实战建议:如何配置密码套件
说了这么多,到底怎么配?我给出一个通用的推荐列表,你可以直接参考。
# 推荐密码套件列表(TLS 1.2 + 1.3)
# 优先级从高到低
# TLS 1.3 套件(固定,无需选择)
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
# TLS 1.2 套件(按性能排序)
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
配置要点:
- 优先使用 TLS 1.3,它的套件是固定的,性能最优。
- TLS 1.2 中,ECDHE + AES-128-GCM 是黄金组合。
- 把 ChaCha20 放在 AES-256-GCM 前面,因为移动端用户多。
- 禁用所有 CBC 模式、RC4、3DES、RSA 密钥交换。
我个人习惯,在 Nginx 里这样配:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
你想想看,密码套件选对了,性能优化就完成了一半。剩下的,就是调握手参数和网络了。