前端用AES加密数据后,后端解密失败是怎么回事?

小艺霖 阅读 18

我在前端用 CryptoJS 做 AES 加密,把用户输入的敏感信息加密后再发给后端。但后端(PHP)一直解密失败,说 padding 或 key 不对。我确认 key 和 iv 是前后端一致的,也用了 CBC 模式,不知道哪里出问题了。

下面是我前端加密的 HTML + JS 代码片段:

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script>
  const key = CryptoJS.enc.Utf8.parse('1234567890123456');
  const iv = CryptoJS.enc.Utf8.parse('1234567890123456');
  const encrypted = CryptoJS.AES.encrypt('hello', key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
  console.log(encrypted.toString());
</script>
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
博硕(打工版)
这个问题太经典了,我之前也被坑过好几次。前端 CryptoJS 和后端 PHP 联调 AES 加密,十有八九是这几个坑。

首先说最常见的问题,前端 encrypted.toString() 输出的是 Base64 格式的密文,这个没问题。但后端 PHP 的 openssl_decrypt 默认也期望 Base64 输入,所以很多人搞混了。

给你一套前后端对得上的代码,直接拿去用。

前端代码:
const key = CryptoJS.enc.Utf8.parse('1234567890123456');
const iv = CryptoJS.enc.Utf8.parse('1234567890123456');
const encrypted = CryptoJS.AES.encrypt('hello', key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
// 输出 Base64 字符串传给后端
console.log(encrypted.toString());


后端 PHP 解密代码:
$key = '1234567890123456';
$iv = '1234567890123456';
// 前端传来的 Base64 字符串
$encrypted = '前端传来的加密字符串';

// 方法一:PHP 默认期望 Base64 输入,选项传 0 就行
$decrypted = openssl_decrypt($encrypted, 'AES-128-CBC', $key, 0, $iv);

// 方法二:手动 base64_decode 后用 OPENSSL_RAW_DATA
// $decrypted = openssl_decrypt(base64_decode($encrypted), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);

var_dump($decrypted);


说几个容易踩的坑。第一,Key 长度要注意,16 字节用 AES-128-CBC,32 字节用 AES-256-CBC,你这个是 16 字节所以用 AES-128-CBC。第二,如果还是报 padding 错误,检查一下传输过程中有没有被 URL 编码或者空格被 trim 掉了,Base64 里面的加号和等号特别容易出问题。第三,有些人后端喜欢用 mcrypt_decrypt,那个扩展早就废弃了,别用,直接上 openssl_decrypt

试试这个方法,应该能解出来。
点赞 2
2026-02-28 15:05