javascriptphpencryptionsodium

How to get private key (in the right format) with sodium-plus js (secretbox) from html page for decrypting a message


I can do that : Encrypt on frontend (sodium-plus.js) with public-key from backend (PHP sodium)

But I want to do the contrary (encrypt with php, decrypt with javascript), and I have an issue.

I can get my private key from my html page (generated with php) as a hex string ( sodium_bin2hex(sodium_crypto_secretbox_keygen()) ), but I can't use it with sodium plus.

I know this code to get public key :

let key = X25519PublicKey.from('...', "hex");

but in my case that doesn't work and I have an error passing this variable in

await sodium.crypto_secretbox_open(text, nonce, key);

I've tried just with the hex string convert to bin ( await sodium.sodium_hex2bin(key) ) but it doesn't work too.

Here is my code :

define(function (require) {
    const { SodiumPlus } = require("sodium-plus");
});

let sodium;

(async function () {
    if (!sodium) sodium = await SodiumPlus.auto();
    let text = "...";//my text + nonce (at the end) in hex

    let nonce = text.substr(-48);
    text = text.substr(0, text.length - 48);
    let key = X25519PublicKey.from($("#key").text(), "hex");//get my private key in hex, on my html page

    text = await sodium.sodium_hex2bin(text);
    nonce = await sodium.sodium_hex2bin(nonce);

    let output = await sodium.crypto_secretbox_open(text, nonce, key);    

    console.log(output.toString());

})();

thank you


Solution

  • Here is my solution with crypto_box and secret and public twice :

    define(function (require) {
        const { SodiumPlus } = require("sodium-plus");
    });
    
    let sodium;
    
    (async function () {
        if (!sodium) sodium = await SodiumPlus.auto();
        let text = ""; //string in hex to be decrypted (see below for my php code server side)
    
        let nonce = text.substring(text.length -48); //nonce at the end of the  string
        nonce = await sodium.sodium_hex2bin(nonce); //nonce hex to bin
    
        text = text.substring(0, text.length - 48); //text without nonce
        text = await sodium.sodium_hex2bin(text); //text hex to bin
    
        let publicKey = $("#key").text(); //to get my key in hex from my html page (key = secret key + public key), see below my php code $decryption_key
    
        let secretKey = publicKey.substring(0, 64);//to get the public key in hex
        secretKey = X25519SecretKey.from(secretKey, "hex"); //public key hex to array bin
    
        publicKey = publicKey.substring(publicKey.length -64); //same for public key
        publicKey = X25519PublicKey.from(publicKey, "hex");
    
        let output = await sodium.crypto_box_open(text, nonce, secretKey, publicKey);
        output = output.toString(); // bin to string
    
        console.log(output);
    
    })();
    

    Here is my php code to encrypt, for example :

    $text = '...'; //text to encrypt
    $key = sodium_hex2bin( '...' ); //key in hex (got from an other code, see below $encryption_key)
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    $text_encrypt = sodium_crypto_box($text, $nonce, $key);
    $text_encrypt = sodium_bin2hex($text_encrypt.$nonce);
    return $text_encrypt;
    

    My php code for encryption key in php, and decryption key on my html page (then got by javascript)

    $keypair1 = sodium_crypto_box_keypair();
    $keypair1_secret = sodium_crypto_box_secretkey($keypair1);
    $keypair1_public = sodium_crypto_box_publickey($keypair1);
    $keypair2 = sodium_crypto_box_keypair();
    $keypair2_secret = sodium_crypto_box_secretkey($keypair2);
    $keypair2_public = sodium_crypto_box_publickey($keypair2);
    
    $encryption_key = sodium_crypto_box_keypair_from_secretkey_and_publickey($keypair1_secret, $keypair2_public);
    $encryption_key = sodium_bin2hex( $encryption_key ); //for my php encrypt code
    
    $decryption_key = sodium_crypto_box_keypair_from_secretkey_and_publickey($keypair2_secret, $keypair1_public);
    $decryption_key = sodium_bin2hex( $decryption_key ); //for my html page, then got by javascript