javascriptreactjscryptographylibsodium

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


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.


Solution

  • 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.