openssl_decrypt异常:自定义加密函数加密后解密返回空值
问题分析与解决方案
这个问题的核心在于**openssl_encrypt函数的$tag参数是引用传递**,而你的自定义mc_encrypt函数没有正确处理这个特性,导致解密时使用了错误的认证标签。
具体原因
在GCM加密模式下,openssl_encrypt的第6个参数$tag是用来输出加密过程中生成的认证标签的,它要求以引用的方式传入(PHP中用&标记)。当你直接调用openssl_encrypt时,外部的$tag变量会被自动更新为新生成的标签;但你的mc_encrypt函数把$tag当作普通值参数传入,函数内部对$tag的修改无法同步到外部,导致解密时使用的还是你最初解码的旧标签,标签验证失败,所以openssl_decrypt返回空值。
修改后的代码
只需要把mc_encrypt函数中的$tag参数改为引用传递即可:
$key = base64_decode("PRIV KEY"); $cipher = "aes-256-gcm"; $iv = base64_decode("BASE64 encoded IV "); $tag = ""; // 初始化空标签,加密时会被自动填充 function mc_encrypt($plaintext, $cipher, $key, $iv, &$tag){ // $tag是引用传递,加密后会同步更新外部的$tag变量 $encrypted_text = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_RAW_DATA, $iv, $tag); return base64_encode($encrypted_text); // 统一处理base64编码,避免默认行为混淆 } function mc_decrypt($encrypted_text, $cipher, $key, $iv, $tag){ $encrypted_text = base64_decode($encrypted_text); $decrypted_text = openssl_decrypt($encrypted_text, $cipher, $key, OPENSSL_RAW_DATA, $iv, $tag); return $decrypted_text; } $test = "Teststring"; // 使用自定义函数加密,此时$tag会被更新为本次加密生成的新标签 $encrypted = mc_encrypt($test, $cipher, $key, $iv, $tag); $decrypted = mc_decrypt($encrypted, $cipher, $key, $iv, $tag); if($decrypted == $test) { echo "Success!"; }
额外说明
- 我添加了
OPENSSL_RAW_DATA选项,让加密返回原始二进制数据后再手动base64编码,这样能避免默认自动编码带来的逻辑混淆,也让加密解密的编码逻辑更统一。 - 从安全角度来说,GCM模式要求每次加密使用唯一的IV(即使密钥相同),测试时可以用随机IV生成代码:
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
内容的提问来源于stack exchange,提问作者Fastbuilder575
相关产品推荐
相关产品推荐

