Diffie-Hellman and Elliptic Curve Diffie-Hellman protocols for secure key establishment between parties without prior shared secrets.
Standard Diffie-Hellman key exchange using discrete logarithms over finite fields.
/**
* Create a Diffie-Hellman instance with custom prime
* @param {number|string|Buffer} prime - Prime number as number, string, or Buffer
* @param {string} [primeEncoding] - Encoding of prime if string ('hex', 'base64', etc.)
* @returns {DiffieHellman} DiffieHellman instance
*/
function createDiffieHellman(prime, primeEncoding) { }
/**
* Create a Diffie-Hellman instance from predefined group
* @param {string} name - Standard group name (e.g., 'modp1', 'modp2', 'modp5')
* @returns {DiffieHellmanGroup} DiffieHellmanGroup instance
*/
function createDiffieHellmanGroup(name) { }
/**
* Get a predefined Diffie-Hellman group
* @param {string} groupName - Standard group name
* @returns {DiffieHellmanGroup} DiffieHellmanGroup instance
*/
function getDiffieHellman(groupName) { }
/**
* DiffieHellman object for key exchange operations
* @class DiffieHellman
*/
/**
* Generate public and private key pair
* @param {string} [encoding] - Output encoding for public key
* @returns {Buffer|string} Public key as Buffer or encoded string
*/
DiffieHellman.prototype.generateKeys = function(encoding) { };
/**
* Compute shared secret with other party's public key
* @param {string|Buffer} otherPublicKey - Other party's public key
* @param {string} [inputEncoding] - Encoding of input key if string
* @param {string} [outputEncoding] - Encoding for shared secret output
* @returns {Buffer|string} Shared secret as Buffer or encoded string
*/
DiffieHellman.prototype.computeSecret = function(otherPublicKey, inputEncoding, outputEncoding) { };
/**
* Get the public key
* @param {string} [encoding] - Output encoding
* @returns {Buffer|string} Public key as Buffer or encoded string
*/
DiffieHellman.prototype.getPublicKey = function(encoding) { };
/**
* Get the private key
* @param {string} [encoding] - Output encoding
* @returns {Buffer|string} Private key as Buffer or encoded string
*/
DiffieHellman.prototype.getPrivateKey = function(encoding) { };
/**
* Set the public key
* @param {string|Buffer} publicKey - Public key to set
* @param {string} [encoding] - Encoding of input key if string
*/
DiffieHellman.prototype.setPublicKey = function(publicKey, encoding) { };
/**
* Set the private key
* @param {string|Buffer} privateKey - Private key to set
* @param {string} [encoding] - Encoding of input key if string
*/
DiffieHellman.prototype.setPrivateKey = function(privateKey, encoding) { };
/**
* Get the prime number
* @param {string} [encoding] - Output encoding
* @returns {Buffer|string} Prime as Buffer or encoded string
*/
DiffieHellman.prototype.getPrime = function(encoding) { };
/**
* Get the generator
* @param {string} [encoding] - Output encoding
* @returns {Buffer|string} Generator as Buffer or encoded string
*/
DiffieHellman.prototype.getGenerator = function(encoding) { };
/**
* Verify the prime number
* @returns {number} Verification result flags
*/
DiffieHellman.prototype.verifyError = function() { };
/**
* DiffieHellmanGroup object (inherits all DiffieHellman methods)
* @class DiffieHellmanGroup
* @extends DiffieHellman
*/
function DiffieHellmanGroup() { }
DiffieHellmanGroup.prototype = Object.create(DiffieHellman.prototype);Elliptic curve variant of Diffie-Hellman for more efficient key exchange.
/**
* Create an ECDH instance for the specified curve
* @param {string} curveName - Elliptic curve name (e.g., 'secp256k1', 'prime256v1')
* @returns {ECDH} ECDH instance
*/
function createECDH(curveName) { }
/**
* ECDH object for elliptic curve key exchange operations
* @class ECDH
*/
/**
* Generate public and private key pair
* @param {string} [encoding] - Output encoding for public key
* @param {string} [format] - Point format ('compressed', 'uncompressed', 'hybrid')
* @returns {Buffer|string} Public key as Buffer or encoded string
*/
ECDH.prototype.generateKeys = function(encoding, format) { };
/**
* Compute shared secret with other party's public key
* @param {string|Buffer} otherPublicKey - Other party's public key
* @param {string} [inputEncoding] - Encoding of input key if string
* @param {string} [outputEncoding] - Encoding for shared secret output
* @returns {Buffer|string} Shared secret as Buffer or encoded string
*/
ECDH.prototype.computeSecret = function(otherPublicKey, inputEncoding, outputEncoding) { };
/**
* Get the public key
* @param {string} [encoding] - Output encoding
* @param {string} [format] - Point format ('compressed', 'uncompressed', 'hybrid')
* @returns {Buffer|string} Public key as Buffer or encoded string
*/
ECDH.prototype.getPublicKey = function(encoding, format) { };
/**
* Get the private key
* @param {string} [encoding] - Output encoding
* @returns {Buffer|string} Private key as Buffer or encoded string
*/
ECDH.prototype.getPrivateKey = function(encoding) { };
/**
* Set the private key
* @param {string|Buffer} privateKey - Private key to set
* @param {string} [encoding] - Encoding of input key if string
*/
ECDH.prototype.setPrivateKey = function(privateKey, encoding) { };
/**
* Set the public key
* @param {string|Buffer} publicKey - Public key to set
* @param {string} [encoding] - Encoding of input key if string
*/
ECDH.prototype.setPublicKey = function(publicKey, encoding) { };Direct access to key exchange classes.
/**
* DiffieHellman class constructor
* @constructor
*/
function DiffieHellman() { }
/**
* DiffieHellmanGroup class constructor
* @constructor
*/
function DiffieHellmanGroup() { }Establish shared secret between two parties using standard DH groups.
const crypto = require('crypto-browserify');
// Both parties use the same predefined group
const alice = crypto.createDiffieHellmanGroup('modp14');
const bob = crypto.createDiffieHellmanGroup('modp14');
// Each party generates their key pair
const alicePublicKey = alice.generateKeys('hex');
const bobPublicKey = bob.generateKeys('hex');
console.log('Alice public key:', alicePublicKey);
console.log('Bob public key:', bobPublicKey);
// Each party computes the shared secret using the other's public key
const aliceSharedSecret = alice.computeSecret(bobPublicKey, 'hex', 'hex');
const bobSharedSecret = bob.computeSecret(alicePublicKey, 'hex', 'hex');
console.log('Alice shared secret:', aliceSharedSecret);
console.log('Bob shared secret:', bobSharedSecret);
console.log('Secrets match:', aliceSharedSecret === bobSharedSecret);Create DH instance with custom prime and generator.
const crypto = require('crypto-browserify');
// Generate a prime (in practice, use well-known safe primes)
const prime = Buffer.from('ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff', 'hex');
const generator = 2;
// Create DH instance with custom parameters
const alice = crypto.createDiffieHellman(prime, generator);
const bob = crypto.createDiffieHellman(prime, generator);
// Generate keys and compute shared secret
const alicePublicKey = alice.generateKeys();
const bobPublicKey = bob.generateKeys();
const sharedSecret = alice.computeSecret(bobPublicKey);
console.log('Shared secret:', sharedSecret.toString('hex'));More efficient key exchange using elliptic curves.
const crypto = require('crypto-browserify');
// Create ECDH instances using the same curve
const alice = crypto.createECDH('secp256k1');
const bob = crypto.createECDH('secp256k1');
// Generate key pairs
const alicePublicKey = alice.generateKeys('hex', 'compressed');
const bobPublicKey = bob.generateKeys('hex', 'compressed');
console.log('Alice ECDH public key:', alicePublicKey);
console.log('Bob ECDH public key:', bobPublicKey);
// Compute shared secrets
const aliceSharedSecret = alice.computeSecret(bobPublicKey, 'hex', 'hex');
const bobSharedSecret = bob.computeSecret(alicePublicKey, 'hex', 'hex');
console.log('ECDH shared secret match:', aliceSharedSecret === bobSharedSecret);
console.log('ECDH shared secret:', aliceSharedSecret);Complete key exchange protocol with key derivation.
const crypto = require('crypto-browserify');
class KeyExchangeProtocol {
constructor(groupName = 'modp14') {
this.dh = crypto.createDiffieHellmanGroup(groupName);
this.publicKey = this.dh.generateKeys();
}
getPublicKey(encoding = 'base64') {
return this.dh.getPublicKey(encoding);
}
computeSharedSecret(otherPublicKey, encoding = 'base64') {
const sharedSecret = this.dh.computeSecret(otherPublicKey, encoding);
// Derive symmetric keys from shared secret
const symmetricKey = crypto.pbkdf2Sync(sharedSecret, 'key-derivation-salt', 1000, 32, 'sha256');
const macKey = crypto.pbkdf2Sync(sharedSecret, 'mac-derivation-salt', 1000, 32, 'sha256');
return {
sharedSecret: sharedSecret.toString('hex'),
symmetricKey: symmetricKey.toString('hex'),
macKey: macKey.toString('hex')
};
}
}
// Simulate key exchange between two parties
const alice = new KeyExchangeProtocol();
const bob = new KeyExchangeProtocol();
console.log('=== Key Exchange Protocol ===');
// Exchange public keys
const alicePublicKey = alice.getPublicKey();
const bobPublicKey = bob.getPublicKey();
console.log('Alice sends public key:', alicePublicKey);
console.log('Bob sends public key:', bobPublicKey);
// Compute derived keys
const aliceKeys = alice.computeSharedSecret(bobPublicKey);
const bobKeys = bob.computeSharedSecret(alicePublicKey);
console.log('Alice derived keys:', aliceKeys);
console.log('Bob derived keys:', bobKeys);
console.log('Keys match:', JSON.stringify(aliceKeys) === JSON.stringify(bobKeys));Key exchange with authentication to prevent man-in-the-middle attacks.
const crypto = require('crypto-browserify');
class AuthenticatedKeyExchange {
constructor(privateKey, publicKey, groupName = 'modp14') {
this.privateKey = privateKey; // RSA private key for signing
this.publicKey = publicKey; // RSA public key for verification
this.dh = crypto.createDiffieHellmanGroup(groupName);
this.dhPublicKey = this.dh.generateKeys();
}
createSignedPublicKey() {
const publicKeyHex = this.dh.getPublicKey('hex');
// Sign the DH public key
const sign = crypto.createSign('RSA-SHA256');
sign.update(publicKeyHex);
const signature = sign.sign(this.privateKey, 'base64');
return {
dhPublicKey: publicKeyHex,
signature: signature,
timestamp: Date.now()
};
}
verifyAndComputeSecret(signedPublicKey, otherRsaPublicKey) {
// Verify the signature
const verify = crypto.createVerify('RSA-SHA256');
verify.update(signedPublicKey.dhPublicKey);
const isValid = verify.verify(otherRsaPublicKey, signedPublicKey.signature, 'base64');
if (!isValid) {
throw new Error('Invalid signature - possible man-in-the-middle attack');
}
// Check timestamp to prevent replay attacks
const now = Date.now();
if (now - signedPublicKey.timestamp > 300000) { // 5 minutes
throw new Error('Signature too old - possible replay attack');
}
// Compute shared secret
const sharedSecret = this.dh.computeSecret(signedPublicKey.dhPublicKey, 'hex');
return {
sharedSecret: sharedSecret.toString('hex'),
verified: true,
timestamp: signedPublicKey.timestamp
};
}
}
// Example with RSA keys for authentication
const aliceRsaKeys = {
private: `-----BEGIN PRIVATE KEY-----\n...Alice's RSA private key...\n-----END PRIVATE KEY-----`,
public: `-----BEGIN PUBLIC KEY-----\n...Alice's RSA public key...\n-----END PUBLIC KEY-----`
};
const bobRsaKeys = {
private: `-----BEGIN PRIVATE KEY-----\n...Bob's RSA private key...\n-----END PRIVATE KEY-----`,
public: `-----BEGIN PUBLIC KEY-----\n...Bob's RSA public key...\n-----END PUBLIC KEY-----`
};
// Note: In practice, you would use real RSA keys
// const alice = new AuthenticatedKeyExchange(aliceRsaKeys.private, aliceRsaKeys.public);
// const bob = new AuthenticatedKeyExchange(bobRsaKeys.private, bobRsaKeys.public);ECDH with proper key derivation for different purposes.
const crypto = require('crypto-browserify');
function performECDHKeyExchange(curveName = 'prime256v1') {
// Create ECDH instances for both parties
const alice = crypto.createECDH(curveName);
const bob = crypto.createECDH(curveName);
// Generate key pairs
const aliceKeys = {
private: alice.generateKeys(),
public: alice.getPublicKey('hex', 'compressed')
};
const bobKeys = {
private: bob.generateKeys(),
public: bob.getPublicKey('hex', 'compressed')
};
// Compute shared secret
const sharedSecret = alice.computeSecret(bob.getPublicKey());
// Derive multiple keys for different purposes
const keys = {
encryptionKey: crypto.pbkdf2Sync(sharedSecret, 'encryption', 10000, 32, 'sha256'),
macKey: crypto.pbkdf2Sync(sharedSecret, 'authentication', 10000, 32, 'sha256'),
kdfKey: crypto.pbkdf2Sync(sharedSecret, 'key-derivation', 10000, 32, 'sha256')
};
return {
alicePublic: aliceKeys.public,
bobPublic: bobKeys.public,
sharedSecret: sharedSecret.toString('hex'),
derivedKeys: {
encryption: keys.encryptionKey.toString('hex'),
mac: keys.macKey.toString('hex'),
kdf: keys.kdfKey.toString('hex')
}
};
}
// Usage
const result = performECDHKeyExchange('secp256k1');
console.log('ECDH Key Exchange Result:', result);Standard predefined groups available:
'modp1' - 768-bit prime (RFC 2409) - Deprecated'modp2' - 1024-bit prime (RFC 2409) - Deprecated'modp5' - 1536-bit prime (RFC 3526)'modp14' - 2048-bit prime (RFC 3526) - Recommended'modp15' - 3072-bit prime (RFC 3526)'modp16' - 4096-bit prime (RFC 3526)Common curves supported:
'prime256v1' - NIST P-256 (recommended)'secp256k1' - Bitcoin curve'secp384r1' - NIST P-384'secp521r1' - NIST P-521Key exchange functions may throw errors in the following scenarios:
const crypto = require('crypto-browserify');
try {
const ecdh = crypto.createECDH('invalid-curve');
} catch (err) {
console.error('Unsupported curve:', err.message);
}
try {
const alice = crypto.createECDH('prime256v1');
alice.generateKeys();
// Invalid public key format
const secret = alice.computeSecret('invalid-key', 'hex');
} catch (err) {
console.error('Invalid public key:', err.message);
}
// Safe key exchange with error handling
function safeKeyExchange(curveName, otherPublicKey) {
try {
const ecdh = crypto.createECDH(curveName);
ecdh.generateKeys();
const secret = ecdh.computeSecret(otherPublicKey, 'hex');
return { success: true, secret: secret.toString('hex') };
} catch (err) {
return { success: false, error: err.message };
}
}