deriveKey 方法的完整示例,演示如何使用 HMAC 作为密钥派生函数(KDF)来从一个给定的秘密(如密码)派生出一个新的 AES 加密密钥。
//创建一个函数来生成随机盐
function getRandomSalt(length)
{
let array=new Uint8Array(length);
window.crypto.getRandomValues(array);
return array;
}
//生成随机数字
function randomFloat(){
const fooArray=new Uint32Array(1);
const maxUint32=0xFFFFFFFF;
return crypto.getRandomValues(fooArray)[0];
}
//生成随机密码,导入密钥当中
function getKeyMaterial()
{
//const password=window.prompt("请输入你的密码");//就是为加密时用密码
//这里不用输入密码,我们采用随机生成的数字,这样可以增加破解难度,提升安全性
const password=randomFloat();
const enc=new TextEncoder();
return window.crypto.subtle.importKey(
"raw",
enc.encode(password),
"PBKDF2",
false,
["deriveBits","deriveKey"]
);
}
//创建一个函数来派生密钥
async function deriveAeskey(salt,info,keyLength)
{
//生成已有密钥
//不能直接用new Textcoder().encoder(password)这样来生成密码,必须用这个函数的importKey导入密钥才行
const passwordBuffer=await getKeyMaterial();
const derivedKey=await crypto.subtle.deriveKey(
{
name:'PBKDF2',
salt:salt,
iterations:10000,
hash:'SHA-256'
},
passwordBuffer,
{
name:'AES-GCM',
length:keyLength
},
true,
["encrypt","decrypt"]
);
return derivedKey;
}
//使用派生的密钥进行加密
async function encryptData(derivedKey,dataToEncrypt){
const encoder=new TextEncoder();
const dataBuffer=encoder.encode(dataToEncrypt);
const iv=window.crypto.getRandomValues(new Uint8Array(12));
const encryption=await crypto.subtle.encrypt(
{
name:'AES-GCM',
iv:iv
},
derivedKey,
dataBuffer
);
return {
ciphertext:encryption,
iv:Array.from(iv)
}
}
//使用派生的密钥进行解密
async function decryptData(derivedKey,ciphertext,iv)
{
const decrypted=await crypto.subtle.decrypt(
{
name:'AES-GCM',
iv:new Uint8Array(iv)
},
derivedKey,
ciphertext
);
const decoder=new TextDecoder();
return decoder.decode(decrypted);
}
//最后把他们综合到一起,进行加密和解密,以及做加密后内容的演式
(async function(){
const salt=getRandomSalt(16);
const info=new Uint8Array();
const keyLength=256;
try{//派生的密钥
const derivedKey=await deriveAeskey(salt,info,keyLength);
//需要加密的数据
const dataToEncrypt="this is data";
const {ciphertext,iv}=await encryptData(derivedKey,dataToEncrypt);
//这里是演式你加密后的数据样式
console.log(String.fromCharCode(...new Uint8Array(ciphertext)));
//解密数据
const decryptedData=await decryptData(derivedKey,ciphertext,iv);
console.log('解密数据:',decryptedData);
}catch(error)
{
console.log('加解密时发生错误',error);
}
})();