X25519密钥交换
这个密钥交换是非常的轻量简洁了,现代安全加密套件也都在使用这个(TLS1.3、ssh、Noise、WireGuard)
它的核心就是
shared_secret = X25519(private_key_A, public_key_B)其中内部是
shared = a * B (在 Curve25519 上)- a:32 字节的私钥,经过 clamp 处理
- B:对方的 32 字节公钥(Montgomery x 坐标)
- 运算:Montgomery ladder,保证常数时间,不被侧信道攻击
Clamp 规则(RFC 7748):
k[0] &= 248 清掉最低 3 位(让 k 可被 8 整除)
k[31] &= 127 清掉最高 1 位
k[31] |= 64 设置第二高位目的:确保私钥落在安全子群里,避免小子群攻击
公钥生成 给定私钥 k,公钥就是:
public = X25519(k, basepoint)basepoint 是固定的:9
Curve25519 的 Montgomery x 坐标上的生成元
双方 Alice 和 Bob:
-
Alice:
- 生成 32 字节随机数 → clamp → 得到私钥 a
- pubA = X25519(a, 9)
-
Bob:
- 生成 32 字节随机数 → clamp → 得到私钥 b
- pubB = X25519(b, 9)
-
互换公钥后:
-
Alice 计算:
-
sharedA = X25519(a, pubB)
-
Bob 计算:
-
sharedB = X25519(b, pubA)
-
-
最终:
- sharedA == sharedB 共享密钥一致,后面开始进行通信
代码
这个代码不涉及到任何的底层,我对这个底层的数学曲线函数是完全不理解,所以只能实际写一个使用的代码不能给各位写从0开始的代码
package main
import (
"crypto/rand"
"crypto/ecdh"
"fmt"
)
func main() {
// 使用 Curve25519(X25519)
curve := ecdh.X25519()
// Alice
alicePriv, _ := curve.GenerateKey(rand.Reader)
alicePub := alicePriv.PublicKey()
// Bob
bobPriv, _ := curve.GenerateKey(rand.Reader)
bobPub := bobPriv.PublicKey()
// 密钥交换
sharedA, _ := alicePriv.ECDH(bobPub)
sharedB, _ := bobPriv.ECDH(alicePub)
fmt.Printf("Alice: %x\n", sharedA)
fmt.Printf("Bob: %x\n", sharedB)
fmt.Println("是否一致:", string(sharedA) == string(sharedB))
}