TLS/SSL 协议深度解析:握手过程、证书链验证、密码套件选择、TLS 1.3 新特性
说到加密接口安全,TLS/SSL 是绕不开的基础设施。我做过不少审计项目,发现很多团队虽然配了证书、启用了 HTTPS,但握手细节和证书链验证经常被忽略。说白了,配置错了等于没配。今天咱们就把这块硬骨头啃下来。
4.1 握手过程:不是你想的那么简单
TLS 握手是整个协议的核心。它的目标就三个:身份认证、密钥协商、加密开始。你想想看,客户端和服务端之前互不相识,怎么就能安全地交换密钥呢?
4.1.1 传统 TLS 1.2 握手(完整版)
先看 TLS 1.2 的完整握手。我记得第一次抓包分析这个流程时,整整看了一天。
- ClientHello:客户端发个招呼,带上支持的 TLS 版本、密码套件列表、一个随机数。
- ServerHello:服务端选一个密码套件、发自己的随机数,顺便把证书甩过来。
- Certificate:服务端证书链,包含服务器证书、中间证书,有时还会带上根证书。
- ServerKeyExchange:如果密码套件需要(比如 DHE 或 ECDHE),服务端会发送密钥交换参数。
- ServerHelloDone:服务端说“我说完了,轮到你”。
- ClientKeyExchange:客户端根据服务端的参数,生成预备主密钥,加密后发给服务端。
- ChangeCipherSpec:双方各自切换加密策略,后续开始加密通信。
- Finished:发送一条加密后的消息,验证握手没被篡改。
这里有个容易踩的坑——ServerKeyExchange 这一步。如果是 RSA 密钥交换,这一步可以没有。但如果是 ECDHE,服务端必须发公钥和签名。我在项目中遇到过开发直接写死 RSA,结果安全审计时被判定为“前向安全性不足”。
4.1.2 握手流程可视化
光讲文字有点干,我画了一张图帮你直观理解。
4.2 证书链验证:别只看叶子证书
很多人觉得证书验证就是检查证书是否过期。其实远不止这些。我见过一个真实案例——某个金融 App 上线前审计,发现证书链中间证书居然在本地存储中硬编码了私钥。嗯,这可是大事故。
4.2.1 证书链是什么?
证书链就像是一份担保书:
- 叶子证书:你的网站域名,由中间 CA 签发。
- 中间证书:由根 CA 签发,负责代理签发叶子证书。
- 根证书:预装在操作系统或浏览器中的信任锚点。
说白了,浏览器不会直接信任任何证书。它必须通过根证书这个“老祖宗”来验证整条链。如果链断了,浏览器会跳警告。
4.2.2 验证步骤
- 签名验证:从叶子证书开始,用上一级证书的公钥验证本证书的数字签名。
- 有效期检查:每个证书的生效时间需覆盖当前时间。
- 域名匹配:叶子证书的 CN 或 SAN 必须和访问的域名一致。
- 吊销检查:通过 CRL 或 OCSP 确认证书未被吊销。
我记得有一次在审计一个海外部署项目时,发现他们的根证书是自签的。开发说“本地测试没问题啊”。但实际上,移动端和浏览器根本无法信任自签根证书。正确的做法是使用受信任的公共 CA 或搭建内部 CA 并预先分发根证书。
4.3 密码套件选择:不是越新越好
密码套件决定了加密的强度、密钥交换的方式以及消息认证的算法。我建议你把它当成“菜单”——选错了菜,可能消化不良。
4.3.1 密码套件结构
一个典型的密码套件长这样:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
| 字段 | 含义 | 我个人的推荐 |
|---|---|---|
| TLS | 协议 | 固定 |
| ECDHE | 密钥交换算法 | 优先 ECDHE 或 DHE |
| RSA | 身份认证算法 | RSA 或 ECDSA(ECDSA 更轻量) |
| AES_256_GCM | 对称加密算法及模式 | AEAD 模式(GCM、CCM) |
| SHA384 | 消息认证码哈希算法 | SHA256 或以上 |
4.3.2 推荐的密码套件清单
TLS_AES_128_GCM_SHA256(TLS 1.3 默认)TLS_AES_256_GCM_SHA384(TLS 1.3 高安全)TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(TLS 1.2 推荐)TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(TLS 1.2 高安全)
4.4 TLS 1.3 新特性:不是简单的升级
TLS 1.3 在 2018 年正式发布,它把老版本的很多历史包袱全扔了。我特别喜欢它的一点——握手从 2 次往返降到 1 次。你想想看,在弱网环境下这能省多少时间。
4.4.1 主要变化
- 移除不安全算法:RSA 密钥交换、RC4、3DES、CBC 模式全被删除。
- 使用 AEAD 加密:只允许 GCM、CCM、ChaCha20-Poly1305 这类认证加密算法。
- 握手简化:合并 ServerHello 和 Certificate,去掉 ServerKeyExchange、ChangeCipherSpec。
- 0-RTT 模式:客户端可以在第一次消息中就携带应用数据,适合短连接场景。
4.4.2 0-RTT 的隐患
0-RTT 虽然快,但有重放攻击的风险。攻击者如果截获了客户端的 0-RTT 数据,可以多次发送给服务器。我在审计一个 IoT 平台时发现它们的传感器上报数据用了 0-RTT,结果重复数据导致后端的幂等性处理失效。
4.4.3 迁移建议
如果你还在用 TLS 1.2,建议逐步向 1.3 迁移。但不是所有客户端都支持 1.3。我一般策略是:
- 服务端同时开启 1.2 和 1.3。
- 1.2 只保留 ECDHE + AES-GCM 的高强度套件。
- 1.3 启用并禁用所有向后兼容的降级机制。
好了,这一节的深度解析就到这里。要记住,TLS 不是配完证书就完事的。握手细节、证书链、密码套件选择,每一项都会影响你的接口安全等级。下次遇到加密接口审计,不妨从这些维度入手,你会发现很多被忽视的漏洞。