3

I would like to achieve an anonymous public-key encryption in a web browser using sodium-plus.js with keys generated in PHP sodium like this:

$keyPair = sodium_crypto_box_keypair();

$privateKey = sodium_crypto_box_secretkey($keyPair);
$publicKey = sodium_crypto_box_publickey($keyPair);

The keys generated with this method work fine in PHP with the sodium_crypto_box_seal and sodium_crypto_box_seal_open methods, but however, I am unable to make it work on the frontend. My approach:

<script type='text/javascript' src='js/sodium-plus.min.js?v=0.4.2'></script>
<script>
async function getPublicKey() {

    return X25519PublicKey.from(
        '<?php echo sodium_bin2hex($publicKey); ?>', // 6a00b1550ccdeff3886a469b9cd4e5dc9aecd30f5deb3dd3e29fd01f8a32103f
        'hex'
    );

}

async function encryptString(clearText, publicKey) {

    if (!window.sodium) window.sodium = await SodiumPlus.auto();

    let cipherText = await sodium.crypto_box_seal(clearText, publicKey);

    return cipherText.toString('hex');

}

(async function () {

    let clearText = "String that contains secret.";
    let publicKey = await getPublicKey();

    console.log(await encryptString(clearText,publicKey));

})();
</script>

This returns TypeError: Argument 2 must be an instance of X25519PublicKey in the console.

Notes:

  1. A public-key that is derived from sodium.crypto_box_keypair() on the frontend works.
  2. Tried with CryptographyKey.from() instead of X25519PublicKey.from() – did not work.
  3. The getPublicKey() function returns an object wit buffer: Uint8Array(32) [ … ], while the public-key derived from sodium.crypto_box_keypair() returns an object with buffer: Uint8Array(32) [ … ], keyType: "x25519", publicKey: true.

Concept is based on:

  1. https://github.com/paragonie/sodium-plus/blob/master/docs/SodiumPlus/sealed-boxes.md
  2. https://dev.to/paragonie/message-encryption-in-javascript-and-php-cg9
  3. https://stackoverflow.com/a/34058638
lesDev
  • 77
  • 1
  • 8

2 Answers2

1

The short answer is: Upgrade to version 0.5.0 or later.

The long answer is: Wait until version 0.6.0 is out, and then upgrade to that instead, since it also loosens some of the type-pedantic restrictions that you're running into.

Scott Arciszewski
  • 33,610
  • 16
  • 89
  • 206
  • This error doesn't completely go away, even the newer versions. The first time I encrypt and submit, everything works fine, but when I return with a new public key and run the process again, it gives the same error. Only when I re-declare `window.sodium` (basically remove the `if()` statement prefixing it, does the error go away, so something in sodium "remembers" the previous public key. It's an easy fix, but thought I'd give you a heads up in case it's a bug not a feature. :-) – dearsina May 24 '20 at 13:07
0

I use https://github.com/jedisct1/libsodium.js/ and it works great, encrypts in javascript and decrypts in PHP

Saud Iqbal
  • 375
  • 1
  • 4
  • 15