---
title: TLS 1.3 握手
url: https://doc.liz6.com/networking/05-tls-and-pki/02-tls-1-3-handshake
locale: zh
area: networking
tags:
- networking
- TLS与PKI
date: 2026-06-30
modified: 2026-07-16
description: TLS 1.3 握手流程详解:1-RTT 完整握手、key_share 如何省掉一轮往返、HKDF 密钥派生、0-RTT PSK 与重放攻击风险、Encrypted ClientHello。与 TLS 1.2 的核心区别:砍掉静态 RSA、强制前向安全、握手消息全加密。
---

# TLS 1.3 握手

> TLS 1.3 把握手压缩到 1-RTT,0-RTT 甚至零往返——手段是砍掉静态 RSA、强制前向安全、把密钥协商提前到 ClientHello。干净利落的协议设计,代价是 0-RTT 丧失了重放保护。

## 概述

TLS 1.3(RFC 8446, 2018)是对 TLS 1.2 的最大改版,而它的核心手法可以用一句话概括:**客户端不再"问服务器想用什么",而是直接猜**——在 ClientHello 里就带上 ECDHE 公钥(key_share),赌服务器支持 x25519(几乎总是赌对)。于是 TLS 1.2 里"先协商算法、再交换密钥"的两轮往返,坍缩成一轮;有会话票据时甚至零往返(0-RTT)。

设计目标四条:

1. **减少握手轮次**:2-RTT → 1-RTT(首次),0-RTT(重连)
2. **移除不安全算法**:静态 RSA 密钥交换、CBC、RC4、MD5/SHA-1——凡是历史上出过事的一律清除
3. **加密更多握手消息**:ServerHello 之后全部加密,被动窃听者连证书都看不到
4. **简化**:约 100 个 cipher suite 砍到 5 个

与 TLS 1.2 的关键区别一表看完:

| | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 首次握手 | 2-RTT | **1-RTT** |
| 会话恢复 | session ID / ticket, 1-RTT | PSK, **0-RTT** |
| 密钥交换 | RSA 或 (EC)DHE | 仅 (EC)DHE → **强制前向安全** |
| 握手加密 | 全明文 | ServerHello 后全加密 |
| Cipher suite | ~100 个,含密钥交换+签名 | 5 个,只含 AEAD + hash |
| 密钥派生 | PRF | HKDF |

## 1-RTT 完整握手流程

```mermaid
sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: ClientHello<br>key_share(x25519 公钥), cipher_suites,<br>supported_groups, signature_algorithms
    Note over S: 已能算出共享密钥<br>→ 之后的消息全部加密
    S->>C: ServerHello (key_share)<br>🔒 EncryptedExtensions<br>🔒 Certificate + CertificateVerify<br>🔒 Finished
    Note over C: 验证证书与签名,<br>算出相同密钥
    C->>S: 🔒 Finished + 应用数据
    Note over C,S: 第一个 RTT 结束时数据已在路上<br>(TLS 1.2 要等两个 RTT)
```

流程里藏着三个设计要点:

**key_share:密钥协商提前**。客户端为若干椭圆曲线各附一把 ECDHE 公钥(x25519 32 字节、secp256r1 65 字节),服务器挑一条曲线、回自己的公钥——双方在第一次往返内就完成了 Diffie-Hellman。猜错了怎么办?服务器回 `HelloRetryRequest` 指定曲线,客户端重发 ClientHello,退化为 2-RTT——实践中几乎不发生。

**认证与保密解耦**。TLS 1.2 的静态 RSA 把两件事绑在一起:服务器私钥既证明身份、又参与解密密钥——私钥一旦泄露,过去录下的全部流量都能回放解密。TLS 1.3 里密钥只来自每次全新的 ECDHE(**前向安全**),证书私钥只做一件事:对握手记录签名(`CertificateVerify`)证明"我确实是这个域名的主人"。

**Cipher suite 只剩 AEAD + hash 的组合**:

