前端用AES加密数据后,后端解密失败是怎么回事?
我在前端用 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>
首先说最常见的问题,前端
encrypted.toString()输出的是 Base64 格式的密文,这个没问题。但后端 PHP 的openssl_decrypt默认也期望 Base64 输入,所以很多人搞混了。给你一套前后端对得上的代码,直接拿去用。
前端代码:
后端 PHP 解密代码:
说几个容易踩的坑。第一,Key 长度要注意,16 字节用 AES-128-CBC,32 字节用 AES-256-CBC,你这个是 16 字节所以用 AES-128-CBC。第二,如果还是报 padding 错误,检查一下传输过程中有没有被 URL 编码或者空格被 trim 掉了,Base64 里面的加号和等号特别容易出问题。第三,有些人后端喜欢用
mcrypt_decrypt,那个扩展早就废弃了,别用,直接上openssl_decrypt。试试这个方法,应该能解出来。