2. TLS 加密原理

先聊一个基本问题:TLS 到底怎么保护你的数据?

说白了就是两层加密。一个管安全握手,一个管高效传输。

2.1 对称加密 vs 非对称加密

特性对称加密非对称加密
密钥数量一把密钥,加解密都用它公钥+私钥,一对儿
性能极快,硬件加速友好(秒级 Gbps)慢,比对称慢 1000 倍以上
典型算法AES、ChaCha20RSA、ECC
核心问题密钥怎么安全地给到对方?公钥随意发,私钥自己守
TLS 中的角色加密传输数据(记录层)身份验证 + 安全传递对称密钥

我早期做 HTTPS 优化时踩过一个坑:以为全用 RSA 就能搞定。结果发现握手后只有对称加密在干活,RSA 只管「递钥匙」那一步。你想想看,如果每次连接都用非对称加密整个会话,服务器 CPU 直接冒烟。

TLS 的聪明之处就在这里:

  1. 非对称加密:握手阶段交换一个临时的对称密钥(叫 Pre-Master Secret)
  2. 对称加密:拿到这个临时密钥后,后续所有数据都用它加密传输
关键点:TLS 只用非对称加密做「钥匙配送」,真正的货物运输全靠对称加密。这个设计让安全性和性能都站住了脚。

2.2 密钥交换算法

「钥匙配送」这一步,历史上出现过好几种玩法,现在主流的是 ECDHE。

RSA 密钥交换

最古老也最简单:客户端用服务器公钥加密一个随机数,发给服务器,服务器用私钥解密得到对称密钥。我在一个金融项目里见过遗留系统还在用 RSA 密钥交换,当时检查日志发现每次重连都要重新协商,而且还不支持前向安全性。

避坑:RSA 密钥交换没有前向安全性。一旦私钥泄露,之前所有记录的会话都能被解密。我曾经建议客户把所有 RSA 密钥交换套件禁用掉,改用 ECDHE,对方一开始嫌麻烦,后来真的出事才后悔。

DH / DHE 密钥交换

Diffie-Hellman 让双方在不直接传递密钥的情况下,各自算出同一个共享密钥。

  • 静态 DH:服务器证书里固定一个 DH 参数,前向安全性依然差(私钥泄露,历史也能破)
  • 临时 DH(DHE):每次握手都用新生成的 DH 参数,即使以后私钥泄露,过去的会话仍然安全

DHE 的计算开销比较大,因为用的是大质数模幂运算。我在压测时见过 DHE 握手延迟比 RSA 高 3–5 倍。

ECDHE(Elliptic Curve Diffie-Hellman Ephemeral)

用椭圆曲线替代大质数,安全性更高,性能却更好。我现在的项目默认只开 ECDHE,配合 X25519 曲线,握手延迟降到 3ms 以内。

算法前向安全性性能当下建议
RSA 密钥交换❌ 无中等禁用
静态 DH❌ 无较慢禁用
DHE✅ 有慢可用(兼容旧客户端)
ECDHE✅ 有快首选

2.3 密码套件组成与协商

密码套件就是一串字符串,告诉 TLS 用哪套组合拳。

举个典型例子:TLS_AES_128_GCM_SHA256

  • TLS:协议版本
  • AES_128_GCM:对称加密算法(AES 128位,GCM模式,带认证)
  • SHA256:HMAC 哈希算法,用于消息完整性校验

如果是老版本 TLS 1.2,密码套件会更长,比如 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,这里面包含了密钥交换算法(ECDHE)和身份验证算法(RSA 签名)。

协商流程:

  1. 客户端发送 ClientHello,附上自己支持的密码套件列表(按优先级排序)
  2. 服务器从列表里选一个它也能支持的,通常选最安全且都接受的
  3. 服务器回复 ServerHello,带上选中的套件
  4. 后续握手就按这个套件定下来的算法跑
实战建议:我一般会在服务器上只保留 ECDHE + AES-GCM + SHA256 的套件,其他全删掉。既安全又快。如果遇到老客户端连不上,再慢慢补上兼容用的套件。

密码套件里的对称加密算法还会影响性能。我测试过 AES-GCM 和 ChaCha20-Poly1305,在移动端(没有 AES 硬件加速)ChaCha20 快 30% 以上。所以如果客户端是手机,我会优先选 ChaCha20 的套件。

TLS 1.3 握手加密与密钥交换流程(简化) 客户端 服务器 ① ClientHello (密码套件列表 + 密钥交换参数) 选择套件 ② ServerHello (选中的套件 + 服务器密钥交换参数) 计算共享密钥 计算共享密钥 对称加密(AES-GCM) 对称加密(AES-GCM) ③ 加密应用数据 密钥交换算法在握手阶段完成 ECDHE 生成临时共享密钥后,双方立即进入对称加密会话

这张图把 TLS 握手简化成三步,关键就是密钥交换那一步决定后续用什么对称密钥。你仔细看流程:客户端和服务器的「计算共享密钥」节点都标着绿色,说明这是握手阶段的核心,而且必须用 ECDHE 这类临时算法才能保证前向安全性。

我的经验:调优时我会抓包看 ClientHello 里发了多少套件。有的客户端带了几十个套件,服务器要花时间扫描匹配。我会在服务器端提前排序,让最安全的 ECDHE 套件排第一,减少协商时间。

对称加密的选型也影响整体质量。我建议:

  • 服务端有 AES-NI 指令集 → 用 AES-256-GCM
  • 移动端或 IoT 设备 → 用 ChaCha20-Poly1305(省电且无硬件加速也快)
  • 永远别开 CBC 模式(容易 padding oracle 攻击)

嗯,以上就是 TLS 加密体系的核心骨架。你把对称/非对称、密钥交换、密码套件这三块理清了,后面看再复杂的流量处理都能快速定位问题。