2. 密码学基础回顾:TLS 的三大基石
搞 TLS 1.3 之前,我们得先把密码学的基本功练扎实。说白了,整个 TLS 握手就是一场精心设计的「密码组合拳」——对称加密、非对称加密、哈希函数各司其职。这一章我带你快速过一遍它们在 TLS 里的真实角色,顺便讲讲我在生产环境里踩过的坑。
2.1 对称加密:AES 为什么是 TLS 的默认主力
AES(Advanced Encryption Standard)是目前最广泛使用的对称加密算法。它的核心特点是:加密和解密使用同一个密钥。速度快、效率高,适合加密大量数据——TLS 握手完成后,真正传输的 HTTP 内容就是用 AES 保护的。
我记得 2018 年给一个金融客户调优 HTTPS 性能时,发现他们的老旧服务器只支持 AES-CBC,结果每次握手都要多耗几个毫秒。后来我建议升级到 AES-GCM,吞吐量直接翻了一倍。为什么?因为 GCM 模式自带认证,不需要额外的 HMAC 步骤。
- 握手完成后,用协商出的对称密钥加密所有应用数据(HTTP、HTTP/2 帧等)
- TLS 1.3 强制要求使用 AEAD 模式(Authenticated Encryption with Associated Data),最常用的是 AES-128-GCM 和 AES-256-GCM
- GCM 同时提供机密性和完整性,一次计算搞定两件事
几种 AES 模式对比
| 模式 | 是否认证 | TLS 1.3 支持 | 我的建议 |
|---|---|---|---|
| AES-CBC | 否(需额外 HMAC) | 不支持 | 别用了,Padding Oracle 攻击风险高 |
| AES-GCM | 是(内置认证) | 是 | 首选,性能高、安全 |
| AES-CCM | 是(内置认证) | 支持(较少见) | GCM 不够时再用,效率略低 |
2.2 非对称加密:RSA 与 ECC 的分工
非对称加密解决了一个根本问题:两个从未见过面的人,怎么安全地商量出一个共同的对称密钥? 答案是用公钥加密、私钥解密。但 RSA 和 ECC 在 TLS 里的戏份完全不同——尤其在 TLS 1.3 里。
RSA:曾经的王者
RSA 依赖大整数分解的数学难题。在 TLS 1.2 及之前,它既用来做密钥交换(Client 用 Server 的公钥加密 Pre-Master Secret),也用来做数字签名。但 TLS 1.3 做了一个重大改变:不再使用 RSA 做密钥交换,只保留它的签名功能。
为什么?因为 RSA 密钥交换是「静态」的——如果私钥泄露,之前所有通信记录都能被解密(前向安全性缺失)。而 ECDHE 每次握手都生成临时密钥对,私钥用完就丢掉,彻底解决了这个问题。
ECC:TLS 1.3 的黄金搭档
椭圆曲线密码(Elliptic Curve Cryptography, ECC)在同等安全强度下,密钥更短、计算更快。TLS 1.3 官方推荐的密钥交换就是基于 Curve25519 或 P-256 的 ECDHE。签名则可以用 ECDSA 或 Ed25519。
我在一个 IoT 项目里尝到了甜头——设备端 CPU 很弱,RSA 2048 做签名验证要几十毫秒,换成 ECDSA 之后变成了 2 毫秒。关键是功耗也跟着降下来了。你想想看,对于移动端或嵌入式设备,ECC 几乎是最优解。
RSA vs ECC 签名对比
| 特性 | RSA-2048 | ECDSA P-256 | Ed25519 |
|---|---|---|---|
| 公钥大小 | 256 字节 | 32 字节 | 32 字节 |
| 签名大小 | 256 字节 | 64 字节 | 64 字节 |
| 验证速度 | 慢 | 快 | 非常快 |
| TLS 1.3 推荐度 | 兼容(不推荐新业务) | 推荐 | 推荐(RFC 8446 可选) |
2.3 哈希函数:SHA-256 的守护任务
哈希函数是密码学里的「数字指纹」。它把任意长度的数据变成固定长度的摘要,而且不可逆。在 TLS 1.3 里,SHA-256 几乎无处不在:证书签名验证、密钥派生、握手消息完整性保护,每一步都离不开它。
具体来说,SHA-256 在 TLS 中有这三项核心职责:
- 签名验证: 验证证书链时,CA 的签名就是先对证书内容做 SHA-256 哈希,再用私钥加密这个哈希值。客户端用公钥解密后比对哈希值,就知道证书有没有被篡改。
- 密钥派生: TLS 1.3 使用 HKDF(基于 HMAC 的密钥派生函数),而 HMAC 底层就是 SHA-256。每次握手会跑很多次 SHA-256,把共享秘密「拉伸」成加密密钥、认证密钥、初始化向量等。
- Finished 消息: 双方在握手最后发送 Finished 消息,里面包含了之前所有握手消息的 SHA-256 哈希。一旦中途被篡改,哈希值对不上,握手立刻失败。这防止了中间人攻击。
2.4 三种密码原语在 TLS 1.3 中的协作流程
说了这么多,它们到底怎么一起工作的?我画了一张图,把核心逻辑理清楚。
2.5 综合实战要点
讲完理论,我直接给你几个在工程里用得上的 Checklist:
- 配置 TLS 1.3 加密套件时: 只保留 TLS_AES_128_GCM_SHA256 和 TLS_AES_256_GCM_SHA384 就够了。别再把那些过时的 ECDHE-RSA-AES128-SHA 加进去——TLS 1.3 根本不认。
- 证书选择: 新业务直接上 ECDSA P-256 或 Ed25519。如果兼容老旧客户端(比如 Windows XP/Android 4.x),必须保留 RSA 证书,但仅做签名用途。
- 哈希强度: 当前最少用 SHA-256。SHA-1 已经彻底被禁止在 TLS 1.3 中使用。我曾在一个遗留系统里看到 SHA-1 证书链……浏览器直接报了 ERR_CERT_WEAK_SIGNATURE_ALGORITHM,用户无法访问。
- 随机数质量: 密钥交换的安全性强烈依赖随机数生成器。我在生产环境遇到过因为容器 /dev/urandom 熵不足导致 ECDHE 生成慢的问题。解决办法是挂载 haveged 或使用专用硬件熵源。
openssl s_client -connect yourdomain.com:443 -tls1_3 -ciphersuites TLS_AES_128_GCM_SHA256如果返回握手成功,说明你的服务器已经用上了今天讲的这套密码组合。