2. TLS/SSL 握手:TLS 1.2 与 1.3 握手流程对比、证书链验证、密钥交换算法(RSA/ECDHE)
握手,是整个 TLS 安全通道的起点。说白了,就是客户端和服务器在正式传输数据前,先互相打个招呼、亮个身份、商量好用什么加密方式。这一步要是出了问题,后面所有加密都是白搭。
我刚开始接触 HTTPS 时,总觉得握手就是“交换个证书、生成个密钥”这么简单。直到有一次在生产环境排查一个间歇性的连接超时问题,抓包一看,发现握手阶段来回折腾了七八次,延迟直接飙到 500 毫秒以上。嗯,从那以后,我再也不敢小看握手了。
2.1 TLS 1.2 握手流程:经典但有点啰嗦
TLS 1.2 从 2008 年服役到现在,依然广泛使用。它的握手流程,我习惯把它拆成四个阶段来看。
- ClientHello:客户端发个招呼,告诉服务器自己支持的 TLS 版本、密码套件列表、以及一个随机数。
- ServerHello + 证书 + ServerHelloDone:服务器选好版本和密码套件,发回自己的证书链,然后说“我说完了”。
- 密钥交换:客户端验证证书,然后根据协商好的密钥交换算法(RSA 或 ECDHE),生成预主密钥并发送给服务器。
- ChangeCipherSpec + Finished:双方各自计算会话密钥,然后互相发一条“我准备好了”的消息,握手结束。
你想想看,这一来一回,至少需要 2 个 RTT(网络往返)。如果网络延迟高,光握手就要等很久。
核心要点:TLS 1.2 握手是显式的,每一步都清清楚楚,但也因此多了不少冗余。
2.2 TLS 1.3 握手流程:精简到极致
TLS 1.3 在 2018 年发布,最大的变化就是——快。它把握手压缩到了 1 个 RTT,甚至支持 0-RTT 模式(首次连接后可以复用)。
- ClientHello:客户端不仅打招呼,还直接把自己的密钥交换参数(比如 ECDHE 的公钥)带过去。
- ServerHello + 证书 + 密钥交换参数:服务器也一次性把证书和密钥参数发回来。双方此时已经可以算出会话密钥。
- Finished:双方直接发送加密后的 Finished 消息,握手完成。
为什么能这么快?因为 TLS 1.3 砍掉了那些不安全的算法,强制使用前向安全的密钥交换(比如 ECDHE),并且把很多协商过程提前了。我个人觉得,这是 TLS 历史上最漂亮的一次升级。
避坑指南:我曾经在升级 TLS 1.3 时,发现一些老旧的负载均衡器不支持 0-RTT 的重放保护,导致业务数据被重复处理。所以,0-RTT 虽好,但幂等性设计一定要跟上。
2.3 证书链验证:信任的传递
证书验证,说白了就是回答一个问题:“我怎么知道这个公钥真的是服务器的?”
答案就是证书链。服务器发来的证书不是孤立的,而是一串证书:
- 叶子证书:服务器的身份证明,由中间 CA 签发。
- 中间 CA 证书:由根 CA 签发,用来证明叶子证书的合法性。
- 根 CA 证书:自签名证书,预装在操作系统或浏览器中,是信任的锚点。
验证过程是这样的:
- 用根 CA 的公钥验证中间 CA 证书的签名。
- 用中间 CA 的公钥验证叶子证书的签名。
- 检查叶子证书的域名、有效期、吊销状态。
嗯,这里要注意:如果中间 CA 证书没发全,客户端可能无法构建完整的证书链,导致验证失败。我在项目中遇到过好几次这种问题,最后发现是服务器配置漏发了中间证书。
警告:永远不要信任自签名的叶子证书。除非你在内部测试环境,并且明确知道自己在做什么。
2.4 密钥交换算法:RSA vs ECDHE
密钥交换,就是双方在不安全的网络上,安全地商量出一个共享密钥。TLS 1.2 支持多种算法,但 TLS 1.3 只保留了 ECDHE。
| 特性 | RSA 密钥交换 | ECDHE 密钥交换 |
|---|---|---|
| 前向安全性 | ❌ 不支持 | ✅ 支持 |
| 密钥生成方式 | 客户端生成预主密钥,用服务器公钥加密发送 | 双方各自生成临时密钥对,通过 DH 算法计算共享密钥 |
| 性能 | 较快(但私钥泄露后所有历史通信都可解密) | 稍慢(但每次会话密钥独立,私钥泄露不影响历史) |
| TLS 1.3 支持 | ❌ 已移除 | ✅ 强制使用 |
为什么 RSA 被淘汰了?因为一旦服务器的私钥泄露,攻击者就可以解密所有用该私钥加密的历史会话。而 ECDHE 每次会话都生成临时密钥,即使私钥泄露,也只能解密未来的会话,无法回溯过去。这就是所谓的前向安全性。
个人经验:我建议所有新系统都优先使用 ECDHE。RSA 密钥交换虽然简单,但风险太高。如果你还在用 RSA 做密钥交换,赶紧升级吧。
2.5 核心逻辑流程图
下面这张图,把 TLS 1.2 和 1.3 的握手流程放在一起对比,你可以直观地看到差异。
2.6 实战建议
- 优先使用 TLS 1.3:如果你的服务端和客户端都支持,直接上 TLS 1.3。性能更好,安全性更高。
- 证书链要完整:配置服务器时,确保把中间证书也带上。很多问题都是因为漏了中间证书导致的。
- 禁用 RSA 密钥交换:如果你还在用 TLS 1.2,务必禁用 RSA 密钥交换,只保留 ECDHE 套件。
- 监控握手延迟:我习惯在 Nginx 或负载均衡器上开启握手延迟监控,一旦发现异常,立刻排查证书或密码套件配置。
一句话总结:TLS 1.3 是未来,ECDHE 是标配,证书链是信任的基石。把这三点抓好,你的握手阶段就稳了。