
cryptojs aes加密后返回base64字符串,但解密后直接调用`.tostring()`会默认输出十六进制编码(如"6869"),需显式指定`cryptojs.enc.utf8`才能正确还原原始字符串。
在使用 CryptoJS 进行 AES 加密/解密时,一个常见误区是忽略了 加密输出 与 解密输出 的编码处理方式。你观察到 encrypt("hi", "12345") 返回类似 U2FsdGVkX1++p462vXg3LggRE5kzRtX3VbKkcMBWuHY= 的 Base64 字符串,这是正确的;但当你对返回值直接调用 decrypt(...).toString() 时,CryptoJS 默认将其转为十六进制字符串("6869" 即 "h" 和 "i" 的 ASCII 十六进制表示),而非原始 UTF-8 文本。
根本原因在于:
- CryptoJS.AES.encrypt() 返回的是一个 CipherParams 对象(非纯字符串),其 .toString() 方法默认使用 CryptoJS.enc.Hex 编码;
- CryptoJS.AES.decrypt() 返回的是 WordArray 对象,必须通过 .toString(CryptoJS.enc.Utf8) 显式解码为可读字符串。
✅ 正确用法如下:
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
<script>
function encrypt(data, key) {
return CryptoJS.AES.encrypt(data, key).toString(); // ✅ 转为 Base64 字符串
}
function decrypt(encryptedBase64, key) {
const decrypted = CryptoJS.AES.decrypt(encryptedBase64, key);
return decrypted.toString(CryptoJS.enc.Utf8); // ✅ 强制 UTF-8 解码
}
// 使用示例
const original = "hi";
const secretKey = "12345";
const encrypted = encrypt(original, secretKey);
const decrypted = decrypt(encrypted, secretKey);
console.log("原文:", original); // "hi"
console.log("密文:", encrypted); // "U2FsdGVkX1+..."
console.log("解密:", decrypted); // "hi"
</script>⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 密钥安全性:"12345" 是弱口令,实际项目中应使用强随机密钥(如 CryptoJS.lib.WordArray.random(256/8))或派生密钥(PBKDF2);
- 版本兼容性:示例使用 CryptoJS v3.1.2,新版(v4+)API 有差异(如需显式传入 { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
- 跨平台一致性:若需与后端(如 Node.js crypto 模块)互通,务必统一:密钥派生方式、IV(初始化向量)、填充模式(默认 PKCS7)、编码格式(Base64);
- 避免明文密钥硬编码:前端密钥易被逆向,敏感场景建议仅用于临时混淆,勿替代服务端加密。
总结:CryptoJS 的 .toString() 行为取决于上下文对象类型和编码参数——加密结果调用 .toString() 得 Base64;解密结果必须显式传入 CryptoJS.enc.Utf8 才能获得预期明文。掌握这一细节,即可稳定实现前后端兼容的 AES 字符串加解密。










