最稳方案是 crypto-js:纯 JS、跨端兼容;key 用 Utf8.parse,iv 每次随机生成并 URL 安全 base64 编码;小程序需配置 transpileDependencies 且版本 ≤4.2.0。

uni-app 里 AES 加密用哪个库最稳
直接用 crypto-js,别碰原生 WebCrypto 或小程序自带加密 API。uni-app 多端(H5/微信小程序/APP)编译下,WebCrypto 在微信小程序里不可用,APP 端 Android/iOS 行为也不一致;而 crypto-js 是纯 JS 实现,无依赖、跨平台兼容性好,npm install 后开箱即用。
常见错误:有人试过 @ethersproject/aes 或 node-forge,结果 H5 正常、小程序白屏——因为这些库用了 Buffer、global 或 Node.js 内置模块,uni-app 小程序端 runtime 不支持。
- 安装命令:
npm install crypto-js - 导入方式统一用 ES6:
import CryptoJS from 'crypto-js'(不要require) - 微信小程序需在
vue.config.js或vue.config.ts中配置transpileDependencies: ['crypto-js'],否则可能报 “Unexpected token”
key 和 iv 怎么生成才安全又可复用
AES 是对称加密,key 和 iv 必须和服务端严格一致,且不能硬编码在前端。常见错误是把固定字符串当 key 直接传给 CryptoJS.AES.encrypt,这实际触发的是「password-based」模式(PBKDF2),服务端若用原始 key 解密就会失败。
正确做法是:前端和服务端约定好 key/iv 的字节长度(如 AES-128 → 16 字节),然后用 base64 或 hex 传输原始二进制数据。
-
key推荐 16/24/32 字节(对应 AES-128/192/256),用CryptoJS.enc.Utf8.parse('your-16-byte-key')转成 WordArray -
iv必须每次加密随机生成(不可复用!),用CryptoJS.lib.WordArray.random(16),再通过请求头或参数和密文一起发给后端 - 避免用
Math.random()拼字符串当 iv —— 安全熵不足,且无法跨平台复现
加密后的数据怎么传给后端不被截断或乱码
加密结果是 WordArray,直接 .toString() 默认输出 Base64,但部分后端(如 Java 的 Base64.getDecoder())对换行符敏感;更常见的是 uni-app 请求时,encodeURIComponent 自动处理导致 + 号变空格、/ 被转义,解密失败。
核心原则:加密输出必须做 URL 安全的 base64 编码(去掉 +、/、=),且整个密文字段作为 JSON 字符串值发送,不要塞进 URL 查询参数。
- 加密后转 URL 安全 base64:
ciphertext.toString(CryptoJS.enc.Base64).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') - iv 同样处理,并和密文一起放在请求 body 里,例如:
{ encryptedData: "xxx", iv: "yyy" } - 禁用:
uni.request的header['Content-Type'] = 'application/x-www-form-urlencoded',改用'application/json',避免表单编码污染密文
微信小程序里 AES 解密失败的三个隐藏坑
不是代码写错了,而是环境限制没绕过去。最典型的是:H5 能跑通,小程序真机调试报错 TypeError: Cannot read property 'encrypt' of undefined,或者解密出乱码。
- 确认
crypto-js版本 ≤ 4.2.0 —— 4.3.0+ 引入了exports字段,微信开发者工具 v3.4+ 会优先读它,导致模块解析失败 - 小程序端不能用
CryptoJS.enc.Hex.parse解析十六进制 iv,必须先转成字符串再 parse:CryptoJS.enc.Utf8.parse(ivHexStr)(因为 Hex.parse 对输入格式极其敏感) - 后端返回的密文如果是标准 base64,前端用
CryptoJS.enc.Base64.parse()解析时,必须确保字符串末尾没有空格或换行 ——uni.request响应体默认带 \n,建议先res.data.trim()
加密本身不难,难的是 key/iv 的生命周期管理、多端运行时差异、以及和后端加解密逻辑的字节级对齐。少一个 .trim(),少一次 WordArray.random(),都可能让整条链路静默失败。


















