/**
* 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}`)
console.debug(`password: ${password}`)
AESEncrypt(plaintext, password).then(ciphertext => {
console.debug(`AES Encrypt: ${ciphertext}`)
AESDecrypt(ciphertext, password).then(plaintext => {
console.debug(`AES Decrypt: ${plaintext}`)
})
})
//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(`crypto-js aes-256-cbc 123: ${aesEncrypt("123")}`);
console.debug(`crypto-js aes-256-cbc: ${aesDecrypt("ObQj0pVbF5lUu8lKGIhMqw==")}`);