密钥交换组协商
supported_groups 扩展(早期叫 elliptic_curves)列出客户端支持的椭圆曲线与密钥交换组,TLS 1.3 还要求客户端在 key_share 扩展里直接带上准备用于首轮交换的组参数。如果客户端列出的组服务端都不接受,服务端会回一个 HelloRetryRequest 让客户端换组重试;再不行就只能握手失败。它决定了 ECDHE 用哪条曲线,也就决定了密钥交换的性能与强度。
基本信息
| 关键字段 | tls.handshake.extensions_supported_group、tls.handshake.extensions_key_share_group |
|---|---|
| 常见组 | x25519、secp256r1(prime256v1)、secp384r1 |
| 1.3 特有 | HelloRetryRequest 换组重试,多一次往返 |
| 适用平台 | Wireshark 4.x 可展开 ClientHello 的扩展逐项查看 |
典型使用场景
- 老客户端不支持 x25519,与新服务端策略不匹配导致握手失败
- 排查 TLS 1.3 多出的一次往返:确认是否由 HelloRetryRequest 引起
- 合规清理:禁用弱曲线或已弃用的二进制曲线
- 性能对比:不同曲线在移动终端上的握手耗时差异
- 核对客户端声明的组与服务端最终选中的组是否一致
观察协商过程
观察协商过程
tshark -r t.pcap -Y "tls.handshake.type==1" -T fields -e ip.src -e tls.handshake.extensions_supported_group
# 客户端支持的组清单,逗号分隔
tshark -r t.pcap -Y "tls.handshake.type==2" -T fields -e ip.src -e tls.handshake.extensions_key_share_group
# 服务端最终选中的组;同一连接出现两次 ServerHello 时,注意 Wireshark 标注为 Hello Retry Request 的那一次常见组读法
| 组名 | 说明 | 实践提示 |
|---|---|---|
| x25519 | 现代实现的默认首选 | 性能好,兼容性已很广 |
| secp256r1 / prime256v1 | NIST 曲线,兼容性最好 | 与老客户端对接的保底选项 |
| secp384r1 | 强度更高,运算代价更大 | 高安全要求场景使用 |
| secp521r1 | 强度最高但支持面窄 | 部分客户端不支持 |
| ffdhe 系列 | 1.3 中的有限域 DHE 组 | 作为 ECDHE 之外的兜底,需确认两端都支持 |
TLS 1.3 中 key_share 与 supported_groups 列表可以不同:客户端只为部分组预生成密钥对以节省开销,所以「列在支持列表里」不等于「本次带了 key_share」,服务端只能从带了 key_share 的组里选,否则触发换组重试。
只看客户端的支持列表不够。最终选用哪个组由服务端的 ServerHello 决定,且中间设备可能裁剪扩展,判断兼容性必须以服务端应答为准。
排查顺序
- 先确认握手是否走到了 ServerHello,卡在 ClientHello 说明连接层面就断了
- 比对客户端 supported_groups 与服务端策略,看有没有共同组
- 出现两次 ServerHello 时先分清哪次是 Hello Retry Request
- 确认失败侧的主机名与 SNI 对应正确,避免拿错服务端配置比对
- 记录客户端实现与版本,老终端兼容问题往往与实现版本强相关