php用openssl_decrypt解密需严格对齐cipher、key、iv、padding四要素:cipher名须完全匹配(如aes-128-cbc),key和iv必须为二进制且长度合规(如16或32字节),密文需base64_decode后传入,选项设openssl_raw_data,失败时检查openssl_error_string()。

PHP接口收到加密数据后怎么用openssl_decrypt解密
直接用 openssl_decrypt 是最常见也最稳妥的方式,前提是知道加密时用的算法、密钥、IV 和填充方式。很多前端传来的 AES 加密数据(比如用 CryptoJS 加密的),后端 PHP 必须严格对齐参数,否则返回空或乱码。
常见错误现象:openssl_decrypt 返回 false 或空字符串,不是代码写错了,大概率是参数不匹配。
- 算法名必须完全一致:CryptoJS 默认用
AES-128-CBC,PHP 就得写'AES-128-CBC',不能简写成'AES128'或漏掉-CBC - 密钥和 IV 必须是二进制格式:如果前端传的是 base64 编码的密钥/IV,PHP 里得先
base64_decode;如果密钥是字符串(如"my-secret-key"),要确保长度符合算法要求(AES-128 要 16 字节,不够就补位或哈希截取) - 数据本身通常是 base64 编码的密文,解密前必须
base64_decode,否则直接解会失败
示例(对接 CryptoJS 常见场景):
$cipher = 'AES-128-CBC';
$encrypted_data = base64_decode($_POST['data']); // 前端传的 base64 密文
$key = substr(hash('sha256', 'your-password'), 0, 16); // 生成 16 字节密钥
$iv = substr(hash('sha256', 'your-iv-string'), 0, 16); // 同样生成 16 字节 IV
$decrypted = openssl_decrypt($encrypted_data, $cipher, $key, OPENSSL_RAW_DATA, $iv);
if ($decrypted === false) {
die('解密失败:' . openssl_error_string());
}
echo $decrypted;
为什么用 mcrypt_decrypt 会报错或被拒绝执行
mcrypt_decrypt 在 PHP 7.1+ 已被彻底移除,不是“不推荐”,是根本不存在。很多老教程还在写它,一跑就报 Call to undefined function mcrypt_decrypt()。
如果你维护的旧项目还依赖 mcrypt,别试图降级 PHP,应该立即迁移到 openssl 扩展——它从 PHP 5.3 就内置,兼容性更好,API 更清晰。
- mcrypt 的 ECB 模式默认不填充,openssl 默认使用 PKCS#7 填充,迁移时若原数据没填充分,需加
OPENSSL_ZERO_PADDING标志 - mcrypt 的 IV 长度检查宽松,openssl 更严格:AES-CBC 要求 IV 必须是 16 字节,少一字节都会失败
- 不要用
mcrypt_get_key_size()这类已废弃函数去推导参数,直接查算法文档定死值
接口收到 JSON 加密体后如何安全提取并解密
实际接口中,前端常把整个 JSON 对象加密后 POST 一个字段(如 {"data": "xxx", "ts": 171xxxxx", "sign": "yyy"}),而不是只加密业务字段。这时候不能跳过校验直接解密。
- 先验证
sign(比如 HMAC-SHA256 签名),防止中间人篡改密文 - 检查
ts时间戳是否超时(如 5 分钟),避免重放攻击 -
data字段解密后,仍需json_decode($decrypted, true)并校验结构,防止解密出错导致后续逻辑崩掉 - 解密失败时不要泄露细节,统一返回
400 Bad Request,日志里记openssl_error_string()用于排查
关键点:解密只是中间一步,不是终点。没做签名和时效校验的解密接口,等于把锁换成了透明玻璃门。
base64 解密后出现乱码或 json_decode 失败怎么办
这基本不是编码问题,而是解密环节出了偏差。PHP 的 json_decode 对 UTF-8 非常敏感,而解密后如果残留了不可见填充字节(比如 PKCS#7 补的 \x07\x07…),就会让 json_decode 直接返回 null。
- 确认解密后没有多余字符:用
bin2hex($decrypted)看末尾是不是一串相同字节(如07070707070707),那是 PKCS#7 填充,openssl_decrypt默认已自动去除,不用手动 trim - 但如果你用了
OPENSSL_ZERO_PADDING,就得自己处理填充——此时必须手动截掉末尾 N 个相同字节 - 检查原始密文是否被 URL 安全 base64 编码过(比如把
+换成-,/换成_),PHP 的base64_decode不支持,得先还原再解码
最容易被忽略的一点:前端加密时用了 UTF-8 字符串,但 PHP 接口文件自身编码不是 UTF-8(比如 GBK),会导致 json_decode 识别失败——确认脚本文件保存为 UTF-8 无 BOM 格式。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











