第3章 密码套件详解:对称与非对称加密、哈希算法、常见套件安全等级

密码套件这东西,说白了就是 HTTPS 握手里最终用来保护数据的“武器组合”。我刚开始搞 TLS 配置的时候,看到一串像 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 的套件名字,感觉就像看天书。后来调多了才明白,每个字段都在告诉你:用什么密钥交换、用什么证书签名、用什么对称加密、用什么哈希做完整性校验。

这章我们就把这些零件一个个拆开,看看它们各自的戏份,再给常见套件排个安全等级。

对称加密:又猛又快,但有一个致命问题

对称加密就是通信双方用同一个密钥加密和解密。好处很明显——快。AES(高级加密标准)是现在最主流的,我见过大多数生产环境都在用 AES-128 或 AES-256。

不过有个硬伤:怎么安全地把那个密钥交给对方?你在网上发,中间人截获你就完了。这就引出了非对称加密。

我的习惯:对称加密我用 AES-256-GCM,它自带认证标签(Auth Tag),能防篡改也防重放。以前测试时用过 CBC 模式,结果发现需要额外处理填充攻击,有点麻烦,后来就全切 GCM 了。

非对称加密:公钥私钥各干各的

非对称加密把密钥拆成一对:公钥随便给人,私钥自己藏着。别人用公钥加密的数据,只有私钥才能解开。这完美解决了密钥分发问题。

但它慢。一套 RSA-2048 的加解密操作,能比 AES 慢好几个数量级。所以实际 TLS 握手里只用它做两件事:密钥交换和数字签名。

  • RSA:经典方案,支持密钥交换和数字签名。但现在我建议尽量别用纯 RSA 做密钥交换,因为一旦私钥泄露,之前所有的通信记录都能被解密(没有前向安全性)。
  • ECDHE:临时椭圆曲线 Diffie-Hellman。每次握手都生成临时密钥对,即使服务器私钥被偷,以前的会话也解不开——这叫前向安全性(Perfect Forward Secrecy)。我个人非常推荐。
避坑指南: 我曾经在一个项目中,发现运维为了让老旧安卓机兼容,把 ECDHE 套件全部去掉了,只留了 RSA 密钥交换。结果半年后有人买到了泄露的服务器私钥,所有历史流量都能解密。后来我们紧急升级配置,强制启用 ECDHE,才补上这个窟窿。

哈希算法:数据完整性的大管家

哈希算法把任意长度的数据压缩成固定长度的摘要(digest)。你发送一个文件,附上它的 SHA-256 哈希值,接收方一算就能知道文件有没有被篡改。

在 TLS 套件里,哈希算法有两个角色:

  1. 证书签名验证:CA 用 SHA-256 对证书内容做哈希,再用自己的私钥加密这个哈希值,生成数字签名。
  2. HMAC 或 AEAD 里的认证:像 AES-256-GCM 里的 GCM 模式直接集成了认证标签,而老的 CBC 模式需要额外的 HMAC 来做数据完整性。

现在最安全的是 SHA-256 和 SHA-384。SHA-1 已经废了,我在 2017 年就发现不少旧设备还在用 SHA-1 签名,Chrome 直接弹出警告。所以能切就赶紧切。

套件安全等级归纳:你该用哪些、弃哪些

我按实际生产经验,把常见套件分了四个等级。你配置服务器时,直接参考这个表就行。

等级 典型套件示例 说明
A+(最优) TLS_AES_256_GCM_SHA384(TLS 1.3)
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS 1.3 原生套件或 ECDHE + AEAD,前向安全 + 硬件加速友好
A(推荐) TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
主流配置,性能与安全均衡,Chacha20 对移动端很友好
B(可接受) TLS_RSA_WITH_AES_128_GCM_SHA256 无前向安全,但用了 AEAD 模式。仅用于兼容不支持 ECDHE 的陈旧客户端
F(禁用) TLS_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
CBC 模式 + SHA-1 容易受攻击(BEAST, Lucky13),3DES 已经被 NIST 废弃

你看,真正推荐的都是 ECDHE + GCM 或 Chacha20 的组合。你想想看,如果用了 RSA 密钥交换,等于放弃前向安全,这风险何必去冒?

我的配置原则: 只开 ECHDE 系列 + 强制 AEAD 模式(GCM 或 Chacha20-Poly1305),哈希用 SHA-256 或 SHA-384。TLS 1.3 自然满足这些条件,所以如果条件允许,直接升级到 TLS 1.3 最省心。

一张图看懂密码套件结构

下面我把密码套件的组成画成一张结构图。你看清每个环节的依赖关系,配置时就不会乱。

密码套件结构图 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 密钥交换 ECDHE / DHE 身份认证 RSA / ECDSA 对称加密 AES / Chacha20 哈希 & 认证 SHA256 / GCM 安全等级分级(从高到低) A+ 级 A 级 B 级 F 级(禁用) 判定标准:前向安全 + AEAD + 无已知弱点

实战中怎么控制套件顺序?

很多 web 服务器配置里,套件是可以写多个的,客户端握手时会根据双方共同支持的套件,按服务端的优先顺序选择一个。我的做法是这样:

# 强烈推荐(A+ / A 级)放在最前面
TLS_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
# 兼容降级(B 级)放中间,但一定要开启前向安全
TLS_RSA_WITH_AES_128_GCM_SHA256
# 不写任何 F 级套件

嗯,这里要注意:有些框架会自动补入一些老套件,比如 OpenSSL 默认配置里可能包含 DHE-RSA-AES256-SHA。我建议你每次部署后跑一遍 SSL Labs 测试,看看实际协商出的套件是不是你想要的。我曾经就因为没检查,发现某个内部接口还在用 3DES,吓了一跳。

一句话总结: 密钥交换选 ECDHE,对称加密选 AES-256-GCM 或 Chacha20-Poly1305,哈希让 GCM 模式帮你带着,哈希摘要用 SHA-256 以上。套件等级按我们刚讲的表卡就行。