3. TLS 1.2 握手协议详解:ClientHello 与 ServerHello、证书交换与密钥协商、Finished 消息验证

TLS 1.2 握手协议是安全通信的基石,负责在客户端与服务器之间协商加密参数、验证身份并生成共享密钥。本章将深入剖析握手协议的三个核心阶段:Hello 消息交换、证书与密钥协商、以及 Finished 消息的完整性验证。理解这些细节对于分析协议漏洞(如降级攻击、中间人攻击)至关重要。

3.1 ClientHello 与 ServerHello:密码套件协商与随机数交换

握手的第一步是客户端与服务器交换 Hello 消息,用于协商协议版本、密码套件、压缩算法以及交换随机数。这些随机数是后续密钥派生的重要输入。

3.1.1 ClientHello 消息结构

客户端发送 ClientHello 消息,包含以下关键字段:

字段 长度(字节) 说明
Protocol Version 2 客户端支持的最高 TLS 版本,TLS 1.2 为 0x0303
Random 32 客户端生成的 32 字节随机数(client_random),包含 4 字节 Unix 时间戳 + 28 字节随机值
Session ID 可变 用于会话恢复的标识符,若为空则表示新建会话
Cipher Suites 可变 客户端支持的密码套件列表,按优先级降序排列
Compression Methods 可变 支持的压缩算法列表,通常仅包含 null(0x00)
Extensions 可变 扩展字段,如 SNI、ALPN、签名算法、椭圆曲线等
安全要点:攻击者可能通过修改 ClientHello 中的版本号或密码套件列表来实施降级攻击。例如,将 TLS 1.2 降级为 TLS 1.0 或 SSL 3.0,从而利用旧版本中的已知漏洞(如 POODLE 攻击)。服务器必须验证客户端提供的版本不低于自身支持的最低安全版本。

3.1.2 ServerHello 消息结构

服务器收到 ClientHello 后,选择双方都支持的参数,并回复 ServerHello:

字段 长度(字节) 说明
Protocol Version 2 服务器选择的 TLS 版本,不得高于客户端提供的版本
Random 32 服务器生成的 32 字节随机数(server_random)
Session ID 可变 若支持会话恢复,则返回匹配的 Session ID;否则生成新 ID
Cipher Suite 2 从客户端列表中选定的单一密码套件
Compression Method 1 选定的压缩算法,通常为 null
Extensions 可变 服务器支持的扩展响应
漏洞风险:如果服务器未正确验证 ClientHello 中的版本字段,攻击者可以伪造一个低版本 ClientHello,诱使服务器选择弱密码套件。例如,DROWN 攻击利用服务器对 SSLv2 的兼容性来破解 TLS 会话。

3.1.3 Hello 消息交换流程

下图展示了 ClientHello 与 ServerHello 的交互过程,以及随机数在后续密钥派生中的作用:

ClientHello 与 ServerHello 交换流程 客户端 生成 client_random 服务器 生成 server_random ClientHello 版本、密码套件列表、client_random ServerHello 选定版本、选定密码套件、server_random 密钥派生输入 client_random + server_random + 预主密钥 → 主密钥(Master Secret)→ 会话密钥

3.2 证书交换与密钥协商:身份验证与预主密钥生成

在 Hello 消息交换之后,服务器(通常)会发送其数字证书,并可能请求客户端证书。随后,双方通过密钥交换算法(如 RSA 或 ECDHE)协商出预主密钥(Pre-Master Secret)。

3.2.1 证书交换过程

服务器发送 Certificate 消息,包含一个 X.509 证书链(从服务器证书到根 CA 证书)。客户端需要验证证书链的合法性:

  1. 证书链验证:检查每个证书的签名是否由上一级 CA 签发,直至信任的根 CA。
  2. 有效期检查:确认证书未过期且未被撤销(通过 CRL 或 OCSP)。
  3. 域名匹配:验证证书中的 subjectAltName 或 CN 字段与服务器域名一致。
  4. 密钥用途:确认证书的密钥用途(Key Usage)包含数字签名或密钥加密。
漏洞案例:如果客户端未正确验证证书链(例如,接受自签名证书或忽略域名匹配),攻击者可以通过中间人攻击(MITM) 伪造服务器身份,拦截或篡改通信。著名的 Superfish 事件 就是由于预装根证书导致所有 HTTPS 连接被劫持。

3.2.2 密钥协商算法对比

TLS 1.2 支持多种密钥交换算法,其中 RSA 和 ECDHE 是最常见的两种。下表对比了它们的安全特性:

