第2章:密码学基础——对称加密、非对称加密、哈希函数
聊TLS之前,得先把密码学那三块老本行搞明白。我见过不少同学,一上来就研究TLS握手协议,结果搞混了签名与加密、混淆了对称与非对称性能差异,后面Debug时一脸懵。说白了,整个TLS的安全性就靠这三根柱子撑着——对称加密、非对称加密、哈希函数。
这一章我带你用"工程师"的视角重新看它们,不堆数学公式,重点说清楚:每个东西解决什么问题、有什么坑、以及它们在TLS里是怎么搭伙干活的。
对称加密——最快的密码学选手
对称加密,你想想看:加密和解密用的是同一个密钥。就像你和我的共享小本本,我写密码之前我俩约定好,用同一把锁。效率极高,尤其是AES这种算法,用硬件加速更是快到飞起。
我在项目中遇到过一个大流量网关,每秒要处理几十万条消息。当时选了非对称加密做整个链路……结果CPU直接打满,延迟暴增。后来切回对称加密(AES-128-GCM),同样的机器处理能力翻了快5倍。所以对称加密就是"速度快、适合大数据量"的选手,但有一个致命问题:密钥怎么安全地给到对方?
| 算法 | 密钥长度 | 典型分组模式 | 实际场景 |
|---|---|---|---|
| AES | 128 / 192 / 256 bit | GCM、CBC、CTR | TLS记录层加密 |
| ChaCha20 | 256 bit | Poly1305 | 移动端TLS(无AES硬件加速时) |
| 3DES(已过时) | 112 bit | CBC | 遗留系统兼容(不要再用) |
重要:
TLS 1.3 里只允许 AEAD 模式的对称加密(AES-GCM / ChaCha20-Poly1305),CBC 模式已经被完全移除了。原因你往后看就知道了——CBC 有一堆填充预言机攻击。
非对称加密——密钥分发的救星
非对称加密有公钥私钥这一对。你可以把公钥扔到大街上,大家都能用它加密数据,但只有拥有私钥的你能解密。说白了:公钥加密,私钥解密。
那它的缺点呢?慢。非常慢。RSA-2048 比 AES-256 慢大概 1000~3000 倍。所以你不可能用非对称加密去传整条视频流。TLS 的做法很聪明:非对称加密只用来交换一个临时对称密钥(或者说用来验证身份),后面的数据全交给对称加密。
我记得曾经在配置一个老旧 HTTPS 服务器时,对方坚持只使用 RSA 密钥交换,不给配 ECDHE。结果每次握手都要做 RSA 解密操作,几百并发就把服务器整垮了。后来我帮他改成 ECDHE+RSA 签名,握手延迟从 300ms 降到了 15ms。这就是非对称加密的正确用法——只在必要的环节用,别滥用。
| 算法 | 典型用途 | 性能开销 | 安全性状态 |
|---|---|---|---|
| RSA | 密钥传输 / 签名 | 慢(特别是解密) | 2048位以上安全,1024位已破 |
| ECDHE | 临时密钥协商(前向安全) | 快(椭圆曲线运算) | 推荐用于TLS 1.3 |
| Ed25519 | 数字签名 | 极快、可抵抗量子部分攻击 | 现代首选签名算法 |
实用建议:
新项目直接选 ECDHE 密钥交换 + Ed25519 签名。RSA 的密钥传输方式已经不具备前向安全性——如果私钥被偷,所有历史通话都能被解密。
哈希函数——唯一的指纹盖章
哈希函数不讲武德,你给它任意长度的输入,它输出固定长度的摘要(比如 SHA-256 就是 32 字节)。而且你很难通过摘要反推出原始数据,也很难找到两个不同的输入产生相同输出。
在 TLS 里哈希函数干什么用?四个场景:
- 证书签名验证——CA 对证书哈希值签名,你验证时算一次哈希再验签。
- 消息认证码(HMAC)——用哈希 + 密钥来保证数据完整性和真实来源。
- 密钥派生——从共享秘密导出会话密钥,TLS 1.3 用的 HKDF 就是拿哈希当轮子。
- 数字签名摘要——先对消息做哈希,再对哈希签名,节省大文件签名时间。
我踩过一个大坑:有一次接手一个旧版TLS配置,证书的签名哈希算法还是 SHA-1。Chrome 57 以后直接报不安全,但当时我忘记检查降级兼容……结果某些用户频繁收到证书错误。SHA-1 目前已经被学术界证明碰撞可行(2017 年 Google 和 CWI 发布了首个碰撞实例)。不要再用 SHA-1 做签名了。
警告:
SHA-1 在数字签名中已经不安全。TLS 1.2 虽然还允许 SHA-256 以上的签名算法,但 TLS 1.3 已经彻底弃用了 SHA-1。你配置服务器时请确保签名算法至少是 SHA-256。
三者如何配合?我画了一张图
对称加密、非对称加密、哈希函数不是各自为战,而是紧密协作——非对称解决密钥分发,对称解决数据加密,哈希解决完整性验证。下面这张流程图能帮你直观理解它们的关系。
你看,非对称加密先跑一步,交换出一个对称密钥(比如 ECDHE 做完后双方得到同样的 pre-master secret),接着对称加密接管数据通道,用这个密钥加密 HTTP 请求。哈希函数在每一步里面都起作用——HMAC 用于认证加密数据的完整性,证书签名需要计算哈希再加密,密钥派生也全靠它。少了任何一个环节,TLS 的安全模型都会出大问题。
避坑清单(我自己都摔过)
- 对称加密模式选错:别用 ECB 模式,它会把相同明文块加密成相同密文块,一看就知道重复内容。TLS 1.2 之前曾用 CBC,但容易出 Padding Oracle 攻击;现在只信任 AEAD 模式。
- 密钥长度别凑合:AES-128 目前足够安全,但如果你对接政府或金融系统,对方可能强制 AES-256。非对称方面,RSA 请不要低于 2048,否则审计过不去。
- 二次哈希不增加强度:我曾经见过有人对密码先 MD5 再 SHA-1 再 SHA-256,以为更安全。实际上哈希碰撞概率是由最长输出决定的,瞎叠加反而增加实现风险。
- 哈希函数的长度扩展攻击:SHA-2 家族(SHA-256/384/512)是 Merkle–Damgård 结构,直接拿它做 MAC 有长度扩展风险。一定要用 HMAC 或者直接上 SHA-3(如 BLAKE2)。TLS 里用的就是 HMAC,所以没问题。
我的习惯:
配置 TLS 密码套件时,我永远把 TLS_AES_128_GCM_SHA256 放在首选(完美平衡安全与性能)。如果客户端是 iOS 或老旧设备没有 AES 硬件加速,就备选 TLS_CHACHA20_POLY1305_SHA256。签名证书我全用 Ed25519,只要平台支持。