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

AES-GCM解密报错:Authentication tag does not match tag length求助

解决AES-GCM解密时"Authentication tag does not match tag length"错误

核心问题是你误解了node-forge中AES-GCM的标签处理逻辑:GCM的认证标签不会自动附加到密文输出里,cipher.finish()执行后,标签会单独存在于cipher.tag属性中。你当前只存储了IV和密文,解密时缺少必要的标签校验,所以触发错误。

修复步骤

1. 加密函数修改:追加认证标签到存储内容中

加密时需要把IV、密文、标签三者拼接后再编码为Base64:

import forge from 'node-forge';

// Convert hex to ByteStringBuffer
const hexToBytes = (hex) => forge.util.createBuffer(forge.util.hexToBytes(hex));

// 加密函数修改版
export const encryptDataWithSessionKey = (data, sessionKeyHex) => {
  console.log('data during encryption: ', data);

  try {
    const sessionKey = hexToBytes(sessionKeyHex);
    const iv = forge.random.getBytesSync(12); // 96 bits IV for GCM
    console.log('iv during encryption: ', iv);

    const dataBytes = forge.util.encodeUtf8(data);
    const cipher = forge.cipher.createCipher('AES-GCM', sessionKey);
    console.log('cipher during encryption: ', cipher);
    cipher.start({ iv, tagLength: 128 });
    cipher.update(forge.util.createBuffer(dataBytes));
    cipher.finish();

    // 取出密文和认证标签
    const encryptedBytes = cipher.output.getBytes();
    const tagBytes = cipher.tag.getBytes(); // 新增:获取GCM认证标签
    console.log('encrypted during encryption: ', encryptedBytes, encryptedBytes.length);
    console.log('tag during encryption: ', tagBytes, tagBytes.length);

    // 拼接IV + 密文 + 标签,再转Base64
    const encryptedBase64 = forge.util.encode64(iv + encryptedBytes + tagBytes); // 修改:加入标签
    console.log('encryptedBase64 during encryption: ', encryptedBase64, encryptedBase64.length);
    
    return encryptedBase64;
  } catch (error) {
    console.error('Error encrypting data:', error);
    throw error;
  }
};

2. 解密函数修改:拆分IV、密文、标签并传入解密器

解密时需要从解码后的字节中拆分出IV(前12字节)、密文(中间部分)、标签(最后16字节,对应128位tagLength),然后在启动解密器时传入标签:

// 解密函数修改版
export const decryptDataWithSessionKey = (encryptedData, sessionKeyHex) => {
  console.log('encryptedData during decryption: ', encryptedData);

  try {
    const sessionKey = hexToBytes(sessionKeyHex);
    const encryptedBytesWithIVTag = forge.util.decode64(encryptedData);

    // 拆分IV、密文、标签
    const iv = encryptedBytesWithIVTag.slice(0, 12);
    const tag = encryptedBytesWithIVTag.slice(-16); // 新增:取出最后16字节作为标签
    const encryptedBytes = encryptedBytesWithIVTag.slice(12, -16); // 修改:截取中间部分作为密文
    console.log('iv during decryption: ', iv);
    console.log('tag during decryption: ', tag);
    console.log('encryptedBytes during decryption: ', encryptedBytes, encryptedBytes.length);
    
    const decipher = forge.cipher.createDecipher('AES-GCM', sessionKey);
    console.log('decipher during decryption: ', decipher);

    console.log(1);
    // 修改:启动解密器时传入tag参数
    decipher.start({ iv, tagLength: 128, tag: forge.util.createBuffer(tag) });
    decipher.update(forge.util.createBuffer(encryptedBytes));
    console.log(2);
    const result = decipher.finish();
    console.log(3, result);

    const decrypted = decipher.output.getBytes();
    const decryptedData = forge.util.decodeUtf8(decrypted);

    return decryptedData;
  } catch (error) {
    console.error('Error decrypting data:', error);
    throw error;
  }
};

关键修改点说明

  • 加密时必须把cipher.tag的字节内容追加到密文后,一起编码存储
  • 解密时要从总字节中拆分出标签,通过tag参数传入decipher.start(),node-forge的GCM实现不会自动从密文末尾读取标签

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:46:04