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
相关产品推荐
相关产品推荐

