You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 04:45:11