openssl_encrypt用aes-256-gcm时返回false主因是漏传$tag引用参数或未使用openssl_raw_data选项;$tag必须声明变量并以引用方式传入,iv长度须严格为12字节,密钥和iv必须用random_bytes()生成,明文需为字符串。

openssl_encrypt用AES-256-GCM时为什么总返回false
绝大多数情况是漏传了$tag引用参数,或者没用OPENSSL_RAW_DATA选项。GCM模式下openssl_encrypt()必须通过引用接收$tag,否则加密看似成功,但解密时会静默失败。
-
$tag必须声明为变量并传引用:openssl_encrypt($data, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag)—— 少了&$tag或写成$tag = null都不行 - 别用
OPENSSL_ZERO_PADDING:GCM不支持该标志,加了会导致返回false -
$iv长度必须严格匹配:openssl_cipher_iv_length('aes-256-gcm')在主流 OpenSSL 版本中返回12,硬写16或用md5()生成会失败 - 明文不能是
null或array:先json_encode()或serialize(),再确保is_string($data)为true
AES-256-GCM的IV和tag怎么拼接存储
IV不保密,tag必须和密文绑定传输,三者缺一不可。推荐把$iv、$tag、$ciphertext按固定顺序拼成二进制串,再统一base64_encode() —— 不要用JSON或URL参数拼接,避免解析歧义和截断。
- 加密后拼接:
$encrypted = base64_encode($iv . $tag . $ciphertext) - 解密前拆分:
$raw = base64_decode($encrypted); $ivLen = openssl_cipher_iv_length('aes-256-gcm'); $tagLen = 16; $iv = substr($raw, 0, $ivLen); $tag = substr($raw, $ivLen, $tagLen); $ciphertext = substr($raw, $ivLen + $tagLen); - 别把
$tag当普通字符串处理:它不是base64编码过的,不能提前base64_decode()再拼
密钥和IV生成必须用random_bytes(),别信openssl_random_pseudo_bytes()
openssl_random_pseudo_bytes()已被标记为废弃(PHP 8.2+),且其$strong参数不可靠;random_bytes()才是现代PHP唯一可信赖的密码学安全随机源。
- 密钥生成:
$key = random_bytes(32)——mb_strlen($key, '8bit')必须等于32,strlen()在这里也安全 - IV生成:
$iv = random_bytes(openssl_cipher_iv_length('aes-256-gcm'))—— 动态获取长度,不硬编码12 - 绝不能从字符串哈希派生密钥:
hash('sha256', 'my-secret')输出64字符十六进制串,转二进制才32字节,但实际是弱熵源,且易被彩虹表攻击
解密时openssl_decrypt报错error:06065064:bad decrypt怎么办
这个错误90%以上是因为$tag不匹配,而不是密钥或IV错了。GCM对认证标签极其敏感,哪怕一个字节差异都会触发该错误。
- 检查
$tag是否完整还原:解密时传入的$tag必须和加密时生成的完全一致,包括长度和二进制内容 - 确认
$iv没被截断或填充:从base64解码后,strlen($iv)必须等于openssl_cipher_iv_length('aes-256-gcm') - 别忽略
OPENSSL_RAW_DATA:加密用OPENSSL_RAW_DATA,解密也必须用,混用OPENSSL_BASE64会导致乱码 - 加一层校验:解密后用
json_validate()或unserialize()反序列化前先判断格式,避免把解密失败当业务数据处理
random_bytes()调用、$tag引用传递——这四个点只要有一个松动,GCM就拒绝工作,而且不给你明确提示。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











