Diffie-Hellman 密钥交换模拟器 返回
密码学教学模拟器

Diffie-Hellman 密钥交换模拟器 — 公钥交换的数论

共享公开素数 p 与原根 g,让 Alice 与 Bob 由各自的私钥计算公开值并交换,最终得到相同的共享密钥。用小数字直观理解为什么双方能在公开信道上达成一致。

参数设置
素数 p(公开)
原根 g(公开)
Alice 的私钥 a
Bob 的私钥 b

输入非素数时会自动取最接近的素数。这是教学演示,实际部署请使用 p ≥ 2048 比特或 ECDH。

计算结果
Alice 的公开值 A=g^a mod p
Bob 的公开值 B=g^b mod p
Alice 的共享密钥 K=B^a mod p
Bob 的共享密钥 K=A^b mod p
密钥交换流程

左 Alice、中 Public Channel (p, g)、右 Bob。箭头表示公开值在双方之间的传递。

理论与主要公式

Diffie-Hellman 密钥交换允许两方仅借助公开素数 p 与原根 g,在不安全信道上达成共享密钥。

Alice 与 Bob 各自选取私钥 a、b,并计算公开值:

$$A = g^{a} \bmod p, \qquad B = g^{b} \bmod p$$

将对方公开值用自己的私钥求幂,即可得到相同的共享密钥:

$$K_{\text{Alice}} = B^{a} \bmod p = A^{b} \bmod p = K_{\text{Bob}}$$

这是因为指数律 $(g^a)^b = (g^b)^a = g^{ab}$ 在有限域 mod p 下同样成立:

$$K = g^{ab} \bmod p$$

仅知 p、g、A、B 的窃听者要恢复 a 或 b 必须求解离散对数问题,对足够大的 p 在计算上不可行。

Diffie-Hellman 密钥交换模拟器是什么

🙋
「公钥密码学」我听过,但是不见面就能加密通信?如果在被监听的线路上发送密钥,岂不是没意义吗?
🎓
问得好。1976 年的 Diffie-Hellman 密钥交换正是首次解决这个问题的方法。简单说,二人公开约定一个素数 p 和原根 g。Alice 选一个秘密数 a,把 A = g^a mod p 发出去。Bob 同样由 b 算出 B = g^b mod p 发出去。结果二人都能算出 g^(ab) mod p 这同一个值。在上面模拟器里设 p=23, g=5, a=6, b=15,你会得到 A=8, B=19,共享密钥 K=2。
🙋
咦?A 和 B 都是公开发送的吧?窃听到的人不能算出密钥吗?
🎓
这正是密钥交换的精妙之处。窃听者就算知道 p、g、A、B 全部,要从 A 反推出 a,必须求解「离散对数问题」。在大素数 p 下这件事极其困难。模拟器只支持 p ≤ 997 的小素数,现实里 a 一下就被穷举出来。实际部署 p 至少 2048 比特,那时才能说计算量上「事实上不可行」。
🙋
明白了。但 Alice 的 K_A 和 Bob 的 K_B 为什么会得到同一个值呢?
🎓
就是指数律啊。$(g^a)^b = (g^b)^a = g^{ab}$ ——这在普通数学里成立,在 mod p 的幂运算下同样成立。Alice 把 B = g^b 用自己的 a 求幂得到 (g^b)^a = g^(ab),Bob 把 A = g^a 用自己的 b 求幂得到 (g^a)^b = g^(ab),结果一致。模拟器里你换各种 a、b 试试,K_A 和 K_B 永远相等。
🙋
那么只用 Diffie-Hellman 加密通信就万无一失了?
🎓
可惜,纯 DH 对「中间人攻击」毫无抵抗力。攻击者分别冒充 Alice 和 Bob,与对方各做一次密钥交换,二人毫不察觉。所以实际系统会把 DH 与认证机制结合:对公开值签名、配合服务器证书等,确实地认证对方身份。TLS 的 ECDHE 就是典型例子。

