# TLS 密码套件详解：命名规则、AEAD 与推荐配置

> 看懂 TLS 1.2 密码套件名字，弄清 TLS 1.3 为什么只剩 5 个套件、哪些该禁用，附 Nginx/Apache/宝塔配置和国密套件说明。

Source: https://ssl.sh/zh/learn/cipher-suites/
Last updated: 2026-11-10

密码套件（cipher suite）就是一次 TLS 连接所用算法组合的名字。TLS 1.2 的套件名把密钥交换、身份认证、对称加密和哈希四件事都写进去了；TLS 1.3 的套件名只管 AEAD 加密算法和密钥派生用的哈希，总共只有 5 个。截至 2026 年 11 月，稳妥的服务器配置是：TLS 1.3 用默认套件，TLS 1.2 只留少数几个 ECDHE + AES-GCM 或 ChaCha20-Poly1305 套件，其余全关。

## 拆开一个 TLS 1.2 套件名

TLS 1.2 套件名可以看成一句有四个空位的话，读懂它就知道连接会怎么做。

```text
TLS _ ECDHE _ RSA _ WITH _ AES_128_GCM _ SHA256
      |       |            |             |
      |       |            |             +-- PRF 用的哈希（CBC 套件里还是 HMAC 算法）
      |       |            +---------------- 对称加密算法、密钥长度和模式
      |       +----------------------------- 身份认证：证书的密钥类型
      +------------------------------------- 密钥交换方式
```

| 位置 | 常见取值 | 决定了什么 |
|---|---|---|
| 密钥交换 | `ECDHE`、`DHE`、`RSA` | 共享秘密怎么产生；只有临时的 (EC)DHE 才有前向保密 |
| 身份认证 | `RSA`、`ECDSA` | 能配合哪种证书 |
| 对称加密 | `AES_128_GCM`、`AES_256_GCM`、`CHACHA20_POLY1305`、`AES_128_CBC`、`3DES_EDE_CBC` | 记录怎么加密 |
| 哈希 | `SHA256`、`SHA384`、`SHA`（即 SHA-1） | TLS 的 PRF；CBC 套件里还用作记录 MAC |

当密钥交换和认证是同一种算法时名字会合并：`TLS_RSA_WITH_AES_128_CBC_SHA` 表示用 RSA 传输密钥、同时用 RSA 认证，根本没有临时密钥。

OpenSSL 有自己的一套短名字，`openssl ciphers -stdname` 可以两种名字对照着看：

```bash
openssl ciphers -stdname 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:AES128-SHA'
```

```text
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA    - ECDHE-RSA-AES128-SHA        TLSv1   Kx=ECDH Au=RSA Enc=AES(128)    Mac=SHA1
TLS_RSA_WITH_AES_128_CBC_SHA          - AES128-SHA                  SSLv3   Kx=RSA  Au=RSA Enc=AES(128)    Mac=SHA1
```

（OpenSSL 总会在最前面多打印三行 TLS 1.3 套件，这里省略了。）`TLSv1`、`SSLv3` 这一列表示该套件最早出现的协议版本，看到它基本就能判断是老套件。

## TLS 1.3：只有 5 个套件

TLS 1.3 把密钥交换和身份认证从套件名里拿掉了：密钥交换走 `supported_groups` 和 `key_share`，签名走 `signature_algorithms`，套件只负责选 AEAD 算法和 HKDF 哈希。

| 编号 | 名称 | RFC 9846 中的地位（与 RFC 8446 相同） | OpenSSL 3.x 默认启用 |
|---|---|---|---|
| 0x1301 | `TLS_AES_128_GCM_SHA256` | 必须实现 | 是 |
| 0x1302 | `TLS_AES_256_GCM_SHA384` | 应当实现 | 是 |
| 0x1303 | `TLS_CHACHA20_POLY1305_SHA256` | 应当实现 | 是 |
| 0x1304 | `TLS_AES_128_CCM_SHA256` | 可选 | 否 |
| 0x1305 | `TLS_AES_128_CCM_8_SHA256` | 可选，认证标签只有 8 字节 | 否 |

