如何使用CryptoJS解密window.subtle.crypto的AES-GCM加密数据
适配解决方法
Web Crypto API和CryptoJS的AES-GCM实现参数存在格式差异,按以下步骤调整即可完成解密:
核心适配点
- 密钥处理:Web Crypto导出的JWK字段
k是Base64URL编码的原始密钥,需要先解码为CryptoJS支持的WordArray格式,CryptoJS不识别Web Crypto生成的CryptoKey对象 - 密文拆分:Web Crypto加密返回的ArrayBuffer是「密文 + 16字节GCM认证标签」的拼接结果,CryptoJS解密时需要将密文和标签拆分后单独传入
- 格式统一:IV、密文、标签都需要从
Uint8Array/ArrayBuffer转换为WordArray类型 - 算法配置:解密时显式指定GCM模式,传入拆分后的认证标签
完整可运行代码
const text = "This is an encrypted message"; // ArrayBuffer转WordArray工具方法 const buf2WordArray = (buf) => { const uint8 = new Uint8Array(buf); return CryptoJS.lib.WordArray.create(uint8, uint8.length); } const generateKey = async () => { const key = await window.crypto.subtle.generateKey({ name: "AES-GCM", length: 128 }, true, ["encrypt", "decrypt"]); const key_exported = await window.crypto.subtle.exportKey("jwk", key); return key_exported.k; } const printCurrent = async () => { let kkey = await generateKey(); // 先把JWK的base64url格式密钥转成CryptoJS能用的WordArray const cryptoJSKey = CryptoJS.enc.Base64.parse(kkey.replace(/-/g, '+').replace(/_/g, '/')); const iv = new Uint8Array(12); // 测试用固定IV,生产环境需随机生成 const cryptoJSIv = buf2WordArray(iv); const importedKey = await window.crypto.subtle.importKey( "jwk", { k: kkey, alg: "A128GCM", ext: true, key_ops: ["encrypt", "decrypt"], kty: "oct", }, { name: "AES-GCM", length: 128 }, false, ["encrypt", "decrypt"] ); const encryptedBuf = await window.crypto.subtle.encrypt( { name: "AES-GCM", iv: iv }, importedKey, new TextEncoder().encode(JSON.stringify(text)) ); // 拆分密文和GCM标签:最后16字节是标签,前面是密文 const encryptedUint8 = new Uint8Array(encryptedBuf); const ciphertext = buf2WordArray(encryptedUint8.slice(0, -16)); const authTag = buf2WordArray(encryptedUint8.slice(-16)); // 调用CryptoJS解密 const decrypted = CryptoJS.AES.decrypt( { ciphertext: ciphertext }, cryptoJSKey, { iv: cryptoJSIv, mode: CryptoJS.mode.GCM, padding: CryptoJS.pad.NoPadding, authTag: authTag } ); console.log("cryptojs解密结果:", decrypted.toString(CryptoJS.enc.Utf8)); } printCurrent();
注意事项
测试用固定全0IV仅适用于调试,生产环境必须使用随机生成的12字节IV,且IV需要和密文一起存储传递才能正常解密。
内容的提问来源于stack exchange,提问作者junaiddarajat
相关产品推荐
相关产品推荐

