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

Node.js AES-256-GCM加密数据无法被Java解密问题求助

解决Node.js AES-256-GCM加密后Java解密报AEADBadTagException的问题

你的Java解密代码存在几个关键错误,直接导致标签验证失败,下面是问题分析和修复方案:

问题点

  1. 缺失Base64解码:Node.js输出的密文、标签、IV都是Base64编码后的字符串,但Java端直接调用getBytes()将这些字符串转成字节——这相当于把Base64字符的UTF-8编码当成了原始加密字节,完全不符合要求,必须先对Base64字符串解码。
  2. GCM标签处理错误:Java里用cipher.update(tag)传递认证标签是错误的逻辑,GCM模式下的认证标签需要在doFinal阶段处理,不能通过update方法传入。
  3. 密钥编码未统一:Java端KEY.getBytes()未指定编码,如果Node.js的密钥是UTF-8编码的字符串,Java默认编码可能与之不匹配,导致密钥字节不一致。

修复后的Java解密代码

import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESDecryptor {
    // 替换成和Node.js端一致的32字节密钥,保持UTF-8编码
    private static final String KEY = "your-32-byte-secret-key-here";

    public static String decrypt(String encryData) throws Exception {
        String[] parts = encryData.split("\\.");
        // 对Base64字符串解码,还原加密时的原始字节
        byte[] encryptedBytes = Base64.getDecoder().decode(parts[0]);
        byte[] tagBytes = Base64.getDecoder().decode(parts[1]);
        byte[] ivBytes = Base64.getDecoder().decode(parts[2]);

        GCMParameterSpec gcmSpec = new GCMParameterSpec(128, ivBytes);
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        // 指定UTF-8编码,确保密钥字节和Node.js端完全一致
        SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmSpec);

        // 先处理密文,再传入标签完成解密和验证
        byte[] partialDecrypt = cipher.update(encryptedBytes);
        byte[] finalDecrypt = cipher.doFinal(tagBytes);

        // 合并解密后的字节数组
        byte[] result = new byte[partialDecrypt.length + finalDecrypt.length];
        System.arraycopy(partialDecrypt, 0, result, 0, partialDecrypt.length);
        System.arraycopy(finalDecrypt, 0, result, partialDecrypt.length, finalDecrypt.length);

        return new String(result, "UTF-8");
    }
}

额外注意事项

  • 密钥必须是32字节(256位):AES-256要求密钥长度严格为32字节,Node.js里的key参数如果是字符串,要确保它的UTF-8编码结果是32字节,否则Node.js会自动截断,导致Java端密钥不匹配。
  • 全程统一UTF-8编码:所有涉及字符串转字节的操作(密钥、明文、解密结果)都要指定UTF-8,避免编码差异导致的字节不一致。
  • IV长度符合标准:你Node.js里使用的12字节IV是GCM模式推荐的长度,Java端无需修改这部分逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:30:27