2. TLS 握手过程详解:ClientHello、ServerHello、证书交换、密钥交换、Finished 消息
好,咱们直接进入正题。上一章我们聊了为什么 HTTPS 需要 TLS 握手,这一章我就带你亲手拆开这个握手过程。你打开 Wireshark,抓一个 HTTPS 的包,看到的第一个动作就是 ClientHello。别急,我们一个一个来。
2.1 ClientHello —— 客户端发起“打招呼”
说白了,这就是客户端在说:“嘿,服务器,我想跟你建立安全连接,我支持这些加密方式,你看哪个合适?”
在 Wireshark 里,你双击一个 ClientHello 包,会看到这些关键字段:
- Version:客户端能支持的最高 TLS 版本。比如 TLS 1.2 或 1.3。
- Random:一个 32 字节的随机数。这个很重要,后面生成会话密钥全靠它。
- Session ID:如果之前连过这个服务器,可以带上之前的 Session ID 做会话复用。
- Cipher Suites:客户端支持的加密套件列表。我见过有些客户端列了十几个,其实真正用的就前面几个。
- Extensions:扩展字段,比如 SNI(Server Name Indication),告诉服务器你想访问哪个域名。
2.2 ServerHello —— 服务器回应
服务器收到 ClientHello 后,会回复一个 ServerHello。它从客户端提供的列表中选一个双方都支持的加密套件,然后告诉客户端:“我们就用这个吧。”
ServerHello 里同样包含一个 Random 字段(也是 32 字节),以及服务器选中的 Cipher Suite。注意,这里的 Random 和客户端的 Random 不一样,它们是独立的。
嗯,这里要注意:如果服务器找不到双方都支持的加密套件,它会直接发一个 Alert 消息,握手就断了。我在项目中遇到过这种情况,原因是客户端太老,只支持 RC4,而服务器早就禁用了它。
2.3 证书交换 —— 服务器亮出“身份证”
ServerHello 之后,服务器会发送自己的 Certificate 消息。这个证书里包含了服务器的公钥、域名、颁发者等信息。Wireshark 里展开 Certificate 字段,你能看到证书链:
- 服务器证书(叶子证书)
- 中间 CA 证书
- 根 CA 证书(通常不发送,客户端本地有)
你想想看,如果证书的域名和实际访问的域名不匹配,浏览器会直接报安全警告。Wireshark 里你可以直接看 Certificate 字段里的 Subject 和 Issuer,确认证书是谁发的、发给谁的。
2.4 密钥交换 —— 协商会话密钥
证书交换之后,客户端需要生成一个 Pre-Master Secret(预主密钥),然后用服务器的公钥加密它,发送给服务器。这个过程叫做 Client Key Exchange。
服务器收到后用私钥解密,拿到 Pre-Master Secret。然后双方用三个东西:
- Client Random
- Server Random
- Pre-Master Secret
通过伪随机函数(PRF)生成 Master Secret(主密钥)。再进一步生成会话密钥,用于后续的对称加密。
在 Wireshark 里,如果你有服务器的私钥(RSA 密钥交换场景),可以配置 SSL 解密,Wireshark 会自动解密后续的加密数据。我个人习惯在实验室环境里用这种方式来验证握手过程是否正确。
| 密钥材料 | 长度 | 作用 |
|---|---|---|
| Client Random | 32 字节 | 防止重放攻击 |
| Server Random | 32 字节 | 防止重放攻击 |
| Pre-Master Secret | 48 字节 | 核心密钥材料 |
| Master Secret | 48 字节 | 派生会话密钥 |
2.5 Finished 消息 —— 握手完成确认
最后一步,双方各自发送 Finished 消息。这个消息的内容是对整个握手过程所有消息的哈希值(用 PRF 计算),并加上一个固定的标签 "client finished" 或 "server finished"。
如果双方都能正确验证对方的 Finished 消息,说明握手过程中没有人篡改数据,密钥协商也一致。之后就可以开始加密通信了。
在 Wireshark 里,Finished 消息的 Verify Data 字段就是那个哈希值。你可以自己算一下,看看是否匹配。我偶尔会这么干,用来验证 Wireshark 的解密是否正确。
2.6 完整握手流程图
下面这张图把整个握手过程串起来,你一看就明白了。
你看,从 ClientHello 到 Finished,一共 6 步(不算 ChangeCipherSpec 的话是 5 步)。每一步都有明确的职责,Wireshark 里都能看到对应的包。我个人建议你抓一个真实的 HTTPS 流量,对照着这张图一个一个包看,印象会深很多。