这一改动终结了 TLS 1.2 时代的组合爆炸：IANA 注册表里为各种“交换 × 签名 × 加密 × 哈希”组合登记了数百个编号。代价是光看 TLS 1.3 套件名，看不出密钥交换用的是 X25519、P-256 还是混合的 X25519MLKEM768，工具会单独报告，比如 `openssl s_client -brief` 里的 `Negotiated TLS1.3 group: X25519MLKEM768`。

2026 年 7 月发布的 TLS 1.3 修订版 RFC 9846 版本号仍是 0x0304，5 个套件也没有变；它在澄清条文的同时，把密钥交换的描述改得更通用，让 ML-KEM 这类基于 KEM 的密钥交换也能自然纳入规范。

两个 CCM 套件是给资源受限设备准备的。QUIC（RFC 9001）明确禁止 `TLS_AES_128_CCM_8_SHA256`，因为 8 字节标签对通用场景太短。

## 国密套件与 TLCP

RFC 8998 在 TLS 1.3 框架里加入了两个国密套件，适合有合规要求的国内系统。

| 编号 | 名称 | 算法 |
|---|---|---|
| 0x00C6 | `TLS_SM4_GCM_SM3` | SM4-GCM 加密，SM3 哈希 |
| 0x00C7 | `TLS_SM4_CCM_SM3` | SM4-CCM 加密，SM3 哈希 |

配合 SM2 签名证书和 curveSM2 密钥交换组使用。在 IANA 注册表里这两个套件标记为“不推荐”，意思只是 IETF 没有对它们做通用推荐，并不代表有已知弱点。

国内政务、金融等行业更常见的是另一套协议 TLCP（GB/T 38636-2020），它沿用类似 TLS 1.1/1.2 的结构，采用签名证书 + 加密证书的双证书体系，与 RFC 8998 不是一回事。标准版 Chrome、Firefox 两者都不支持，需要国密浏览器、铜锁（Tongsuo）等国密 TLS 库或专用网关。面向公众的网站通常同时部署一张国际算法证书，保证普通浏览器能访问。

## 套件是怎么协商出来的

客户端出价，服务器拍板。ClientHello 按偏好顺序列出客户端支持的全部套件，服务器从中选一个自己也支持的，写进 ServerHello；完全没有交集时，服务器回 `handshake_failure` 告警。

在 TLS 1.2 里，选定一个套件会连带其他约束：

- 选 `ECDHE_ECDSA` 套件，服务器必须有 ECDSA 证书；选 `ECDHE_RSA` 套件，必须有 RSA 证书；
- ECDHE 用的曲线来自客户端的 `supported_groups`，可能套件对得上、曲线却对不上；
- ServerKeyExchange 的签名必须用客户端在 `signature_algorithms` 里列出的哈希。

TLS 1.3 把这三件事拆开了：服务器分别从各自的列表里选 AEAD 套件、`key_share` 里的组（或用 HelloRetryRequest 要一个别的）、和证书匹配的签名算法。所以加一个后量子密钥交换组或换一张 Ed25519 证书，都不需要新的密码套件。

客户端这边的列表往往改不了：浏览器随版本内置固定列表；Java 读 `java.security` 文件里的 `jdk.tls.disabledAlgorithms`；Windows Schannel 的顺序由组策略或 PowerShell（`Get-TlsCipherSuite`）控制；curl、Python 继承它们链接的 TLS 库的默认值。内部系统连不上加固后的服务器时，先查清客户端用的是哪个库、哪个版本，再决定要不要动服务器。

## AEAD：现代套件为什么都用它

AEAD（带关联数据的认证加密）用一个算法同时完成加密和认证，TLS 1.3 只允许 AEAD。常见的三种是 AES-GCM、ChaCha20-Poly1305（RFC 7905）和 AES-CCM。