| Suite | 用途 |
|---|---|
| TLS_AES_128_GCM_SHA256 | 默认主力 |
| TLS_AES_256_GCM_SHA384 | 更高安全边际 |
| TLS_CHACHA20_POLY1305_SHA256 | 无 AES 硬件加速的移动端 |
| TLS_AES_128_CCM_SHA256 / CCM_8 | IoT 受限设备 |

## 密钥派生:HKDF

TLS 1.3 用 HKDF 取代 1.2 的 PRF,派生链是一个三级"密钥梯":

```
Early Secret     = HKDF-Extract(salt=0, PSK 或 0)          ← 0-RTT 密钥从这层出
Handshake Secret = HKDF-Extract(Early Secret, ECDHE 共享密钥) ← 握手加密密钥
Master Secret    = HKDF-Extract(Handshake Secret, 0)        ← 应用数据密钥
```

每一步 Expand 都混入 **transcript hash**(至今全部握手消息的哈希)——所以即使两次握手用了同一个 PSK,只要任何一条消息有一个字节不同,派生出的密钥就完全不同。这也是握手防篡改的根:改了任何消息,双方算出的 Finished 校验值对不上。

## 0-RTT PSK:重连零往返

首次握手后服务器发一张 session ticket(本质是 PSK)。重连时客户端在 ClientHello 里带上 PSK 标识和 binder,**同一个包里直接附上加密的应用数据**(early data)——服务器验证 PSK 后立即处理,一个往返都不等。

代价是安全性打折,必须清楚三条:

- **重放攻击**:攻击者原样重发抓到的 0-RTT 包,服务器会再处理一遍 early data。协议层没有完整防御,只能应用层自保——**0-RTT 里只放幂等操作**(HTTP 的 GET/HEAD),这正是各大 CDN 的实现方式。
- **无前向安全**:early data 的密钥只从 PSK 派生,PSK 泄露则过去所有 0-RTT 数据可解密(1-RTT 部分不受影响,因为混入了新的 ECDHE)。
- 服务器可用 `max_early_data_size` 限制敞口,或干脆拒绝 early data 强制回落 1-RTT。

## Encrypted ClientHello (ECH)

TLS 1.3 遗留的最后一块明文:ClientHello 本身——里面的 **SNI(目标域名)让中间设备仍能按域名审查/封锁**。ECH(ESNI 的继任,RFC 草案)补上这一块:

1. 服务器把 ECH 公钥发布在 DNS 的 HTTPS 记录(type 65)里。
2. 客户端把真实 ClientHello(含真实 SNI)加密成内层,外层用一个掩护域名(如 cloudflare-ech.com)。
3. 只有持有 ECH 私钥的服务器能解开内层;路径上的观察者只看到掩护域名。

配合 DoH/DoT(DNS 查询本身也加密,见 [DNS 隐私](/networking/04-DNS/03-dns-privacy-doh-dot-doq-odoh.md)),"用户访问了哪个网站"这条元数据才算真正藏住。

## 相关

TLS 1.2 的完整握手与它的历史包袱见 [TLS 1.2 握手](/networking/05-tls-and-pki/01-tls-1-2-handshake.md);证书链如何被验证见[证书与 PKI](/networking/05-tls-and-pki/03-certificates-and-pki.md);QUIC 把 TLS 1.3 直接内建进传输层,见 [HTTP/3](/networking/06-HTTP/03-HTTP3.md)。

## 参考

- **RFC**: 8446 (Appendix D 有 0-RTT 的安全分析)
- **ECH**: draft-ietf-tls-esni
- **工具**: `openssl s_client -tls1_3 -connect host:443` · Wireshark 过滤 `tls.handshake.type`
- **可视化**: tls13.xargs.org (逐字节图解 TLS 1.3 握手,极好)

*Keywords: TLS 1.3, TLS1.3 握手流程, 1-RTT, key_share, ECDHE, 前向安全, forward secrecy, 0-RTT, PSK, 重放攻击, session ticket, HKDF, transcript hash, ECH, SNI, cipher suite, TLS1.2 区别*
