共享公开素数 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 对中间人攻击(MITM)毫无防御能力——攻击者插在 Alice 与 Bob 之间,分别与双方完成密钥协商即可阅读全部通信。实际系统必须结合「确认对方身份」的认证机制:TLS 用服务器证书,SSH 用已知主机密钥,Signal 用身份密钥指纹,三者都在扮演这个认证角色。
其次常见的是「教学演示里的小素数 p 大概也安全吧」的轻视。像本模拟器中 p ≤ 997 的小素数,攻击者只需依次试 a = 1, 2, 3, ...,找出与公开值 A 一致的 g^a mod p,瞬间就能恢复私钥。实际部署中要把 p 设为至少 2048 比特(十进制 600 位以上);ECDH 则用至少 256 比特的椭圆曲线参数。安全性随 p 的大小指数级增长,妥协于密钥尺寸是致命的。