honzaik
honzaik

Reputation: 273

Is AES GCM in the latest PHP broken or am I doing something wrong?

I tried implementing encryption in PHP using openssl_encrypt/decrypt. I tried using 128bit AES in GCM mode but then I noticed that even a one byte of the GCM tag is enough for decryption to be successful.

I googled a bit and found this crypto.stackexchange question that encounters the same problem. The issue I am asking again is that this is over a 1 year old and this still doesnt seem to be fixed on the latest versions. I checked this on PHP Version 7.3.9-1 with OpenSSL 1.1.1c 28 May 2019.

Here is my code.

$key = 'is_gcm_really_broken_on_php'; //27 bytes ... only need 16 but openssl doesnt use rest automatically. thats ok
$iv = openssl_random_pseudo_bytes(16);
$tag = null;
$toEncrypt = 'hello world';
$encrypted = openssl_encrypt($toEncrypt, 'aes-128-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
echo 'tag is ' . strlen($tag) . ' bytes<br>';
$encodedMsg = base64_encode($iv.$tag.$encrypted);
var_dump($encodedMsg);

//.... decrypting
echo '<br><br>decrypting<br>';

$decodedMsg = base64_decode($encodedMsg);
$msgIv = substr($decodedMsg, 0, 16);
$msgTag = substr($decodedMsg, 16, 1);
echo 'using tag thats ' . strlen($msgTag) . ' bytes<br>';
$msgToDecrypt = substr($decodedMsg, 32);
$decrypted = openssl_decrypt($msgToDecrypt, 'aes-128-gcm', $key, OPENSSL_RAW_DATA, $msgIv, $msgTag);
echo 'decryption is ok.. no error<br>decrypted message is ' . $decrypted;

Is the code OK and PHP is still insecure in this matter (which is kinda crazy cause there is no warning about it in the documentation)? Or is the code wrong?

Thanks

Upvotes: 1

Views: 587

Answers (1)

Lou_is
Lou_is

Reputation: 279

Your code is kinda OK and PHP is secure

The problem here is how you use AES-GCM. The tag length is a security parameter, meaning you can choose any size. Minimal recommanded size is 96bits, and you should check the size.

In your code, you do not check the tag size, openssl_decrypt() does what you ask : validates a 1-byte tag.

PHP would know if this broke, see test line 31

Final thought : be careful when using low-level cryptography, you could use Sodium which is embedded with PHP>7.2

Upvotes: 3

Related Questions