Trying to implement diffie-hellman using libsodium and react but getting a different shared secret key

184 views Asked by At

I am trying to implement diffie hellman using libsodium but I am getting a different shared secret key when doing an exchange.

async function handleSharedSecret() {
 await _sodium.ready;
 const sodium = _sodium;
 const secretKey = sodium.crypto_kx_client_session_keys(
      sodium.crypto_scalarmult_base(
        sodium.from_base64(privateKeyRef.current.value)
      ),
      sodium.from_base64(privateKeyRef.current.value),
      sodium.from_base64(publicKeyRef.current.value)
    );
   
    setSharedSecretKey(sodium.to_base64(secretKey.sharedRx));
}

The output generated is this

Bob's Public Key: _nGMQavOQuMf7FUyUYfaqvfBcj9hAFJPcc-Bo0JHEEw

Alice's Private Key: vrzVDcdX7PyN1BGo00CzJ_vdvWuOnK_sUeHGQbDAZHQ

Shared Secret Key: 8oVOLsEnxq7XLX6ZXuV3wGgjtyGO7bN8SOvFK1BaB0o




Alice's Public Key: SaKUG5MX0m5XP7Tbf8-LjHzhWdxn9Qn6ndRVBP1YeRI

Bob's Private Key: hzFTBbnif8I37ySoDi5eqtEUechU_dBE7n-oFYNENh0

Shared Secret Key: XnwyWbm2kZFddqx67-QAC1K3Sn7trh5Suk15zl4NmcA

The shared secrets keys don't match. Please help me resolve this.

2

There are 2 answers

0
Maverick 2000 On BEST ANSWER

I got it working. Basically you need to define two separate functions, to generate the same shared secret key. If someone has more expertise in this please do explain why.

 async function handleGetEncryptionKey(alicePublicKey, bobPrivateKey) {
    try {
      await _sodium.ready;
      const sodium = _sodium;
      const serverSharedSecret = sodium.crypto_kx_server_session_keys(
        sodium.crypto_scalarmult_base(sodium.from_hex(bobPrivateKey)),
        sodium.from_hex(bobPrivateKey),
        sodium.from_hex(alicePublicKey)
      );
      console.log(
        "Encryption Key: ",
        sodium.to_hex(serverSharedSecret.sharedRx)
      );
      setSharedSecretKey(sodium.to_hex(serverSharedSecret.sharedRx));
    } catch (error) {
      setVariant("danger");
      setSyslog(error.message);
    }
  }
 async function handleGetDecryptionKey(bobPublicKey, alicePrivateKey) {
    try {
      await _sodium.ready;
      const sodium = _sodium;
      const clientSharedSecret = sodium.crypto_kx_client_session_keys(
        sodium.crypto_scalarmult_base(sodium.from_hex(alicePrivateKey)),
        sodium.from_hex(alicePrivateKey),
        sodium.from_hex(bobPublicKey)
      );
      console.log(
        "Decryption Key: ",
        sodium.to_hex(clientSharedSecret.sharedTx)
      );
      setSharedSecretKey(sodium.to_hex(clientSharedSecret.sharedTx));
    } catch (error) {
      setVariant("danger");
      setSyslog(error.message);
    }
  }

This will generate the proper shared secret key for encryption and decryption

For Encryption:
Bob Private Key: c09e3e89a590d449c1dfe6ad82b44438bfe59d146fe4c7e407690c6b84e22077
Alice Public Key: 20f40d0d267f00d67651375ed172a1e7f16e1b085afb09c6c487feaa300e8d31

Shared Secret: bdf9835b9f6c758278c090b4af9539f7843030285cdeafdcfcf6d34c0fbc29b3

For Decryption:
Alice Private Key: 20ff8ef237f2e421b21e33d82fdb0ee8a57e67d572d502be7d4f9916fdcd1e9e
Bob Public Key: a9e7e836a3fd987f93fc332d21a8c8200aa4962ac35e3c8da02135c358df9b19

Shared Secret: bdf9835b9f6c758278c090b4af9539f7843030285cdeafdcfcf6d34c0fbc29b3

As you can see we have the same shared secret key by calling separate functions.

4
Mohsen Robatjazi On

The correct way to do so using libsodium would be this code:

async function diffieHellmanKeyExchange() {
  await sodium.ready;

  const serverKeyPair = sodium.crypto_kx_keypair();
  const clientKeyPair = sodium.crypto_kx_keypair();

  const serverSharedSecret = sodium.crypto_kx_server_session_keys(
    serverKeyPair.publicKey,
    serverKeyPair.privateKey,
    clientKeyPair.publicKey
  );

  const clientSharedSecret = sodium.crypto_kx_client_session_keys(
    clientKeyPair.publicKey,
    clientKeyPair.privateKey,
    serverKeyPair.publicKey
  );

  const serverSharedSecretHex = sodium.to_hex(serverSharedSecret.sharedRx);
  const clientSharedSecretHex = sodium.to_hex(clientSharedSecret.sharedTx);

  console.log('Match:', serverSharedSecretHex === clientSharedSecretHex);
}

diffieHellmanKeyExchange();

Read more at Official Documentation For libsodium.

If you need to , instead of calling sodium.crypto_kx_keypair(), you can use a custom object like following:

const clientKeyPair  = {
    publicKey: sodium.from_hex(publicKey),
    privateKey: sodium.from_hex(privateKey)
};