为什么要了解消息加密时机

在调试TLS问题时,一个常见的困惑是:握手过程中的消息,哪些是加密的,哪些是明文传输的?

理解这个问题对于:

  • 诊断TLS握手故障
  • 使用Wireshark等工具分析流量
  • 理解TLS的安全边界

都非常重要。

TLS 1.2 握手消息加密顺序

在TLS 1.2中,握手消息的加密并不是从一开始就开始的。让我们按顺序来看:

明文消息(不加密)

以下消息在握手初期以明文传输:

1
2
3
4
5
6
7
1. ClientHello        →  明文
2. ServerHello        →  明文
3. Certificate        →  明文
4. ServerKeyExchange  →  明文
5. ServerHelloDone    →  明文
6. ClientKeyExchange  →  明文
7. ChangeCipherSpec   →  明文

关键点:这些消息使用明文发送,因为此时双方还没有协商出加密密钥。

加密消息

ChangeCipherSpec之后,所有的握手消息都被加密:

1
2
8. Finished          →  加密
9. (后续应用数据)   →  加密

完整流程图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
客户端                                              服务器
   |                                                   |
   |------------------- ClientHello (明文) ------------→|
   |←---------------- ServerHello (明文) ---------------|
   |←---------------- Certificate (明文) ---------------|
   |←---------------- ServerKeyExchange (明文) ---------|
   |←---------------- ServerHelloDone (明文) -----------|
   |----------------- ClientKeyExchange (明文) --------→|
   |----------------- ChangeCipherSpec (明文) --------→|
   |----------------- Finished (加密) ----------------→|
   |←---------------- ChangeCipherSpec (明文) ----------|
   |←---------------- Finished (加密) -----------------|
   |================= 应用数据 (加密) =================|

注意:虽然ChangeCipherSpec消息本身是明文,但它是一个切换通知,告诉对方"接下来的消息将使用协商的加密套件"。

TLS 1.3 握手消息加密顺序

TLS 1.3对握手进行了重大简化,消息加密时机也有所不同。

1-RTT握手加密流程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
客户端                                              服务器
   |                                                   |
   |------------------- ClientHello (明文) ------------→|
   |←---------------- ServerHello (加密) --------------|
   |←---------------- EncryptedExtensions (加密) ------|
   |←---------------- Certificate (加密) --------------|
   |←---------------- CertificateVerify (加密) --------|
   |←---------------- Finished (加密) -----------------|
   |----------------- Finished (加密) ----------------→|
   |================= 应用数据 (加密) =================|

关键区别

TLS 1.3的重要改进:从ServerHello开始,消息就已经被加密了!

这是因为TLS 1.3使用了**前向安全(Forward Secrecy)**的密钥交换方式(ECDHE),双方可以在ClientHello和ServerHello过程中快速生成临时密钥。

0-RTT早期数据(可选)

TLS 1.3还支持0-RTT模式,允许在握手之前发送加密数据:

1
2
3
4
5
6
客户端                                              服务器
   |                                                   |
   |------------------- ClientHello (明文) ------------→|
   |------------------- EarlyData (加密) ------------→|  ← 可选,早期数据
   |←---------------- ServerHello (加密) --------------|
   ...

安全注意:0-RTT数据缺乏前向安全性,存在重放攻击风险。

对比总结

握手阶段 TLS 1.2 TLS 1.3
ClientHello 明文 明文
ServerHello 明文 加密
证书 明文 加密
密钥交换 明文 加密(通过ECDHE)
Finished 加密 加密

实际影响

1. Wireshark抓包分析

在TLS 1.2中,你可以在Wireshark中看到明文的握手消息:

1
2
3
4
TLS 1.2 ClientHello (明文可见)
TLS 1.2 ServerHello (明文可见)
TLS 1.2 Certificate (明文可见)
...

在TLS 1.3中,只有ClientHello是明文:

1
2
3
TLS 1.3 ClientHello (明文可见)
TLS 1.3 ServerHello (加密,需密钥解密)
...

2. 调试技巧

使用OpenSSL查看握手消息:

1
2
3
4
5
6
7
8
# 查看TLS 1.2握手消息(-msg显示详细信息)
openssl s_client -connect example.com:443 -tls1_2 -msg

# 查看TLS 1.3握手消息
openssl s_client -connect example.com:443 -tls1_3 -msg

# 同时显示十六进制内容
openssl s_client -connect example.com:443 -tls1_3 -msg -debug

3. 安全边界理解

  • TLS 1.2:证书等信息以明文传输,理论上可被中间人查看(但不能篡改)
  • TLS 1.3:更多握手信息被加密,减少了信息泄露风险

常见问题

Q: ChangeCipherSpec是加密的吗?

A: 在TLS 1.2中,ChangeCipherSpec本身是明文消息,但它是一个状态切换标志。在TLS 1.3中,ChangeCipherSpec被移除,相关功能整合到握手消息中。

Q: 为什么TLS 1.3可以从ServerHello开始加密?

A: TLS 1.3强制使用ECDHE(椭圆曲线Diffie-Hellman)密钥交换。客户端在ClientHello中包含自己的DH公钥,服务器在ServerHello中回复DH公钥,双方可以立即计算出共享密钥,从而实现从ServerHello开始的加密。

Q: 如何确认握手消息是否加密?

A: 可以通过Wireshark观察:

  • 观察TLS Record Layer的Content Type
  • 明文消息通常是handshake (0x16)
  • 加密消息通常是application_data (0x17)

总结

理解TLS握手消息的加密时机,有助于:

  1. 调试问题:知道哪些信息可以看到,哪些看不到
  2. 安全评估:理解TLS的安全边界
  3. 工具使用:更有效地使用Wireshark等分析工具

TLS 1.3在安全性上的一个重要改进,就是从ServerHello开始就使用加密,大幅减少了握手过程中的信息泄露。

参考来源