TLS 协议基础:握手流程、加密套件、证书链验证
各位好,我是老张,带网络安全团队快十年了。今天咱们开始聊 TLS 协议的基础。
你想想看,一个 HTTPS 请求从客户端发出去,到服务端返回数据,中间到底发生了什么?说白了就是三件事:握手协商、数据加密、身份证明。这几件事漏掉任何一个,你的连接就不安全。
我个人习惯把 TLS 协议拆成三个块来讲——握手流程、加密套件、证书链验证。这三块搞明白了,后面聊 OCSP Stapling 和性能优化才接得住。
一、TLS 握手流程:比你想的更啰嗦
刚开始接触 TLS 的同学,总觉得握手就是“客户端发个请求,服务端回个证书”就完了。实际上,完整的握手至少来回两次网络交互。
我记得有一次线上排查慢连接,抓包一看,客户端和服务端来回握了整整 4 个 RTT。嗯,当时我就把项目组的那帮小伙子叫过来,一个一个对着抓包文件讲——你们看,这才是握手的真相。
1.1 完整握手(Full Handshake)
标准流程分 5 步:
- ClientHello:客户端发起,带上支持的 TLS 版本、加密套件列表、随机数。
- ServerHello + Certificate + ServerHelloDone:服务端选好版本和套件,把自己的证书链发过去,再说一句“我好了”。
- ClientKeyExchange + ChangeCipherSpec + Finished:客户端用服务端公钥加密一个预主密钥(Pre-Master Secret),通知对方“我要切加密了”,最后发一条验证消息。
- ChangeCipherSpec + Finished:服务端也切加密,发验证消息。
- 开始加密数据传输:握手完,双方用对称密钥加密数据。
这里面有个坑我得提醒你——证书链的大小直接影响握手性能。我见过有人把整条链(包含所有中间 CA)塞进一个包里,结果 TCP 分段传了好几次,客户端的 TLS 握手机制直接被卡死在等待完整证书上。
1.2 简化握手(Session Resumption)
你想想,每次连接都走完整握手,那得多慢?所以 TLS 提供了会话恢复机制。客户端保存上次握手的 Session ID 或 Session Ticket,下次直接复用之前的加密协商结果。
这个机制在实际项目中特别有用。比如移动端频繁断连重连的场景,用 Session Ticket 能把第二次握手减少到 1 个 RTT。
| 握手类型 | RTT 数 | 适用场景 |
|---|---|---|
| 完整握手 | 2 RTT | 首次连接、缓存丢失 |
| 会话恢复(Session ID) | 1 RTT | 短时间内的后续连接 |
| 会话恢复(Session Ticket) | 1 RTT | 支持无状态服务端 |
| 0-RTT(TLS 1.3) | 0 RTT | 幂等请求(如 GET) |
二、加密套件:选不对就是性能杀手
加密套件(Cipher Suite)决定了握手和加密的算法组合。配置错误的话,要么不安全,要么慢得离谱。
我在项目里见过最典型的例子:某金融客户坚持用 4096 位 RSA 证书做密钥交换,结果每个握手都耗时超过 500 毫秒。我跟他解释说,RSA 本身做密钥交换没问题,但 4096 位的 RSA 签名验证对 CPU 压力太大,尤其在高并发时。
2.1 加密套件结构
TLS 1.2 的加密套件长这样:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
│ │ │ │
│ │ │ └─ 消息认证码(MAC)算法
│ │ └───────────── 对称加密算法
│ └──────────────────────── 身份认证算法(签名)
└─────────────────────────────── 密钥交换算法
当前主流推荐:
- 密钥交换:ECDHE(椭圆曲线 Diffie-Hellman),支持前向安全,不像 RSA 那样私钥泄漏就全完。
- 对称加密:AES-128-GCM,硬件加速好,性能优秀。
- 签名算法:RSA 或 ECDSA。ECDSA 密钥更小,签名更快。
- MAC:GCM 模式自带身份认证,不需要额外的 HMAC。
2.2 性能对比
选加密套件时,我习惯先看这三个指标:
| 算法 | 密钥交换开销 | 对称加密开销 | 前向安全 |
|---|---|---|---|
| RSA 2048 | 高(签名和验证耗 CPU) | N/A | 否 |
| ECDHE P-256 | 低(椭圆曲线运算快) | N/A | 是 |
| ECDHE X25519 | 极低(curve25519 优化好) | N/A | 是 |
| AES-128-GCM | N/A | 低(硬件加速) | N/A |
| ChaCha20-Poly1305 | N/A | 低(纯软件,移动端优) | N/A |
选型建议:服务端建议优先支持 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 和 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256。如果客户端以移动端为主,再加一个 ChaCha20 套件兜底。
三、证书链验证:你信任的到底是谁?
握手时服务端发来的证书链,客户端必须做验证。验证不过直接断连,杜绝中间人攻击。
验证步骤大概是:
- 签名验证:用上一级 CA 的公钥验证当前证书的签名。
- 有效期检查:证书是否在有效期内。
- 吊销状态检查:是否被 CA 吊销。实时检查一般走 CRL 或 OCSP。
- 域名匹配:证书的 CN 或 SAN 是不是和请求的域名一致。
- 信任链锚定:最终能追溯到本地信任的根 CA。
这里有个容易被忽略的点:中间 CA 的跨域策略。我曾经遇到一个客户,子公司用上级公司签发的证书,中间 CA 的 Name Constraints 限制了域名范围,结果跨子域的业务全挂了。抓了三天包才发现是证书路径验证出了错。
本章知识体系
下面这张图把 TLS 基础的三块内容串起来了。你可以把它当作自己的“协议知识地图”。
这三个模块就像 TLS 的三根柱子。握手流程是骨架,加密套件是血液,证书链验证是灵魂。任何一个出了问题,你的 HTTPS 服务要么不安全,要么慢得像蜗牛。
接下来咱们会深入到具体的 OCSP Stapling —— 它专门解决证书吊销检查这块的性能瓶颈。有了今天的基础,你才能理解为什么 Stapling 能省掉一个 RTT,为什么某些场景下它反而可能出问题。