Monday, 1 December 2025

Encrypt and decrypt password using PHP sodium

Encrypt password

<?php
/**
 * encrypt.php
 */
$masterKey = "canyouguess";
$passwordToEncrypt = "top-secret";

//ecncypt password
$code = encrypt($masterKey, $passwordToEncrypt);
echo "code: ", $code, "\n";

/**
 * @param $masterKey
 * @param $password
 * @return string
 * @throws SodiumException
 */
function encrypt($masterKey, $password)
{
    // Derive a subkey of the correct length for secretbox
    $key = sodium_crypto_generichash($masterKey, '', SODIUM_CRYPTO_SECRETBOX_KEYBYTES
    );

    // Generate a random nonce
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

    // Encrypt
    $ciphertext = sodium_crypto_secretbox($password, $nonce, $key);

    // Prepend nonce for later decryption, and base64-encode the lot
    return base64_encode($nonce . $ciphertext);
}

In the directory of encrypt.php, run:

docker run -it --rm -v "$PWD":/usr/src -w /usr/src php:8.2-cli php encrypt.php

Output:

code: qKUilnBOnSPIOmKnwIoJAdOaC+9lhud/0eiTekLPokmuImFiRpuHvKG6AoUs7eT7fBY=

Decrypt code to get password

If do not have master key, there is no way to decrypt the code

<?php
/**
 * decrypt.php
 */

$masterKey = "canyouguess";
$code = "qKUilnBOnSPIOmKnwIoJAdOaC+9lhud/0eiTekLPokmuImFiRpuHvKG6AoUs7eT7fBY=";

//decrypt password using master key
$password = decrypt($masterKey, $code);
echo "password: ", $password, "\n";

/**
 * @param $masterKey
 * @param $code
 * @return string
 * @throws SodiumException
 */
function decrypt($masterKey, $code)
{
    $raw = base64_decode($code, true);
    if ($raw === false) {
        throw new RuntimeException('Invalid base64');
    }

    // same derived subkey
    $key = sodium_crypto_generichash($masterKey, '', SODIUM_CRYPTO_SECRETBOX_KEYBYTES
    );

    $nonceLen = SODIUM_CRYPTO_SECRETBOX_NONCEBYTES;
    if (strlen($raw) < $nonceLen) {
        throw new RuntimeException('Ciphertext too short');
    }

    // extract nonce and ciphertext
    $nonce = mb_substr($raw, 0, $nonceLen, '8bit');
    $ciphertext = mb_substr($raw, $nonceLen, null, '8bit');

    // decrypt & verify
    $plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
    if ($plaintext === false) {
        throw new RuntimeException('Decryption failed or message forged');
    }

    return $plaintext;
}

In the same directory of decrypt.php, run:

docker run -it --rm -v "$PWD":/usr/src -w /usr/src php:8.2-cli php decrypt.php

Output:

password: top-secret

No comments:

Post a Comment