When encrypting, you would ideally use a randomly generated key, as that's considerably harder to guess.
For example, sodium_crypto_aead_chacha20poly1305_ietf_keygen()
But if you need to use a password to encrypt/decrypt, you can use sodium_crypto_pwhash():
<?php
function secrets_encrypt($password, $secret) {
$config = [
'size' => SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES,
'salt' => random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES),
'limit_ops' => SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE,
'limit_mem' => SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE,
'alg' => SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13,
'nonce' => random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES),
];
$key = sodium_crypto_pwhash(
$config['size'],
$password,
$config['salt'],
$config['limit_ops'],
$config['limit_mem'],
$config['alg'],
);
$encrypted = sodium_crypto_aead_chacha20poly1305_ietf_encrypt(
$secret,
$config['nonce'], $config['nonce'],
$key
);
return [
'config' => array_map('base64_encode', $config),
'encrypted' => base64_encode($encrypted),
];
}
$password = 'YoxPR4QLeZ';
$secret = 'This-is-my-secret';
$data = secrets_encrypt($password, $secret);
?>
To decrypt with that password, using the same limits:
<?php
function secrets_decrypt($password, $data) {
$config = array_map('base64_decode', $data['config']);
$encrypted = base64_decode($data['encrypted']);
$key = sodium_crypto_pwhash(
$config['size'],
$password,
$config['salt'],
$config['limit_ops'],
$config['limit_mem'],
$config['alg'],
);
return sodium_crypto_aead_chacha20poly1305_ietf_decrypt(
$encrypted,
$config['nonce'], $config['nonce'],
$key
);
}
$secret = secrets_decrypt($password, $data);
?>