第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 里哈希函数干什么用?四个场景:

  1. 证书签名验证——CA 对证书哈希值签名,你验证时算一次哈希再验签。
  2. 消息认证码(HMAC)——用哈希 + 密钥来保证数据完整性和真实来源。
  3. 密钥派生——从共享秘密导出会话密钥,TLS 1.3 用的 HKDF 就是拿哈希当轮子。
  4. 数字签名摘要——先对消息做哈希,再对哈希签名,节省大文件签名时间。

我踩过一个大坑:有一次接手一个旧版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。

三者如何配合?我画了一张图

对称加密、非对称加密、哈希函数不是各自为战,而是紧密协作——非对称解决密钥分发,对称解决数据加密,哈希解决完整性验证。下面这张流程图能帮你直观理解它们的关系。

密码学三元素在 TLS 中的协作关系 对称加密 AES-GCM / ChaCha20 加密数据内容 非对称加密 ECDHE / Ed25519 密钥协商 & 身份验证 哈希函数 SHA-256 / SHA-384 完整性 & 摘要验校 协商密钥 加密数据 验证标签 三者协作产出:安全信道 非对称交换密钥 → 对称加密后续数据 → 哈希保证不被篡改 签名

你看,非对称加密先跑一步,交换出一个对称密钥(比如 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,只要平台支持。