不要自己实现 jsencrypt,应改用 node-forge;因其兼容 uni-app 多端环境,且需预处理 PEM 公钥(去空格)、指定 RSA-OAEP 与 SHA256 参数,避免解密失败。

uni-app 中 RSA 加密前端要不要自己实现 jsencrypt?
不要。直接用 jsencrypt 会因缺少浏览器原生 crypto.subtle 支持,在微信小程序、App(尤其是 iOS WKWebview)环境报错 Cannot read property 'subtle' of undefined。uni-app 的运行时环境不等同于完整浏览器,很多 Web Crypto API 不可用。
实操建议:
- 服务端生成一对 RSA 密钥,只把 公钥(PEM 格式,
-----BEGIN PUBLIC KEY-----...)传给前端,用于加密;私钥严格保留在服务端解密 - 前端用轻量、兼容性好的库,如
node-forge(比jsencrypt更适配 uni-app 多端) - 安装:
npm install node-forge,然后在页面或 utils 中按需引入(避免全局污染) - 注意:不要尝试在 uni-app 中用
forge.pki.publicKeyFromPem()直接解析带换行的多行 PEM 字符串——必须先用.replace(/\s/g, '')去空格,否则解析失败且无提示
怎么用 node-forge 对登录密码做 RSA 加密(含完整可粘贴代码)
典型场景:用户输入密码后,用服务端下发的 RSA 公钥加密再提交,防止明文传输。
import forge from 'node-forge'
// 假设从接口拿到的公钥字符串(已去除换行和空格)
const PUBLIC_KEY_PEM = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu...' // 实际使用请动态获取
function encryptWithRSA(plaintext) {
try {
const publicKey = forge.pki.publicKeyFromPem(PUBLIC_KEY_PEM)
const encrypted = publicKey.encrypt(plaintext, 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1Md: forge.md.sha256.create()
})
return forge.util.encode64(encrypted) // 转 base64 便于传输
} catch (e) {
console.error('RSA 加密失败:', e.message)
return null
}
}
// 使用示例
const rawPassword = 'user123'
const encryptedPassword = encryptWithRSA(rawPassword)
console.log(encryptedPassword) // 发送到后端的密文
关键点:
-
RSA-OAEP比RSAES-PKCS1-V1_5更安全,uni-app +node-forge支持它 - 必须指定
md和mgf1Md,否则默认用 SHA1(已被部分服务端拒绝) - 加密前确保
plaintext是字符串,不能是 ArrayBuffer 或 Uint8Array;若需加密二进制数据,先转成 UTF-8 字符串或 Base64
AES 加密更适合什么场景?为什么别用前端 AES 做“全程加密”
前端用 AES(如 crypto-js)适合加密**本地敏感缓存**(如 token、用户偏好),但绝不适合替代 HTTPS 做“传输层加密”。原因很实在:
- 密钥必须硬编码或从服务端动态拉取——前者等于裸奔,后者又回到“怎么安全传密钥”的老问题(最终还是靠 HTTPS + RSA)
- uni-app 的
crypto-js在 H5 正常,但在小程序中可能因require机制或模块路径问题报Cannot find module 'crypto',需改用npm install crypto-js --no-save并手动 require - 真正需要端到端 AES 的场景(如离线文件加密),密钥应由用户口令派生(PBKDF2),而非服务端下发——这和登录态加密是两套逻辑
所以,95% 的 uni-app 项目,只需用 RSA 加密关键字段(密码、手机号),其余字段走 HTTPS 即可。加太多层加密,反而增加调试成本和兼容性风险。
后端解密失败的三个高频原因(前端同学要盯住)
即使前端加密看着成功,后端也可能解不出。常见卡点:
- 前端用了
RSA-OAEP,但后端用的是PKCS#1 v1.5解密 —— 算法模式必须严格一致 - 前端 base64 编码后,后端没做
base64_decode就直接解密,报“invalid ciphertext length” - 公钥格式混淆:前端用的是
-----BEGIN PUBLIC KEY-----(RFC 5280),但后端 expecting-----BEGIN RSA PUBLIC KEY-----(PKCS#1)——两者结构不同,不可混用;uni-app 必须和服务端约定统一用哪种 PEM
最稳妥的做法:前后端联调时,前端打印出加密后的 base64 字符串,后端用相同字符串+相同密钥手动跑一遍解密脚本,排除环境干扰。RSA 的坑不在代码多,而在细节对不齐。


















