前端用Diffie-Hellman交换密钥时为什么算不出相同共享密钥?
我在前端实现加密通信时想用Diffie-Hellman算法交换密钥,但双方算出来的共享密钥总不一样,明明参数都共享了,这是哪里出问题了?
我按文档写了个生成密钥对的函数,但测试时发现双方计算的共享密钥完全不同。代码大概是这样写的:
const crypto = require('crypto');
function generateKeyPair() {
const dh = crypto.createDiffieHellman(2048);
const publicKey = dh.getPublicKey();
const privateKey = dh.getPrivateKey();
return { dh, publicKey, privateKey };
}
// 客户端A
const clientA = generateKeyPair();
// 服务端B
const serverB = generateKeyPair();
// A计算共享密钥
const aShared = clientA.dh.computeSecret(serverB.publicKey);
// B计算共享密钥
const bShared = serverB.dh.computeSecret(clientA.publicKey);
console.log(aShared.toString('hex') === bShared.toString('hex')); // 应该为true但实际是false
我检查过参数长度都是2048位,密钥对生成也没报错,但最终得到的共享密钥字符串完全不一致。难道是密钥交换步骤少传了什么参数?或者密钥格式有问题?控制台还报了”invalid key format”的警告…
改成这样:
crypto.createDiffieHellman(2048),但这实际上是各自生成了一对不同的素数和基数。这就好比两个人在不同的星球上跳舞,当然跳不出一致的节奏。解决办法是让双方使用同一个预定义的Diffie-Hellman组,比如标准的
modp组。Node.js提供了现成的generatePrime方法或者可以直接用内置的modp15等标准参数。给你一个改后的代码:
调试看看,这次应该就能算出相同的共享密钥了。记得以后用DH的时候,素数和基数一定要同步好,不然算法再好也白搭。