In short I will list the "problems" you have in your code:
- Its maximum entropy decreased from 128 to 96 because of the
base64
, without any advantage.
- Your chosen cipher (AES-CBC) does not protect against text edits.
- Your "key" seems to be a password, not a key.
- Supporting obsolete versions does not seem to me to be an advantage.
First, I think it’s best to eliminate support for PHP5.6 and PHP 7 for two reasons:
- PHP 5.6 and PHP 7.0 are no longer supported by PHP itself.
- PHP 5.6 (up to PHP 5.6.12) has a vulnerability in
openssl_random_pseudo_bytes
, who wore the RAND_pseudo_bytes
Openssl, which is insecure.
Second, you don’t say the goal you want to accomplish, nor the attacks you intend to mitigate, so without a list of attack vectors it is impossible to "improve it". But one thing you can notice is that your code DOES NOT protect against text edits, you can decipher an altered text without any sign that the text has changed or not. Is that a problem for you? We don’t know.
Third, you’re using the base64_encode
meaningless and is decreasing the maximum entropy of IV
. Note the following lines:
$IV1 = base64_encode(openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC')));
$IV2 = substr($IV1, 0, openssl_cipher_iv_length('AES-256-CBC'));
The AES-256-CBC needs a initialization vector (IV
) 16 bytes. $IV1 will have 24 bytes, however each byte will only have 6 useful bits (after all for every 3 bytes is 4 bytes of Base64). Therefore, its maximum entropy dropped from 128 bits to 96 bits, without any advantage or clear reason for such.
Fourth, you seem to use a password. Password are not keys (if you want to use passwords as keys you will have to use some PBKDF, such as Argon2id). If it is not passwords, create a uniformly random key. I don’t know if this was just an example, however the name of $pass
raised me such suspicion.
Discarding support for such versions, could use the random_bytes
and could use Libsodium (which uses Salsa20 instead of AES, and uses Poly1305 for authentication).
$chave = "\xDE\xAD\xBE\xEF\xFE\xED\xDE\xAD\xBE\xEF\xFE\xED\xDE\xAD\xBE\xEF\xFE\xED\xDE\xAD\xBE\xEF\xFE\xED"
// Sua chave
function encode($data) {
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
return unpack("H*", $nonce)[1] . sodium_crypto_secretbox($data, $nonce, $chave);
}
function decode($data) {
$nonce = pack("H*", substr($data, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES * 2));
return sodium_crypto_secretbox_open($data, $nonce, $chave);
}
If support for PHP 5.6 is really necessary, not much to do (except fix Base64), but PHP 5.6 does not natively support AES-GCM, as far as I know, it would have to do some "gambiarra" using AES-CBC + HMAC.