JavaScript中AES-GCM加密函数报DOMException:数据不符合操作要求
问题原因
AES-GCM算法对密钥长度有强制要求,必须是128位(16字节)、192位(24字节)或256位(32字节)。你传入的密钥字符串"5gfdgdfef"是9个字符,经UTF-8编码后仅9字节,不符合AES的密钥长度规范,导致crypto.subtle.importKey调用失败。
解决方案
有两种可行的修正方式:
方式一:使用符合长度要求的直接密钥
直接传入16/24/32字节长度的密钥字符串(ASCII字符的话,字符数等于字节数),同时补充AES-GCM必需的随机初始化向量(IV):
async function NewEncrypt(data, key) { const enc = new TextEncoder(); // 确保key编码后为16/24/32字节 const CryptoKeyObject = await crypto.subtle.importKey( "raw", enc.encode(key).buffer, {"name": "AES-GCM"}, false, ['encrypt'] ); const encodedData = enc.encode(data); // 生成12字节随机IV(AES-GCM推荐长度) const iv = crypto.getRandomValues(new Uint8Array(12)); const EncryptedData = await crypto.subtle.encrypt( {name: 'AES-GCM', iv: iv}, CryptoKeyObject, encodedData ); // 将IV和加密结果转为base64,方便后续存储/传输 return { iv: btoa(String.fromCharCode(...iv)), encryptedData: btoa(String.fromCharCode(...new Uint8Array(EncryptedData))) }; } // 调用示例:使用16字符的合规密钥 NewEncrypt("1234", "abcdefghijklmnop");
方式二:从任意长度密码派生密钥
如果需要用任意长度的用户密码,需通过密钥派生函数(如PBKDF2)将密码转换为符合长度要求的AES密钥:
async function NewEncrypt(data, password) { const enc = new TextEncoder(); // 生成随机盐值 const salt = crypto.getRandomValues(new Uint8Array(16)); // 导入密码作为密钥材料 const keyMaterial = await crypto.subtle.importKey( "raw", enc.encode(password), {name: "PBKDF2"}, false, ["deriveKey"] ); // 派生256位AES密钥 const CryptoKeyObject = await crypto.subtle.deriveKey( { name: "PBKDF2", salt: salt, iterations: 100000, hash: "SHA-256" }, keyMaterial, {name: "AES-GCM", length: 256}, false, ["encrypt"] ); const iv = crypto.getRandomValues(new Uint8Array(12)); const encodedData = enc.encode(data); const EncryptedData = await crypto.subtle.encrypt( {name: 'AES-GCM', iv: iv}, CryptoKeyObject, encodedData ); // 返回盐、IV和加密结果(均转为base64) return { salt: btoa(String.fromCharCode(...salt)), iv: btoa(String.fromCharCode(...iv)), encryptedData: btoa(String.fromCharCode(...new Uint8Array(EncryptedData))) }; } // 调用示例:使用任意长度的密码 NewEncrypt("1234", "5gfdgdfef");
内容的提问来源于stack exchange,提问作者SK15
相关产品推荐
相关产品推荐

