如何用window.crypto生成AES-CBC密钥并实现跨环境加解密
解决AES-CBC密钥导出与跨环境解密问题
1. 导出原始密钥字节(适配在线工具与跨环境解密)
你之前导出的JWK是JSON结构的密钥表示,并非在线工具所需的原始32字节(256位)密钥数据。正确做法是用'raw'格式导出密钥,再转换为Base64字符串:
const key = await crypto.subtle.generateKey( { name: "AES-CBC", length: 256 }, true, ["encrypt", "decrypt"] ); // 导出原始密钥字节(ArrayBuffer) const keyBuffer = await crypto.subtle.exportKey('raw', key); // 转换为Uint8Array const keyUint8 = new Uint8Array(keyBuffer); // 转换为Base64字符串(即在线工具要求的32字节密钥的Base64形式) const keyBase64 = btoa(String.fromCharCode(...keyUint8));
2. 完整加密流程(保存解密所需全部参数)
AES-CBC加密需要随机IV(初始化向量),解密时必须使用相同的IV,所以加密时要生成并保存IV:
// 生成随机IV(AES-CBC要求IV长度为16字节) const iv = crypto.getRandomValues(new Uint8Array(16)); // 待加密消息转为Uint8Array const message = new TextEncoder().encode('需要加密的内容'); // 执行加密 const encryptedBuffer = await crypto.subtle.encrypt( { name: "AES-CBC", iv: iv }, key, message ); // 转换密文为Base64 const encryptedBase64 = btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer))); // 转换IV为Base64 const ivBase64 = btoa(String.fromCharCode(...iv)); // 保存keyBase64、ivBase64、encryptedBase64,后续解密需用到这三个值
3. 跨环境解密示例(无需window.crypto)
拿到上述三个Base64字符串后,任何支持标准AES-CBC的库都能解密。比如用JavaScript的crypto-js库:
const CryptoJS = require('crypto-js'); // 解码Base64为字节数组 const keyBytes = CryptoJS.enc.Base64.parse(keyBase64); const ivBytes = CryptoJS.enc.Base64.parse(ivBase64); const encryptedBytes = CryptoJS.enc.Base64.parse(encryptedBase64); // 解密 const decrypted = CryptoJS.AES.decrypt( { ciphertext: encryptedBytes }, keyBytes, { iv: ivBytes, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ); // 转为明文 const plaintext = decrypted.toString(CryptoJS.enc.Utf8);
如果用Python,可使用pycryptodome库:
from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import base64 # 解码Base64 key = base64.b64decode(keyBase64) iv = base64.b64decode(ivBase64) encrypted_data = base64.b64decode(encryptedBase64) # 解密 cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = unpad(cipher.decrypt(encrypted_data), AES.block_size).decode('utf-8')
内容的提问来源于stack exchange,提问作者Andy Brown
相关产品推荐
相关产品推荐

