密码套件(Cipher Suite)选择:如何选择安全的密码套件,禁用不安全的套件
密码套件,说白了就是一组加密算法的组合。它决定了你的 SSL/TLS 连接怎么握手、怎么加密、怎么校验完整性。我见过太多开发者直接复制网上的配置,结果连 RC4 这种古董算法都没关掉。嗯,今天我们就来聊聊怎么选一套靠谱的密码套件。
密码套件长什么样?
一个典型的密码套件看起来像这样:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
拆开来看,它包含四个部分:
- 密钥交换算法:ECDHE(椭圆曲线 Diffie-Hellman 临时密钥)
- 身份验证算法:RSA
- 对称加密算法:AES_128_GCM
- 消息认证码算法:SHA256
我个人习惯把密码套件想象成一个「安全工具箱」。每个工具负责一件事,组合起来才能保证通信安全。缺一个都不行。
哪些套件该禁用?
我在项目中遇到过不少坑,有些套件看起来能用,实际上已经漏洞百出。下面这张表是我整理的「禁用清单」:
| 套件类型 | 原因 | 替代方案 |
|---|---|---|
| RC4 系列 | 存在多种攻击,已被 RFC 7465 明确禁止 | AES-GCM |
| CBC 模式(如 AES-CBC) | 易受 Padding Oracle 攻击 | GCM / ChaCha20-Poly1305 |
| 3DES | 密钥长度仅 112 位,不符合现代安全要求 | AES-128 或更高 |
| DSS / DSA | 签名算法过时,性能差 | ECDSA / EdDSA |
| 静态 DH / RSA 密钥交换 | 不支持前向安全性(PFS) | ECDHE / DHE |
| SHA-1 系列 | 碰撞攻击已成现实 | SHA-256 或更高 |
推荐的密码套件列表
那么,该用哪些套件呢?我个人推荐以下组合,按优先级排序:
TLS_AES_128_GCM_SHA256(TLS 1.3 默认)TLS_AES_256_GCM_SHA384(TLS 1.3 高安全)TLS_CHACHA20_POLY1305_SHA256(移动端推荐)TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(TLS 1.2)TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(TLS 1.2 兼容)
你想想看,为什么我特别推荐 ChaCha20-Poly1305?因为它在移动设备上性能极好。Android 设备大多有硬件加速的 AES,但有些低端机没有。ChaCha20 纯软件实现也能跑得飞快。我在做某款社交 App 时,切换到 ChaCha20 后握手时间缩短了 30%。
Android 中如何配置?
在 Android 上配置密码套件,主要通过 SSLSocket 或 SSLEngine 的 setEnabledCipherSuites() 方法。来看代码:
// 获取 SSLSocketFactory
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket("api.example.com", 443);
// 定义允许的套件列表
String[] allowedSuites = new String[] {
"TLS_AES_128_GCM_SHA256",
"TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
};
// 设置套件
socket.setEnabledCipherSuites(allowedSuites);
// 开始握手
socket.startHandshake();
SSLSocket.getSupportedCipherSuites() 动态过滤。这样升级算法时不用改客户端代码。
服务端也要配合
光客户端禁用没用,服务端也得同步。以 Nginx 为例:
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;
这里有个细节:ssl_prefer_server_ciphers on 表示服务端优先选择自己的套件列表。为什么要这么做?因为有些客户端会优先选不安全的套件。服务端强制一下,能避免很多问题。
密码套件选择的核心逻辑
为了让你更直观地理解,我画了一张流程图:
常见误区
最后,我总结几个容易踩的坑:
- 误区一:套件越多越好。其实不是。套件越多,攻击面越大。只保留必要的几个就行。
- 误区二:只看加密强度。AES-256 比 AES-128 安全?理论上是的,但实际中 AES-128 已经足够。更重要的是算法组合是否合理。
- 误区三:忽略前向安全性。没有 PFS 的套件,一旦私钥泄露,所有历史通信都会被解密。ECDHE 是必须的。
核心要点: 选择密码套件时,记住三个原则:前向安全、认证加密、强哈希。ECDHE + AES-GCM + SHA256 是黄金组合。别贪多,别图省事。
好了,关于密码套件的选择就聊到这里。配置好之后,记得用 sslyze 或 testssl.sh 扫一遍,看看有没有遗漏的不安全套件。安全这件事,多检查一遍总没错。