如何在原生JavaScript中实现字符串的AES加解密且规避不合规第三方库
原生JavaScript AES字符串加解密实现方案
方案说明
本方案完全基于浏览器/Node.js内置的原生Web Crypto API实现,无任何第三方依赖,不存在许可证合规问题,完全满足你的使用要求。
采用AES-GCM加密模式,自带密文完整性校验,安全性远高于传统的CBC、ECB模式;密钥通过PBKDF2从输入密码派生,避免弱密码直接作为加密密钥的安全风险。
完整实现代码
// 将字符串转ArrayBuffer function stringToArrayBuffer(str) { return new TextEncoder().encode(str); } // 将ArrayBuffer转Base64字符串 function arrayBufferToBase64(buf) { return btoa(String.fromCharCode(...new Uint8Array(buf))); } // 将Base64字符串转ArrayBuffer function base64ToArrayBuffer(b64) { const binary = atob(b64); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) { bytes[i] = binary.charCodeAt(i); } return bytes.buffer; } // 从密码派生AES密钥 async function getKeyFromPassword(password, salt) { const passwordKey = await crypto.subtle.importKey( "raw", stringToArrayBuffer(password), { name: "PBKDF2" }, false, ["deriveKey"] ); return crypto.subtle.deriveKey( { name: "PBKDF2", salt: salt, iterations: 100000, hash: "SHA-256", }, passwordKey, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"] ); } // AES加密函数 async function aesEncrypt(plainText, password) { // 生成随机盐值和IV const salt = crypto.getRandomValues(new Uint8Array(16)); const iv = crypto.getRandomValues(new Uint8Array(12)); const key = await getKeyFromPassword(password, salt); // 加密 const encrypted = await crypto.subtle.encrypt( { name: "AES-GCM", iv: iv }, key, stringToArrayBuffer(plainText) ); // 拼接盐值、IV、密文,统一转Base64方便存储传输 const resultBuffer = new Uint8Array(salt.length + iv.length + encrypted.byteLength); resultBuffer.set(salt, 0); resultBuffer.set(iv, salt.length); resultBuffer.set(new Uint8Array(encrypted), salt.length + iv.length); return arrayBufferToBase64(resultBuffer.buffer); } // AES解密函数 async function aesDecrypt(encryptedBase64, password) { const encryptedBuffer = base64ToArrayBuffer(encryptedBase64); // 拆分盐值、IV、密文 const salt = encryptedBuffer.slice(0, 16); const iv = encryptedBuffer.slice(16, 16 + 12); const data = encryptedBuffer.slice(16 + 12); const key = await getKeyFromPassword(password, salt); const decrypted = await crypto.subtle.decrypt( { name: "AES-GCM", iv: iv }, key, data ); return new TextDecoder().decode(decrypted); }
使用示例
对应你给出的业务场景,使用方式如下:
// 你的业务参数 const Json = { /* 你的JSON数据 */ }; const pass = "你的加密密码"; const fnm = "encrypted_data.txt"; (async () => { // 替换原有的加密逻辑 var jsn = JSON.stringify(Json); var encrypted = await aesEncrypt(jsn, pass); saveStringToFile(encrypted, fnm); // 解密验证示例 const decryptedStr = await aesDecrypt(encrypted, pass); const decryptedJson = JSON.parse(decryptedStr); })();
注意事项
- 如果你在Node.js环境使用,15以上版本已内置
crypto.webcrypto,仅需把代码中的crypto替换为require('crypto').webcrypto即可正常运行 - 加密输出的Base64字符串已经包含了随机盐、IV和认证标签,无需单独存储其他参数,直接保存即可
- 密钥派生的迭代次数默认设为100000,你可以根据安全需求和性能要求调整,迭代次数越高暴力破解难度越大,加解密耗时也会相应增加
内容的提问来源于stack exchange,提问作者Viktor Chernev
相关产品推荐
相关产品推荐