特性 RSA 密钥交换 ECDHE 密钥交换
前向安全性 ❌ 不支持(私钥泄露可解密所有历史会话) ✅ 支持(每次会话使用临时密钥对)
密钥生成方式 客户端生成预主密钥,用服务器公钥加密后发送 双方通过 ECDH 协议协商出共享密钥
计算开销 较低(非对称加密一次) 较高(需要椭圆曲线点乘运算)
抗量子攻击 ❌ 脆弱(Shor 算法可破解 RSA) ❌ 脆弱(但优于 RSA)
典型密码套件 TLS_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
安全建议:现代 TLS 部署应优先使用 ECDHE 密钥交换,因为它提供前向安全性(PFS)。如果服务器私钥泄露,攻击者无法解密之前记录的会话流量。RSA 密钥交换已被认为不安全,应在 TLS 1.3 中彻底移除。

3.2.3 ECDHE 密钥协商流程

下图展示了基于 ECDHE 的密钥协商过程,包括服务器发送 ServerKeyExchange 消息携带临时公钥:

ECDHE 密钥协商流程 客户端 生成临时密钥对 (sk_c, pk_c) 服务器 生成临时密钥对 (sk_s, pk_s) ServerKeyExchange 椭圆曲线参数、服务器临时公钥 pk_s、签名 ClientKeyExchange 客户端临时公钥 pk_c 客户端计算 共享密钥 = ECDH(sk_c, pk_s) → 预主密钥 服务器计算 共享密钥 = ECDH(sk_s, pk_c) → 预主密钥 共享密钥相同 主密钥 = PRF(预主密钥 + client_random + server_random) PRF: P_SHA256 或 P_SHA384

3.3 Finished 消息验证:握手完整性校验

在密钥协商完成后,双方交换 ChangeCipherSpec 消息(通知对方后续消息将使用协商的密钥加密),然后发送 Finished 消息。Finished 消息是握手过程的最终验证,确保所有握手消息未被篡改。

3.3.1 Finished 消息结构

Finished 消息包含一个 verify_data 字段,其计算方式如下:

verify_data = PRF(master_secret, "finished", Hash(handshake_messages)) [0..11]

其中:

  • master_secret:由预主密钥和随机数派生的 48 字节主密钥。
  • "finished":固定标签字符串。
  • Hash(handshake_messages):所有握手消息(从 ClientHello 到 ServerHelloDone,不包括 Finished 本身)的哈希值。对于 TLS 1.2,使用密码套件指定的哈希算法(如 SHA-256)。
  • [0..11]:取 PRF 输出的前 12 字节。

3.3.2 验证流程

  1. 客户端发送 Finished:客户端计算 verify_data,并使用当前加密参数加密后发送。
  2. 服务器验证:服务器解密后,使用相同的输入重新计算 verify_data,并与接收到的值比较。如果匹配,则握手成功;否则,发送 alert 消息并终止连接。
  3. 服务器发送 Finished:服务器同样计算并发送自己的 verify_data。
  4. 客户端验证:客户端执行相同的验证步骤。
安全意义:Finished 消息验证了握手过程的完整性。如果攻击者在握手过程中修改了任何消息(例如,降级密码套件或篡改证书),双方计算出的 handshake_messages 哈希值将不同,导致 verify_data 不匹配,从而检测到攻击。这是防止中间人攻击的关键机制。

3.3.3 常见漏洞与防御

漏洞类型 攻击原理 防御措施
降级攻击 攻击者修改 ClientHello 中的版本号或密码套件,诱使服务器选择弱算法 服务器应拒绝低于 TLS 1.2 的版本;使用 TLS 1.3 的强制版本协商机制
证书伪造 攻击者使用伪造的证书冒充服务器 客户端严格验证证书链、域名匹配和吊销状态;使用证书透明度(CT)
密钥协商篡改 攻击者修改 ServerKeyExchange 中的临时公钥 服务器对 ServerKeyExchange 消息进行数字签名;客户端验证签名
Finished 消息重放 攻击者重放之前的 Finished 消息 Finished 消息包含随机数,确保每次握手的 verify_data 唯一
实践建议:在实现 TLS 1.2 客户端或服务器时,务必确保:
  • 使用安全的随机数生成器生成 client_random 和 server_random。
  • 优先选择支持前向安全性的密码套件(如 ECDHE + GCM)。
  • 在 Finished 验证失败时,立即终止连接并记录告警日志。
  • 定期更新 CA 证书库,避免信任已泄露的根证书。

3.4 本章小结

TLS 1.2 握手协议通过 ClientHello/ServerHello 协商参数,通过证书交换和 ECDHE/RSA 密钥协商生成共享密钥,最后通过 Finished 消息验证握手完整性。每个阶段都引入了特定的安全风险:

  • Hello 阶段:降级攻击和版本回滚。
  • 证书阶段:证书伪造和中间人攻击。
  • 密钥协商阶段:缺乏前向安全性的 RSA 交换。
  • Finished 阶段:消息篡改检测失败。