<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta charset="utf-8" /> <title>AES 加密解密</title> <script src="https://ss.netnr.com/crypto-js@4.2.0/crypto-js.js"></script> </head> <body> </body> </html>
/** * AES 256 GCM 加密 * @param {*} plaintext 纯文本 * @param {*} password 密钥 * @returns */ async function AESEncrypt(plaintext, password) { const pwUtf8 = new TextEncoder().encode(password); const pwHash = await window.crypto.subtle.digest('SHA-256', pwUtf8); const iv = window.crypto.getRandomValues(new Uint8Array(12)); const ivStr = Array.from(iv).map(b => String.fromCharCode(b)).join(''); const alg = { name: 'AES-GCM', iv: iv }; const key = await window.crypto.subtle.importKey('raw', pwHash, alg, false, ['encrypt']); const ptUint8 = new TextEncoder().encode(plaintext); const ctBuffer = await window.crypto.subtle.encrypt(alg, key, ptUint8); const ctArray = Array.from(new Uint8Array(ctBuffer)); const ctStr = ctArray.map(byte => String.fromCharCode(byte)).join(''); return window.btoa(ivStr + ctStr); } /** * AES 256 GCM 解密 * @param {*} ciphertext 密文 * @param {*} password 密钥 * @returns */ async function AESDecrypt(ciphertext, password) { const pwUtf8 = new TextEncoder().encode(password); const pwHash = await window.crypto.subtle.digest('SHA-256', pwUtf8); const ivStr = window.atob(ciphertext).slice(0, 12); const iv = new Uint8Array(Array.from(ivStr).map(ch => ch.charCodeAt(0))); const alg = { name: 'AES-GCM', iv: iv }; const key = await window.crypto.subtle.importKey('raw', pwHash, alg, false, ['decrypt']); const ctStr = window.atob(ciphertext).slice(12); const ctUint8 = new Uint8Array(Array.from(ctStr).map(ch => ch.charCodeAt(0))); const plainBuffer = await window.crypto.subtle.decrypt(alg, key, ctUint8); return new TextDecoder().decode(plainBuffer); } var plaintext = 'Hello,世界,123!'; var password = "key"; console.debug(`plaintext: ${plaintext} \t password: ${password}`) async function Test1() { var v1 = await AESEncrypt(plaintext, password); console.debug(`Local AES-256-GCM Encrypt: ${v1}`) var v2 = await AESDecrypt(v1, password); console.debug(`Local AES-256-GCM Decrypt: ${v2}`) } Test1(); //ref https://gist.github.com/chrisveness/43bcda93af9f646d083fad678071b90a /** * ref: crypto-js * aes-256-cbc Encrypt */ function aesEncrypt(data, key, iv) { key = (key || "").padEnd(32, ' '); iv = (iv || "").padEnd(16, ' '); var result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(key), { iv: CryptoJS.enc.Utf8.parse(iv), padding: CryptoJS.pad.Pkcs7, mode: CryptoJS.mode.CBC }).toString(); return result; } /** * ref: crypto-js * aes-256-cbc Decrypt */ function aesDecrypt(data, key, iv) { key = (key || "").padEnd(32, ' '); iv = (iv || "").padEnd(16, ' '); var result = CryptoJS.AES.decrypt(data, CryptoJS.enc.Utf8.parse(key), { iv: CryptoJS.enc.Utf8.parse(iv), padding: CryptoJS.pad.Pkcs7, mode: CryptoJS.mode.CBC }).toString(CryptoJS.enc.Utf8); return result; } console.debug(`CryptoJS AES-256-CBC Encrypt: ${aesEncrypt(plaintext, password)}`); console.debug(`CryptoJS AES-256-CBC Decrypt: ${aesDecrypt("UsorChZSHOmkd0SQDL+Tp+n//MKpKmzClya9YsKPZII=", password)}`);