TLS 1.2 握手流程 vs TLS 1.3 握手流程
做安全审计这些年,我见过最多的误判就是——拿着 TLS 1.2 的日志模板去套 1.3。结果呢?字段对不上,时序全乱,最后怀疑自己抓包工具坏了。其实说白了,这两个版本的握手逻辑差别挺大的。
我个人习惯在分析审计日志前,先搞清楚当前连接用的是哪个版本。因为同一个「ServerHello」字段,在 1.2 里它带着证书链和密钥交换参数,在 1.3 里它可能已经把 Finished 消息都塞进去了。你想想看,字段解析顺序都不一样,审计规则能一样吗?
TLS 1.2 握手——四次往返的「老江湖」
TLS 1.2 的握手,概括起来就是「你一次,我一次,再交换一次,最后确认一次」。一共需要 4 次网络往返(如果算上 TCP 三次握手就是 7 次)。
我在一个老旧银行系统里见过这种握手模式,每次建立连接都要拖到 200ms 以上。嗯,那还是纯内网环境。
- ClientHello:客户端发出支持的密码套件列表、随机数、扩展信息。
- ServerHello + Certificate + ServerHelloDone:服务端选好密码套件,发证书,结束自己这一轮。
- ClientKeyExchange + ChangeCipherSpec + Finished:客户端计算预主密钥,切换加密策略,发送验证消息。
- ChangeCipherSpec + Finished:服务端也切换加密策略,回复验证消息。
TLS 1.3 握手——一次交互的秘密
TLS 1.3 通过「预共享密钥(PSK)模式」和「1-RTT 握手」把往返次数降到 1 次。首次连接也只需要 2 次交互就能完成握手。说白了,服务端在收到 ClientHello 后,直接就能把证书、密钥交换参数和 Finished 打包发回去。
记得有一次做性能调优,把内部 RPC 从 1.2 升级到 1.3,延迟直接砍半。我当时还纳闷,到底少了什么环节?后来看抓包才明白——握手流程简化太多了。
- ClientHello:客户端不仅发密码套件列表,还带上
key_share扩展(包含自己的临时公钥)。 - ServerHello + EncryptedExtensions + Certificate + CertificateVerify + Finished:服务端一步到位,把选套件、发证书、验证、结束全放在一个包里。
- (可选 0-RTT)如果复用会话,客户端可以直接发加密的应用数据。
version 字段。
核心差异速览表
| 对比维度 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 握手往返次数 | 4 次(2-RTT) | 2 次(1-RTT),0-RTT 可选 |
| 密钥交换机制 | 支持静态 RSA、DHE、ECDHE(协商方式) | 仅支持 DHE 或 ECDHE,强制前向安全 |
| 密码套件选择 | 客户端发送完整列表,服务端挑选 | 客户端只发送支持的 DH 组和 AEAD 算法,服务端从剩余组合中选 |
| ChangeCipherSpec | 独立记录,code=0x14 | 不再作为独立记录,仅用于兼容性空包 |
| 证书与验证 | ServerHello 后单独发送 Certificate 和 ServerKeyExchange | Certificate 和 CertificateVerify 与 ServerHello 合并在一个飞行中 |
| 会话恢复 | Session ID / Session Ticket | PSK + ticket / 0-RTT |
| 审计日志字段冗余度 | 高(独立记录多,字段解析简单但冗长) | 低(合并记录多,需要根据 handshake_type 二次拆分) |
流程对比图(SVG 内联)
下面这张图把两个版本握手的核心步骤画在一起。左侧是 TLS 1.2 的四次交互,右侧是 TLS 1.3 的两次交互。箭头上的数字是网络往返次数。
审计日志里怎么区分这两个版本?
我直接给个实用技巧:看 Handshake Protocol: Version 字段。TLS 1.2 对应 0x0303,TLS 1.3 对应 0x0304。但要注意,有些中间设备会把版本号改写,我建议你联动 supported_versions 扩展来双重确认。
- TLS 1.2 日志特征:出现独立的 ChangeCipherSpec 记录,ServerHello 之后紧接着 Certificate 和 ServerHelloDone,Finished 消息在 ChangeCipherSpec 之后。
- TLS 1.3 日志特征:没有独立 CCS,ServerHello 之后直接加密扩展和证书验证,Finished 作为握手最后一包合并发送。
type 22 (Handshake) 后面跟着 type 20 (ChangeCipherSpec),那基本可以确定是 TLS 1.2 或更老的版本。TLS 1.3 中的 ChangeCipherSpec 只作为兼容性空包出现,不承载握手信息。
还是那句话,理解握手流程的差异,是写好审计规则的前提。我个人会把 TLS 1.2 的审计日志拆成 4 个阶段分别校验,而 TLS 1.3 只需要校验 ClientHello 和 ServerHello 两个关键点,剩下的字段合并检查就行。
嗯,这就是我处理这两个版本握手时的核心思路——先分版本,再定规则,最后看细节。这样审计日志才不会漏报或误报。