Diffie-Hellman\ 与\ ECDHE
如果你问的是 Diffie-Hellman(DH)和 ECDHE,那它们是 TLS/HTTPS 中最重要的密钥交换算法之一。
很多人学 TLS 时有个疑问:
浏览器已经拿到了服务器公钥,为什么还需要 ECDHE?
答案是:
RSA/ECDSA 负责证明”你是谁”,ECDHE 负责生成”本次会话密钥”。
这是两个完全不同的问题。
先理解一个问题
假设:
1 | 客户端 A |
他们第一次见面。
现在希望得到一个:
1 | 共享密钥 |
例如:
1 | K = abc123 |
以后所有数据:
1 | AES(K) |
加密传输。
问题来了:
1 | 网络被监听 |
如果直接发送:
1 | abc123 |
攻击者也看到了。
那怎么办?
Diffie-Hellman 的伟大发明
1976年,Whitfield Diffie 和 Martin Hellman 提出:
双方不用发送密钥,也能算出同一个密钥。
这在当时是革命性的。
一个简化例子
真实算法涉及大整数和模运算。
先用颜色来理解。
公开信息:
1 | 黄色 |
大家都知道。
客户端秘密选择:
1 | 蓝色 |
服务器秘密选择:
1 | 红色 |
客户端计算:
1 | 黄色 + 蓝色 |
发给服务器。
服务器计算:
1 | 黄色 + 红色 |
发给客户端。
攻击者能看到:
1 | 黄色 |
但看不到:
1 | 蓝色 |
客户端:
1 | 橙色 + 蓝色 |
服务器:
1 | 绿色 + 红色 |
双方得到同一个结果。
攻击者没有:
1 | 蓝色 |
算不出来。
真正的 DH
实际使用数学:
公开参数:
1 | g |
所有人都知道。
客户端:
随机生成:
1 | a |
私密。
计算:
A=g^a\bmod p
发送:
1 | A |
服务器:
随机生成:
1 | b |
私密。
计算:
B=g^b\bmod p
发送:
1 | B |
客户端计算:
K=B^a\bmod p
服务器计算:
K=A^b\bmod p
数学上可以证明:
1 | 结果完全一样 |
即:
1 | K = g^(ab) mod p |
双方得到了同一个密钥。
ECDH 又是什么
DH 有个问题:
1 | 计算量较大 |
例如:
1 | 2048 bit |
才能保证安全。
后来出现:
椭圆曲线密码学(ECC)
对应的 DH 版本:
ECDH
全称:
1 | Elliptic Curve Diffie-Hellman |
特点:
同等安全性下:
1 | RSA 3072位 |
因此:
1 | 更快 |
ECDHE 是什么
很多人分不清:
1 | ECDH |
ECDH:
固定密钥。
1 | 服务器私钥固定 |
ECDHE:
E = Ephemeral
意思:
1 | 临时的 |
每次连接:
服务器都会重新生成:
1 | 临时私钥 |
例如:
第一次访问:
1 | a1 |
第二次访问:
1 | a2 |
第三次:
1 | a3 |
完全不同。
为什么必须临时
这是 TLS1.3 的核心思想:
前向保密(Forward Secrecy)
假设今天:
1 | 你访问银行 |
产生:
1 | Session Key #1 |
明天:
1 | Session Key #2 |
后天:
1 | Session Key #3 |
攻击者把所有流量录下来:
1 | 2023 |
全部保存。
几年后:
服务器私钥泄露。
如果使用老式 RSA 密钥交换:
1 | 过去所有流量 |
非常危险。
如果使用 ECDHE:
即使拿到服务器长期私钥:
1 | 也推不出当时的临时密钥 |
因此:
1 | 历史通信仍然安全 |
这就是:
1 | Forward Secrecy |
TLS 1.2 和 TLS 1.3
TLS 1.2:
可能出现:
1 | RSA |
多种方式。
TLS 1.3:
已经强制要求:
1 | (E)DHE |
也就是:
1 | ECDHE |
基本成为事实标准。
浏览器访问 HTTPS 时实际发生什么
以访问:
Google 为例。
1 | 1 浏览器发起连接 |
因此:
1 | 证书 |
这是现代 HTTPS/TLS 的标准流程。
从工程角度看,你可以把 TLS 理解成:
1 | RSA/ECDSA |
这也是为什么在 Nginx、Java SSL、Spring Security、OAuth2 等场景里,你会经常看到类似:
1 | TLS_AES_128_GCM_SHA256 |
这些套件里面已经默认包含 ECDHE 作为密钥交换机制,而不是过去那种 RSA 直接交换密钥的方式。