PHP使用openssl_encrypt加密的字符串无法在MySQL中AES_DECRYPT解密
问题原因及解决方法
核心问题1:密文编码格式不匹配
PHP侧openssl_encrypt默认返回base64编码后的加密字符串,但MySQL的AES_DECRYPT函数要求输入的是原始二进制密文,你直接把base64字符串传入解密函数,肯定无法得到正确结果。
核心问题2:密钥长度不匹配
AES-256算法要求密钥长度为32字节:
- PHP侧
hash("sha256", xxx)默认返回64个字符的十六进制字符串(总长度64字节),openssl_encrypt会自动截断前32字节作为实际密钥使用 - 你之前在MySQL侧直接把SHA2返回的64字节十六进制字符串作为密钥,和PHP实际使用的密钥不一致
核心问题3:加密结果输出格式不匹配
你之前测试MySQL加密结果不对,是因为AES_ENCRYPT返回的是原始二进制数据,直接转字符串或者查看显示为blob,需要用TO_BASE64()转成base64编码才能和PHP输出的加密结果对比。
正确可运行的代码
解密代码
SET block_encryption_mode = 'aes-256-cbc'; -- 取SHA2结果前32字节作为密钥,和PHP侧实际使用的密钥对齐 SET @key_str = LEFT(SHA2('Pn6nK7Gs9r',256), 32); SET @init_vector = '98awg9X7SiI3jxp3'; SET @encrypted = 'Xq1CcrpteSqcybePun+6pQ=='; -- 先对密文做base64解码,再解密转字符串 SELECT CAST(AES_DECRYPT(FROM_BASE64(@encrypted), @key_str, @init_vector) AS CHAR(100)) AS decrypted;
运行后decrypted字段值就是你预期的test。
加密验证代码
SET block_encryption_mode = 'aes-256-cbc'; SET @key_str = LEFT(SHA2('Pn6nK7Gs9r',256), 32); SET @init_vector = '98awg9X7SiI3jxp3'; SET @string = 'test'; -- 加密后转base64,和PHP输出结果一致 SELECT TO_BASE64(AES_ENCRYPT(@string, @key_str, @init_vector)) AS encrypted;
运行后encrypted字段值就是你预期的Xq1CcrpteSqcybePun+6pQ==。
额外优化建议
如果要避免后续密钥处理的歧义,建议PHP侧生成密钥时直接返回原始二进制,两边处理更统一:
// 第三个参数传true,直接返回32字节的原始二进制哈希值 $enc_key = hash("sha256", "Pn6nK7Gs9r", true);
对应MySQL侧密钥处理改为:
-- 把十六进制的SHA2结果转成32字节二进制 SET @key_str = UNHEX(SHA2('Pn6nK7Gs9r',256));
这种方式更符合AES算法的密钥规范,也不会出现截断的隐含逻辑。
内容的提问来源于stack exchange,提问作者Cephou
相关产品推荐
相关产品推荐

