【问题标题】:Is AES GCM in the latest PHP broken or am I doing something wrong?最新 PHP 中的 AES GCM 是否损坏或我做错了什么?
【发布时间】:2020-01-06 04:18:24
【问题描述】:

我尝试使用 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 encryption cryptography aes-gcm


    【解决方案1】:

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

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

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

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

    最后的想法:使用低级加密时要小心,您可以使用 PHP>7.2 中嵌入的Sodium

    【讨论】:

    • 哦,我现在明白了。它只是以所需的长度切割标签并进行比较。我的假设是,当我在加密时指定标签长度时,标签对于不同的长度会完全不同,但我现在看到 GCM 总是只创建 128 位(块大小)标签。我想在文档中对此有警告不会受到伤害。
    • @honzaik:我同意你的看法。
    • 同意,这就是为什么我建议图书馆为你做这件事
    猜你喜欢
    • 2020-06-08
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 2010-10-23
    相关资源
    最近更新 更多