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

如何用Node.js原生方法实现AES-128-GCM解密?遇IV及认证错误

Node.js AES-128-GCM解密IV错误及认证失败问题解决

问题场景

你在使用Node.js原生crypto模块解密AES-128-GCM数据时,反复遇到两类错误:

  • 触发500错误:{ "statusCode": 500, "message": "Invalid initialization vector" }
  • 抛出异常:Unsupported state or unable to authenticate data

尝试多种IV生成方式后问题仍未解决,相关代码如下:

let decoded: string = '';
for (let ndx = 0; ndx < hash.length; ndx += 2) {
  let i = parseInt('0x' + hash.substring(ndx, ndx + 2));
  decoded += String.fromCharCode(i);
}

try {
  const password = 'somePassword';
  const key = crypto.scryptSync(password, 'salt', 16);
  const iv = Buffer.alloc(11, password, 'ascii'); // Initialization vector.
  const iv2 = crypto.randomBytes(32)
  const iv3 = iv2.toString('hex').slice(0, 16);
  const iv4 = Buffer.allocUnsafe(32)
  const decipher = crypto.createDecipheriv('aes-128-gcm', key, iv);

  let decrypted = decipher.update(decoded, 'ascii', 'utf8');
  decrypted += decipher.final('utf8');
} catch (err) {
  console.error(err);
}

错误原因分析

  1. IV参数不符合GCM要求
    AES-128-GCM模式要求IV必须是12字节的Buffer类型,你代码中的问题:

    • iv仅11字节,长度不达标直接触发无效IV错误
    • iv3是字符串类型,无法被createDecipheriv正确识别
    • iv4未初始化,内存为随机垃圾数据,不符合加密规范
  2. GCM认证标签缺失
    GCM是带完整性认证的加密模式,解密时必须传入加密阶段生成的认证标签(authTag),否则会触发数据认证失败错误,你的代码完全未处理该逻辑。

  3. 密文处理方式错误
    手动将十六进制hash转成ASCII字符串会导致二进制密文损坏,应该直接用Buffer处理十六进制数据。

修正后的代码示例

import crypto from 'crypto';

// 假设加密后的数据格式为: IV(12字节) + 密文 + 认证标签(16字节)
// 需根据实际加密端的拼接规则调整拆分逻辑
const decryptAES128GCM = (encryptedHex: string, password: string, salt: string) => {
  // 1. 将十六进制密文转成Buffer
  const encryptedBuffer = Buffer.from(encryptedHex, 'hex');
  
  // 2. 拆分IV、密文、认证标签
  const iv = encryptedBuffer.slice(0, 12); // GCM标准12字节IV
  const ciphertext = encryptedBuffer.slice(12, -16); // 中间部分为密文
  const authTag = encryptedBuffer.slice(-16); // 最后16字节为认证标签

  // 3. 从密码派生16字节AES-128密钥
  const key = crypto.scryptSync(password, salt, 16);

  // 4. 创建解密实例并设置认证标签
  const decipher = crypto.createDecipheriv('aes-128-gcm', key, iv);
  decipher.setAuthTag(authTag);

  // 5. 执行解密
  let decrypted = decipher.update(ciphertext);
  decrypted = Buffer.concat([decrypted, decipher.final()]);

  return decrypted.toString('utf8');
};

// 使用示例
try {
  const password = 'somePassword';
  const salt = 'salt';
  const encryptedHex = '替换为实际加密后的十六进制字符串';
  const plaintext = decryptAES128GCM(encryptedHex, password, salt);
  console.log('解密结果:', plaintext);
} catch (err) {
  console.error('解密失败:', err.message);
}

关键注意事项

  • IV必须与加密时完全一致:解密用的IV不能随机生成,必须是加密阶段使用的同一个IV,通常加密端会将IV与密文、认证标签一起返回。
  • 认证标签不可缺失:GCM模式的认证标签是验证数据完整性的核心,必须和加密时生成的标签完全匹配。
  • 密钥派生规则一致:加密和解密时使用的盐(salt)、密钥派生算法、密钥长度必须完全相同,否则无法生成正确的解密密钥。
  • 避免字符串转码损坏:密文需以二进制或十六进制形式处理,禁止转成ASCII等编码格式导致数据丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:52:41