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

ReactJS加密NodeJS解密报错:Unsupported state or unable to authenticate data

解决AES-GCM解密报错:Unsupported state or unable to authenticate data

问题根源

浏览器端Web Crypto API的AES-GCM加密输出是密文+16字节认证标签的拼接结果,而Node.js的crypto模块在GCM模式下需要单独设置认证标签才能完成解密验证;同时两端的密钥处理逻辑不一致,也会导致认证失败。

修复方案

1. 同步前后端密钥处理逻辑

前端加密时只取密钥的前32字节(适配AES-256的密钥长度要求),后端必须同步这个处理:

const key = crypto.createSecretKey(Buffer.from(secretKey.slice(0, 32)), 'utf-8');

2. 拆分密文与认证标签并完成解密

从加密数据中拆分出密文和16字节的认证标签,在解密前手动设置认证标签:

const crypto = require('crypto');

const decryptJsonData = async (encryptedData, secretKey) => {
    const { iv, data } = encryptedData;
    // 同步前端密钥处理:仅取前32字节
    const key = crypto.createSecretKey(Buffer.from(secretKey.slice(0, 32)), 'utf-8');
    
    // GCM模式默认认证标签长度为16字节,拆分密文和标签
    const tag = Buffer.from(data.slice(-16));
    const ciphertext = Buffer.from(data.slice(0, -16));
    
    const decipher = crypto.createDecipheriv('aes-256-gcm', key, Buffer.from(iv));
    // 设置认证标签用于解密验证
    decipher.setAuthTag(tag);

    let decrypted = decipher.update(ciphertext);
    decrypted = Buffer.concat([decrypted, decipher.final()]);

    return JSON.parse(decrypted.toString());
}

module.exports = decryptJsonData

验证注意事项

  • 确保前后端使用的secretKey完全一致,且都严格截取前32字节
  • 认证标签长度固定为16字节,这是GCM模式的标准配置,Web Crypto API默认采用该长度
  • 前端加密逻辑无需修改,其输出已正确包含密文与认证标签的拼接结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 05:48:18