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

Node.js AES-256-GCM加密时出现Invalid key length错误求助

解决Node.js AES-256-GCM加密的"Invalid key length"错误

我来帮你搞定这个问题——这个错误的根源非常明确:AES-256-GCM要求密钥必须是32字节(256位)长度,但你的代码里直接把短字符串'd6F3Efeq'当作密钥使用,它的UTF-8字节数只有8,远达不到AES-256的要求,所以crypto模块抛出了密钥长度无效的错误。

除此之外,你的代码还有几个需要修正的安全问题和笔误,我一步步给你拆解解决:

1. 正确生成符合要求的AES密钥

不能直接用明文密码当作AES密钥,应该用**密钥派生函数(KDF)**从密码中生成固定长度的密钥。Node.js的crypto模块提供了scrypt(推荐)或pbkdf2函数来做这件事,它们会通过加盐处理,生成符合长度要求的安全密钥。

2. 不要硬编码IV(初始化向量)

GCM模式下,IV应该是随机生成的(推荐12字节长度,这是GCM的最优长度),硬编码固定IV会严重降低加密的安全性——相同的明文+密钥+固定IV会生成相同的密文,泄露敏感信息。

3. 修正代码中的笔误

你的代码里返回了content:encrypted,但实际加密后的变量名是crypted,这会导致未定义变量的错误。


修正后的完整代码

module.exports = function(crypto) {
  const algorithm = 'aes-256-gcm';
  const password = 'd6F3Efeq'; // 你的原始密码(生产环境别硬编码,用环境变量!)

  this.testFunc = async function(text) {
    // 生成随机盐值(解密时需要用同一个盐,所以要保存下来)
    const salt = crypto.randomBytes(16);
    
    // 从密码派生32字节的AES-256密钥
    const key = await new Promise((resolve, reject) => {
      crypto.scrypt(password, salt, 32, (err, derivedKey) => {
        if (err) reject(err);
        resolve(derivedKey);
      });
    });

    // 生成随机12字节IV(GCM模式推荐长度)
    const iv = crypto.randomBytes(12);
    
    const cipher = crypto.createCipheriv(algorithm, key, iv);
    let crypted = cipher.update(text, 'utf8', 'hex');
    crypted += cipher.final('hex');
    const tag = cipher.getAuthTag();

    // 返回所有解密需要的参数:密文、标签、IV、盐值
    return {
      content: crypted,
      tag: tag.toString('hex'),
      iv: iv.toString('hex'),
      salt: salt.toString('hex')
    };
  };

  // 配套的解密函数,方便测试和使用
  this.decryptFunc = async function(encryptedData) {
    // 用相同的盐值派生密钥
    const key = await new Promise((resolve, reject) => {
      crypto.scrypt(password, Buffer.from(encryptedData.salt, 'hex'), 32, (err, derivedKey) => {
        if (err) reject(err);
        resolve(derivedKey);
      });
    });

    // 初始化解密器,传入密钥、IV,并设置验证标签
    const decipher = crypto.createDecipheriv(algorithm, key, Buffer.from(encryptedData.iv, 'hex'));
    decipher.setAuthTag(Buffer.from(encryptedData.tag, 'hex'));
    
    let decrypted = decipher.update(encryptedData.content, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted;
  };
};

关键说明

  • 密钥派生:scrypt函数通过加盐将短密码转换为32字节的安全密钥,同时增加了暴力破解的难度。
  • 随机IV:每次加密生成新的IV,确保相同明文加密后结果不同,符合加密的语义安全性。
  • GCM标签:getAuthTag()获取的标签用于解密时验证密文是否被篡改,这是GCM模式提供的完整性校验功能。
  • 生产环境注意:绝对不要把密码硬编码在代码里,应该用环境变量(比如process.env.ENCRYPTION_PASSWORD)或者专业的密钥管理服务存储密码。

内容的提问来源于stack exchange,提问作者Pranab V V

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:30:56