常见问题

当 p 为素数时,g 的幂 g^1, g^2, ..., g^(p-1) mod p 在 g 为原根时会取遍 p 以下所有非零值各一次。这样私钥 a 的取值空间最大化,攻击者穷举更困难。如果 p 是合数,或者 g 的阶很小,则共享密钥的可能取值减少,安全性下降。
实际部署中 a、b 是不少于 256 比特的随机整数。教学版模拟器里限制在 1~100 是为了直观,但在这个量级下穷举瞬间就能破解。要点是每次会话都生成新的随机私钥;如果固定使用同一私钥,未来一旦泄露,过往所有通信都会被解密(前向安全性丧失)。
ECDH 把同样的 DH 思想搬到椭圆曲线上的点加法,不再使用整数 mod p 的幂运算。优点是用更小的密钥就能达到同等安全性。传统 DH 需要 2048 比特的地方,ECDH 用约 256 比特就能获得同等甚至更高的安全性。在手机、IoT 等资源受限的环境中,ECDH 已成为事实标准。
不建议直接使用。实际中会把 K 输入「密钥派生函数(KDF,例如 HKDF)」,按用途派生多个密钥(加密用、认证用、初始化向量用等)。这样既能在某一密钥泄露时不波及其他用途,又能消除 K 中的统计偏差,得到适合密码学原语的良好伪随机输出。

实际应用

HTTPS 与 TLS:浏览器与 Web 站点之间的安全连接 TLS 协议中,密钥协商普遍采用 ECDHE(椭圆曲线 Diffie-Hellman 临时密钥)。在用服务器证书认证对方的同时,每个会话使用一次性密钥,使得即便服务器长期私钥未来泄露,过往会话仍无法被解密。这就是「前向安全性」。

VPN(IPsec、WireGuard):企业的远程接入 VPN,以及近年流行的 WireGuard,都在内部使用 Diffie-Hellman 协商每次的隧道密钥。WireGuard 用 ECDH(Curve25519),仅几个往返就建立起轻量、安全的加密通道。

Signal 与 WhatsApp 的端到端加密:消息软件的端到端加密广泛采用 Signal 协议的「Double Ratchet」,几乎对每条消息都进行一次新的 DH 密钥协商。即便某条消息密钥泄露,也不会连带把之前或之后的消息悉数解密。

SSH 与一般加密通信:SSH 会话建立时也使用 DH 密钥协商。客户端和服务器无需事先共享秘密就能为每次会话协商出新的密钥,这是 SSH 成为远程服务器管理标配工具的重要原因之一。

常见误解与注意事项

最常见的误解是认为「只要用 Diffie-Hellman 协商了密钥,加密通信就自动安全」。纯 DH 对中间人攻击(MITM)毫无防御能力——攻击者插在 Alice 与 Bob 之间,分别与双方完成密钥协商即可阅读全部通信。实际系统必须结合「确认对方身份」的认证机制:TLS 用服务器证书,SSH 用已知主机密钥,Signal 用身份密钥指纹,三者都在扮演这个认证角色。

其次常见的是「教学演示里的小素数 p 大概也安全吧」的轻视。像本模拟器中 p ≤ 997 的小素数,攻击者只需依次试 a = 1, 2, 3, ...,找出与公开值 A 一致的 g^a mod p,瞬间就能恢复私钥。实际部署中要把 p 设为至少 2048 比特(十进制 600 位以上);ECDH 则用至少 256 比特的椭圆曲线参数。安全性随 p 的大小指数级增长,妥协于密钥尺寸是致命的。

最后请注意「私钥 a、b 反复使用也没问题」这种误解。如果同一私钥被多个会话复用,那么任意一个会话密钥泄露的瞬间,所有由该长期私钥派生出的会话都会被解密。实际系统采用临时密钥方式(DHE / ECDHE 中的 "E" 即 ephemeral 之意):每个会话生成新的随机 a、b,会话结束后立即销毁,从而保证前向安全性。