最新的 PHP 中的 AES GCM 是否损坏或我做错了什么?

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

我尝试使用 openssl_encrypt/decrypt 在 PHP 中实施加密。我尝试在 GCM 模式下使用 128 位 AES,但后来我注意到即使是 GCM 标记的一个字节也足以使解密成功。

我用谷歌搜索了一下,发现 this crypto.stackexchange question 遇到了同样的问题。我再次问的问题是,这已经超过 1 年了,而且这似乎仍然没有在最新版本中修复。我于 2019 年 5 月 28 日使用 OpenSSL 1.1.1c 在 PHP 版本 7.3.9-1 上进行了检查。

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;

代码是否正确并且 PHP 在这件事上仍然不安全(这有点疯狂,因为文档中没有关于它的警告)?还是代码有误?

谢谢

您的代码还可以,PHP 是安全的

这里的问题是您如何使用 AES-GCM。标签长度为 a security parameter,这意味着您可以选择任何尺寸。建议的最小大小为 96 位,并且您应该检查大小

在您的代码中,您不检查标签大小,openssl_decrypt() 执行您的要求:验证 1 字节标签。

PHP 会知道这是否坏了,请参阅 test line 31

最后的想法:使用低级密码时要小心,你可以使用嵌入了 PHP>7.2

Sodium