老式 TLS 用 CBC 模式加独立的 HMAC，而且是“先 MAC 后加密”。这种结构会通过填充校验和时间差泄露信息，带来了长达十年的攻击：BEAST（2011，针对 TLS 1.0 可预测的 IV）、Lucky Thirteen（2013，CBC 填充的时间侧信道）、POODLE（2014，针对 SSL 3.0）。AEAD 没有可利用的填充预言机。ChaCha20-Poly1305 在纯软件实现下也很快，没有 AES 指令的手机和小型 ARM 设备更愿意用它。见 [AEAD](https://ssl.sh/zh/glossary/aead/)。

## 前向保密与密钥交换

只有密钥交换以 `ECDHE` 或 `DHE` 开头的套件才有[前向保密](https://ssl.sh/zh/glossary/forward-secrecy/)。静态 `RSA` 密钥交换是客户端用证书公钥加密预主密钥发给服务器，日后谁拿到这把私钥，就能解密所有录下来的会话。

| 密钥交换 | 前向保密 | 现状 |
|---|---|---|
| `RSA`（密钥传输） | 无 | 应删除；还容易受 ROBOT（2017）这类填充预言机攻击 |
| `DHE`（有限域） | 有 | 慢，且只有 2048 位以上的组才安全；Mozilla 6.0 版已不再推荐 |
| `ECDHE` | 有 | TLS 1.2 推荐使用 |
| TLS 1.3 的 (EC)DHE / 混合算法 | 有 | 始终使用（纯 PSK 恢复除外） |

一个容易忽略的点：会话票据是用服务器端的票据密钥加密的。如果这把密钥几个月都不换并且泄露，恢复过的会话就能被解密。要定期轮换票据密钥，做不到就关闭票据。

## 哪些要关、为什么

没有 AEAD、没有前向保密、或底层算法已被攻破的，都应该关掉。老服务器上还能见到的有：

| 类别 | 例子（OpenSSL 名） | 问题 |
|---|---|---|
| NULL | `NULL-SHA256` | 根本不加密 |
| 匿名 | `ADH-AES128-SHA` | 不认证身份，中间人随便冒充 |
| 出口级 | `EXP-RC4-MD5` | 故意削弱到 40/56 位；FREAK、Logjam（2015） |
| RC4 | `RC4-SHA` | 统计偏差；RFC 7465（2015）禁止 |
| DES / 3DES | `DES-CBC3-SHA` | 64 位分组；Sweet32（2016）在约 2^32 个分组（32GB）后出现碰撞 |
| CBC + SHA-1 | `ECDHE-RSA-AES128-SHA` | 先 MAC 后加密，填充和时间差问题 |
| 静态 RSA | `AES128-GCM-SHA256` | 没有前向保密 |
| CCM_8 | `TLS_AES_128_CCM_8_SHA256` | 标签太短，不适合 Web |

新版 OpenSSL 已经把最糟糕的那些排除在外：在 OpenSSL 3.6 上执行 `openssl ciphers -v 'RC4'` 和 `openssl ciphers -v '3DES'` 都会返回 “no cipher match”。RFC 9325（BCP 195，2022 年 11 月）列出了 IETF 目前推荐的 TLS 1.2 套件，和下面的 ECDHE + AEAD 列表一致。

## 推荐配置

公网服务器按 Mozilla 的 intermediate 档配置：TLS 1.2 和 1.3 都开，TLS 1.2 只留 6 个 ECDHE 套件。Mozilla 的指南是事实上的参考标准，截至 2026 年 11 月的最新版是 6.0，分两档：

- **modern**：只开 TLS 1.3，套件为 `TLS_AES_128_GCM_SHA256`、`TLS_AES_256_GCM_SHA384`、`TLS_CHACHA20_POLY1305_SHA256`。最老能兼容的客户端包括 Firefox 63、Chrome 70、Safari 12.1、Android 10、Java 11。
- **intermediate**：开 TLS 1.2 和 1.3。TLS 1.2 只允许 6 个套件：`ECDHE-ECDSA-AES128-GCM-SHA256`、`ECDHE-RSA-AES128-GCM-SHA256`、`ECDHE-ECDSA-AES256-GCM-SHA384`、`ECDHE-RSA-AES256-GCM-SHA384`、`ECDHE-ECDSA-CHACHA20-POLY1305`、`ECDHE-RSA-CHACHA20-POLY1305`；密钥交换组为 `X25519MLKEM768`、`X25519`、`prime256v1`、`secp384r1`；不强制服务器套件顺序。

和 5.7 版相比，6.0 删掉了 3 个 DHE 套件，加入了后量子混合组。按 intermediate 写的 Nginx 配置：

```nginx
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
# X25519MLKEM768 需要 Nginx 链接 OpenSSL 3.5 或更高版本
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1:secp384r1;
```

`ssl_ciphers` 只管 TLS 1.2 及以下。TLS 1.3 套件来自 OpenSSL 默认值，本来就是上面那三个；确实要改的话，Nginx 1.19.4 起可以用 `ssl_conf_command Ciphersuites ...`。如果 Nginx 链接的 OpenSSL 低于 3.5，要把 `X25519MLKEM768` 从曲线列表里去掉，否则 Nginx 会启动失败。先用 `nginx -V 2>&1 | grep -i openssl` 确认版本。

Apache 用协议前缀单独设置 TLS 1.3 套件：

```apache
SSLProtocol             -all +TLSv1.2 +TLSv1.3
SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
SSLCipherSuite TLSv1.3  TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
SSLHonorCipherOrder     off
```

每个 TLS 1.2 套件都出现了两次，一次给 ECDSA 证书、一次给 RSA 证书。服务器可以同时挂两种证书，按客户端能力分别下发。其他服务器的配置片段可以用 [TLS 配置生成器](https://ssl.sh/zh/tools/tls-config-generator/)生成。

国内常见环境的改法：

- **宝塔面板**：在网站设置里打开“配置文件”，找到 `ssl_protocols`、`ssl_ciphers` 两行按上面替换，保存后宝塔会自动检查并重载 Nginx。
- **阿里云、腾讯云负载均衡 / CDN**：HTTPS 监听或域名的 HTTPS 配置里都有预置的 TLS 安全策略，选只含 TLS 1.2/1.3、且只有 ECDHE + GCM/ChaCha20 套件的那一档；需要兼容老客户端时再放宽，而不是在源站上改。

## 用 OpenSSL 查看和测试套件

`openssl ciphers -v` 会把套件串展开成具体套件，上线前可以先核对：

```bash
openssl ciphers -v 'ECDHE+AESGCM:ECDHE+CHACHA20' | grep TLSv1.2
```

```text
ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(256)            Mac=AEAD
ECDHE-RSA-AES256-GCM-SHA384    TLSv1.2 Kx=ECDH     Au=RSA   Enc=AESGCM(256)            Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256  TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(128)            Mac=AEAD
ECDHE-RSA-AES128-GCM-SHA256    TLSv1.2 Kx=ECDH     Au=RSA   Enc=AESGCM(128)            Mac=AEAD
ECDHE-ECDSA-CHACHA20-POLY1305  TLSv1.2 Kx=ECDH     Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
ECDHE-RSA-CHACHA20-POLY1305    TLSv1.2 Kx=ECDH     Au=RSA   Enc=CHACHA20/POLY1305(256) Mac=AEAD
```

检查线上服务器接受哪些套件，就用 `s_client` 一次指定一个：TLS 1.2 及以下用 `-cipher`，TLS 1.3 用 `-ciphersuites`。

```bash
# 服务器在 TLS 1.2 下还接受 CBC 套件吗？
openssl s_client -connect example.com:443 -tls1_2 -cipher ECDHE-RSA-AES128-SHA </dev/null
# TLS 1.3 下接受 ChaCha20 吗？
openssl s_client -connect example.com:443 -tls1_3 -ciphersuites TLS_CHACHA20_POLY1305_SHA256 </dev/null
```

返回 handshake failure 告警说明该套件已关闭。[套件与协议命令手册](https://ssl.sh/zh/cookbook/ciphers-and-protocols/)里有逐个测试全部套件的循环脚本，[密码套件查询](https://ssl.sh/zh/tools/cipher-suite-lookup/)可以解析任何 IANA 或 OpenSSL 名称。

## 顺序与性能

只开强套件时，顺序影响的是性能而不是安全。客户端按自己的偏好排序，没有 AES 硬件加速的手机会把 ChaCha20-Poly1305 排在前面。服务器如果强制把 AES-GCM 放第一，这些设备就用不上更快的算法，所以 Mozilla 现在建议让客户端选。OpenSSL 还有个 `PrioritizeChaCha` 选项：保留服务器顺序，但客户端把 ChaCha20 放第一时尊重客户端。

客户端和服务器一个共同套件都没有时握手失败，Chrome 显示 [ERR_SSL_VERSION_OR_CIPHER_MISMATCH](https://ssl.sh/zh/errors/err-ssl-version-or-cipher-mismatch/)。常见原因是只开 TLS 1.3 或冷门套件的服务器碰上了老客户端，或者只会 3DES、RC4 的老设备碰上了新服务器。能改服务器列表就改列表，不要为此重新打开已被攻破的套件。
