js ecdh实现
ECDH 密钥交换实现
ECDH(Elliptic Curve Diffie-Hellman)是一种基于椭圆曲线的密钥交换算法,用于在不安全的通信信道上安全地协商共享密钥。以下是使用 JavaScript 实现 ECDH 密钥交换的步骤。
生成密钥对
使用 Web Crypto API 生成 ECDH 密钥对。需要指定椭圆曲线名称(如 P-256、P-384 或 P-521)。
async function generateKeyPair() {
const keyPair = await window.crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-256",
},
true,
["deriveKey", "deriveBits"]
);
return keyPair;
}
导出公钥
将生成的公钥导出为可传输的格式(如 JWK 或 ArrayBuffer)。

async function exportPublicKey(publicKey) {
const exported = await window.crypto.subtle.exportKey("jwk", publicKey);
return exported;
}
导入公钥
将接收到的公钥导入为 CryptoKey 对象,以便用于密钥派生。
async function importPublicKey(jwkKey) {
const publicKey = await window.crypto.subtle.importKey(
"jwk",
jwkKey,
{
name: "ECDH",
namedCurve: "P-256",
},
true,
[]
);
return publicKey;
}
派生共享密钥
使用本地私钥和对方的公钥派生共享密钥。

async function deriveSharedSecret(privateKey, publicKey) {
const sharedSecret = await window.crypto.subtle.deriveBits(
{
name: "ECDH",
public: publicKey,
},
privateKey,
256
);
return sharedSecret;
}
完整示例
以下是一个完整的 ECDH 密钥交换示例:
async function runECDHExchange() {
// Alice 生成密钥对
const aliceKeyPair = await generateKeyPair();
const alicePublicKey = await exportPublicKey(aliceKeyPair.publicKey);
// Bob 生成密钥对
const bobKeyPair = await generateKeyPair();
const bobPublicKey = await exportPublicKey(bobKeyPair.publicKey);
// Alice 使用 Bob 的公钥派生共享密钥
const bobPublicKeyImported = await importPublicKey(bobPublicKey);
const aliceSharedSecret = await deriveSharedSecret(aliceKeyPair.privateKey, bobPublicKeyImported);
// Bob 使用 Alice 的公钥派生共享密钥
const alicePublicKeyImported = await importPublicKey(alicePublicKey);
const bobSharedSecret = await deriveSharedSecret(bobKeyPair.privateKey, alicePublicKeyImported);
// 验证共享密钥是否相同
const aliceArray = new Uint8Array(aliceSharedSecret);
const bobArray = new Uint8Array(bobSharedSecret);
console.log("Shared secrets match:", arraysEqual(aliceArray, bobArray));
}
function arraysEqual(a, b) {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
runECDHExchange();
注意事项
- 确保使用安全的椭圆曲线(如 P-256、P-384 或 P-521)。
- 在实际应用中,公钥需要通过安全的方式传输(如 TLS)。
- 派生出的共享密钥可以用于对称加密(如 AES-GCM)或其他用途。
兼容性
Web Crypto API 在现代浏览器中广泛支持,但在 Node.js 中需要使用 crypto 模块或其他库(如 node-forge)。以下是在 Node.js 中的实现示例:
const crypto = require('crypto');
function generateKeyPair() {
const alice = crypto.createECDH('secp256k1');
alice.generateKeys();
const bob = crypto.createECDH('secp256k1');
bob.generateKeys();
const aliceSecret = alice.computeSecret(bob.getPublicKey());
const bobSecret = bob.computeSecret(alice.getPublicKey());
console.log('Shared secrets match:', aliceSecret.equals(bobSecret));
}
generateKeyPair();






