4

I am trying to create a shared secret key between Curve25519 (or X25519) asymmetric key pairs using key exchange algorithms just like Diffie Hellman key exchange. Diffie Hellman key exchange can be be done in node.js using crypto module in the following code:

const crypto = require('crypto');

// Generate Alice's keys...
const alice = crypto.createDiffieHellman(2048);
const aliceKey = alice.generateKeys(); // Returns public key

// Generate Bob's keys...
const bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys(); // Returns public key

// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);

// Should be equal
console.log(aliceSecret === bobSecret)

X25519 asymmetric keys can be generated using the following code:

const crypto = require('crypto');
const { publicKey, privateKey } = crypto.generateKeyPairSync('x25519', {
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem'
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem',
  }
});

The keys are generated without any issue but I don't know how to generate a shared secret key. I tried converting X25519 keys to Diffie Hellman keys using the folowing code:

...
const dhKey= crypto.createDiffieHellman(2048);
// privateKey => Generated in the above code
dhKey.setPrivateKey(privateKey)
// publicKey => Generated in the above code
dhKey.setPublicKey(publicKey)
...

When using the above code when two dhKey are generated and key exchange is performed, it is giving the following error:

Error: Supplied key is too large

Is there any way the shared secret can be generated? Thanks in advance.

Darshan Jain
  • 239
  • 5
  • 14
  • It already is a diffie-hellman key, you should not be attempting to convert it. Just use the diffie-hellman methods on it. – President James K. Polk May 19 '20 at 23:40
  • While creating normal diffie hellman key from crypto module curve25519 key is not created and i want to use curve25519 key which is only created by generateKeyPairSync() and there is no method supported with this type of key generation to compute shared secret. – Darshan Jain May 20 '20 at 03:54
  • My apologies, unfortunately it was not as simple as I thought. – President James K. Polk May 20 '20 at 13:30

1 Answers1

5

The documentation for this sub API is unfortunately a little thin. I cobbled together an example but without better documentation I'm not sure it's useful.

const crypto = require('crypto');

const aliceKeyPair = crypto.generateKeyPairSync('x25519');

const alicePubExport = aliceKeyPair.publicKey.export(
    {type: 'spki', format: 'pem'}
    );

const bobKeyPair = crypto.generateKeyPairSync('x25519');

const bobPubExport = bobKeyPair.publicKey.export(
    {type: 'spki', format: 'pem'}
    );

const bobKeyAgree = crypto.diffieHellman({
    publicKey : crypto.createPublicKey(alicePubExport),
    privateKey: bobKeyPair.privateKey
});

const aliceKeyAgree = crypto.diffieHellman({
    publicKey : crypto.createPublicKey(bobPubExport),
    privateKey: aliceKeyPair.privateKey
});

console.log(bobKeyAgree.toString('hex'));
console.log(aliceKeyAgree.toString('hex'));

This is missing authentication and therefore is not secure without adding that piece.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
  • I tried the code it worked but there is a slight issue. When I added cipher and passphrase to [**privateKeyEncoding**](https://nodejs.org/api/crypto.html#crypto_crypto_generatekeypairsync_type_options) while generating the keys, I am getting errors like "Assertion `!errors_.empty()' failed." – Darshan Jain May 20 '20 at 17:11