We're trying to implement an authenticated symmetric encryption in PHP, which works most of the times, but occasionally fails, and we do not really understand why. The code is:
// Encryption of $secret_code, e.g. integer = 152
$secret_code = 152;
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
// This is just an example, keys are generated in a more secure way, returning a base64
// (Compatible with sodium_crypto_secretbox according to https://www.php.net/manual/de/function.sodium-crypto-secretbox.php)
$key = sodium_base642bin(
'Jdjkfhuehrfkjshdfkjhskjfoshdfishf',
SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING
);
$cipher = sodium_crypto_secretbox(
random_bytes(8) . $secret_code
$nonce,
$key
);
sodium_memzero($key);
$ciphertext_base64 = sodium_bin2base64(
$nonce . $cipher,
SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING
);
sodium_memzero($nonce);
sodium_memzero($cipher);
// Decryption then sometimes yields inconsistent values for $secret_code, e.g. 154
$ciphertext = sodium_base642bin(
$ciphertext_base64,
SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING
);
$nonce = mb_substr(
$ciphertext,
0,
SODIUM_CRYPTO_SECRETBOX_NONCEBYTES,
'8bit'
);
$cipher = mb_substr(
$ciphertext,
SODIUM_CRYPTO_SECRETBOX_NONCEBYTES,
null,
'8bit'
);
$secret_code_string = sodium_crypto_secretbox_open(
$cipher,
$nonce,
$key
);
sodium_memzero($key);
sodium_memzero($nonce);
sodium_memzero($cipher);
$secret_code = (int) mb_substr(
$secret_code_string,
8,
null,
'8bit'
);
We suspect that the issue lies somewhere in the splitting of the string on an 8bit
base and base64 string encoding; we're assuming some data is getting truncated occasionally, resulting in the decryption not to fail, but instead yielding the wrong $secret_code
. Any idea?