You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MySQL中存储AES密钥?存储后解密返回空值如何解决?

问题原因

你遇到的问题核心是原始二进制数据和文本存储类型不兼容,具体原因如下:

  • openssl_random_pseudo_bytes() 生成的AES密钥、IV都是原始二进制数据,包含大量不可打印字符、不符合MySQL字段字符集(如utf8)的字节
  • 你使用VARCHAR(255)文本类型存储二进制数据时,MySQL会自动对不符合字符集的字节做截断、转义、替换为乱码的操作,导致存储的密钥/IV和原始生成的内容不一致,解密时密钥不匹配,自然返回空结果。
解决方案

推荐两种可行方案,优先选择第二种,兼容性更高,不会出现字符集相关的异常:

方案1:修改字段类型为二进制类型

直接用二进制类型存储原始密钥/IV,完全避开字符集转换:

  1. 修改encryptiontable表的字段类型:
    • EncryptionKey改为BINARY(32)(刚好对应256位密钥的32字节长度)
    • iv改为BINARY(16)(刚好对应AES-CBC模式的16字节IV长度)
      也可以根据需要选择VARBINARY、TINYBLOB等二进制类型,无需修改业务代码即可生效。

方案2:转码为可打印字符串存储(推荐)

将二进制的密钥、IV转成Base64编码的可打印字符串后存储,不需要修改字段类型,原有VARCHAR(255)完全够用:

存数据时修改代码

在插入加密表之前对密钥和IV做Base64编码:

// 原有生成密钥、IV的代码不变
$encryption_key = openssl_random_pseudo_bytes(32);
$iv = openssl_random_pseudo_bytes($iv_size);

// 新增Base64编码逻辑
$base64_key = base64_encode($encryption_key);
$base64_iv = base64_encode($iv);

// 绑定时传入编码后的值
mysqli_stmt_bind_param($stmt2,"siss", $usertype,$userID,$base64_key,$base64_iv);

取数据解密时修改代码

取出数据后先做Base64解码再传入解密函数:

// 原有查询加密表的代码不变
$data = mysqli_fetch_assoc($Encryptresult);
$cipher = "aes-256-cbc";

// 新增Base64解码逻辑
$decoded_key = base64_decode($data['EncryptionKey']);
$decoded_iv = base64_decode($data['iv']);

// 用解码后的原始二进制密钥、IV解密
$NRIC = openssl_decrypt($row["NRIC"], $cipher, $decoded_key, 0, $decoded_iv);
额外建议
  • 不要用@符号屏蔽MySQL查询错误,调试阶段开启错误提示可以更快定位问题
  • openssl_encrypt第四个参数为0时默认返回Base64编码的密文,你现有的密文存储逻辑不需要修改,可正常使用。

内容的提问来源于stack exchange,提问作者yukang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 14:45:11