TLS 协议基础:握手流程、加密套件、证书链验证

各位好,我是老张,带网络安全团队快十年了。今天咱们开始聊 TLS 协议的基础。

你想想看,一个 HTTPS 请求从客户端发出去,到服务端返回数据,中间到底发生了什么?说白了就是三件事:握手协商、数据加密、身份证明。这几件事漏掉任何一个,你的连接就不安全。

我个人习惯把 TLS 协议拆成三个块来讲——握手流程、加密套件、证书链验证。这三块搞明白了,后面聊 OCSP Stapling 和性能优化才接得住。


一、TLS 握手流程:比你想的更啰嗦

刚开始接触 TLS 的同学,总觉得握手就是“客户端发个请求,服务端回个证书”就完了。实际上,完整的握手至少来回两次网络交互。

我记得有一次线上排查慢连接,抓包一看,客户端和服务端来回握了整整 4 个 RTT。嗯,当时我就把项目组的那帮小伙子叫过来,一个一个对着抓包文件讲——你们看,这才是握手的真相。

1.1 完整握手(Full Handshake)

标准流程分 5 步:

  1. ClientHello:客户端发起,带上支持的 TLS 版本、加密套件列表、随机数。
  2. ServerHello + Certificate + ServerHelloDone:服务端选好版本和套件,把自己的证书链发过去,再说一句“我好了”。
  3. ClientKeyExchange + ChangeCipherSpec + Finished:客户端用服务端公钥加密一个预主密钥(Pre-Master Secret),通知对方“我要切加密了”,最后发一条验证消息。
  4. ChangeCipherSpec + Finished:服务端也切加密,发验证消息。
  5. 开始加密数据传输:握手完,双方用对称密钥加密数据。

这里面有个坑我得提醒你——证书链的大小直接影响握手性能。我见过有人把整条链(包含所有中间 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。
警告:不要启用 RC4、DES、3DES、CBC 模式的加密套件。这些要么已被破解,要么存在时序攻击漏洞。我曾经在老旧金融系统中发现过还在用 RC4-SHA 的配置——立马建议升级。

2.2 性能对比

选加密套件时,我习惯先看这三个指标:

算法密钥交换开销对称加密开销前向安全
RSA 2048高(签名和验证耗 CPU)N/A否
ECDHE P-256低(椭圆曲线运算快)N/A是
ECDHE X25519极低(curve25519 优化好)N/A是
AES-128-GCMN/A低(硬件加速)N/A
ChaCha20-Poly1305N/A低(纯软件,移动端优)N/A

选型建议:服务端建议优先支持 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 和 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256。如果客户端以移动端为主,再加一个 ChaCha20 套件兜底。


三、证书链验证:你信任的到底是谁?

握手时服务端发来的证书链,客户端必须做验证。验证不过直接断连,杜绝中间人攻击。

验证步骤大概是:

  1. 签名验证:用上一级 CA 的公钥验证当前证书的签名。
  2. 有效期检查:证书是否在有效期内。
  3. 吊销状态检查:是否被 CA 吊销。实时检查一般走 CRL 或 OCSP。
  4. 域名匹配:证书的 CN 或 SAN 是不是和请求的域名一致。
  5. 信任链锚定:最终能追溯到本地信任的根 CA。

这里有个容易被忽略的点:中间 CA 的跨域策略。我曾经遇到一个客户,子公司用上级公司签发的证书,中间 CA 的 Name Constraints 限制了域名范围,结果跨子域的业务全挂了。抓了三天包才发现是证书路径验证出了错。

核心观点:证书链验证不仅仅是检查“有没有过期”,更是检查“这条信任路径是否成立”。OCSP Stapling 就是用来优化第三步(吊销检查)性能的,咱们后面专门讲。

本章知识体系

下面这张图把 TLS 基础的三块内容串起来了。你可以把它当作自己的“协议知识地图”。

TLS 协议基础 — 知识体系 TLS 握手流程 加密套件 证书链验证 ClientHello ServerHello + 证书 密钥交换 ChangeCipherSpec 加密通信 密钥交换算法 对称加密算法 MAC 算法 签名算法 性能对比与选型 签名验证 有效期检查 吊销状态检查 域名匹配 信任链锚定 三块知识互相依赖:握手用到加密套件和证书链 证书链验证依赖加密套件中的签名算法

这三个模块就像 TLS 的三根柱子。握手流程是骨架,加密套件是血液,证书链验证是灵魂。任何一个出了问题,你的 HTTPS 服务要么不安全,要么慢得像蜗牛。

接下来咱们会深入到具体的 OCSP Stapling —— 它专门解决证书吊销检查这块的性能瓶颈。有了今天的基础,你才能理解为什么 Stapling 能省掉一个 RTT,为什么某些场景下它反而可能出问题。