const crypto = require('crypto');
// List of common ECDH curves to compare
const curves = [
'secp256k1', // Bitcoin's curve
'prime256v1', // Also known as secp256r1 or NIST P-256
'secp384r1', // NIST P-384
'secp521r1', // NIST P-521
'brainpoolP256r1',
'brainpoolP384r1',
'brainpoolP512r1',
'ed25519', // Edwards curve (not all versions of Node.js support this for ECDH)
'x25519' // Curve25519 (not all versions of Node.js support this for ECDH)
].filter(curve => crypto.getCurves().includes(curve)); // Filter to only include supported curves
console.log('Comparing ECDH Curves');
console.log('='.repeat(50));
// Function to test a curve
function testCurve(curve) {
try {
// Time key generation
const startGen = process.hrtime();
const ecdh1 = crypto.createECDH(curve);
ecdh1.generateKeys();
const ecdh2 = crypto.createECDH(curve);
ecdh2.generateKeys();
const endGen = process.hrtime(startGen);
// Time key exchange
const startExch = process.hrtime();
const secret1 = ecdh1.computeSecret(ecdh2.getPublicKey());
const secret2 = ecdh2.computeSecret(ecdh1.getPublicKey());
const endExch = process.hrtime(startExch);
// Get key sizes
const privateKeySize = ecdh1.getPrivateKey().length;
const publicKeySize = ecdh1.getPublicKey().length;
// Verify the secrets match
const secretsMatch = secret1.equals(secret2);
return {
curve,
keyGenTime: (endGen[0] * 1000 + endGen[1] / 1e6).toFixed(3) + 'ms',
keyExchTime: (endExch[0] * 1000 + endExch[1] / 1e6).toFixed(3) + 'ms',
privateKeySize: `${privateKeySize} bytes`,
publicKeySize: `${publicKeySize} bytes`,
secretSize: `${secret1.length} bytes`,
secretsMatch
};
} catch (error) {
return {
curve,
error: error.message
};
}
}
// Test all curves
const results = curves.map(testCurve);
// Sort by key exchange speed (fastest first)
results.sort((a, b) => {
if (a.error) return 1;
if (b.error) return -1;
return parseFloat(a.keyExchTime) - parseFloat(b.keyExchTime);
});
// Print results
console.log('Curve Name'.padEnd(20), 'Key Gen Time'.padEnd(15), 'Key Exch Time'.padEnd(15),
'Priv Key'.padEnd(10), 'Pub Key'.padEnd(10), 'Secret'.padEnd(10), 'Status');
console.log('-'.repeat(100));
results.forEach(result => {
if (result.error) {
console.log(`${result.curve.padEnd(20)} ${'N/A'.padEnd(15)} ${'N/A'.padEnd(15)} ${'N/A'.padEnd(10)} ${'N/A'.padEnd(10)} ${'N/A'.padEnd(10)} Error: ${result.error}`);
} else {
console.log(
result.curve.padEnd(20),
result.keyGenTime.padEnd(15),
result.keyExchTime.padEnd(15),
result.privateKeySize.padEnd(10),
result.publicKeySize.padEnd(10),
result.secretSize.padEnd(10),
result.secretsMatch ? '✓' : '✗'
);
}
});
// Additional information
console.log('\nNotes:');
console.log('- Key generation and exchange times are for a single operation and may vary by system load.');
console.log('- Key sizes include ASN.1 encoding overhead where applicable.');
console.log('- Not all curves provide the same security level despite similar key sizes.');
console.log('- Ed25519 and X25519 may not be supported for ECDH in all Node.js versions.');