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

如何使用Java 8编写带认证标签的AES-GCM解密代码?

Java 8 实现 AES-256-GCM 解密(对应Node.js crypto等效逻辑)

以下是与你提供的Node.js代码完全等效的Java 8实现,重点解决GCM模式下认证标签的处理问题:

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

public class AESGCMDecryptor {
    private static final String ALGORITHM = "AES/GCM/NoPadding";
    private static final int TAG_LENGTH_BITS = 128; // GCM默认标签长度为128位

    public static String decryptSymmetric128BitHexKeyUTF8(String ciphertext, String iv, String tag, String key) throws Exception {
        // 1. 处理密钥:Node.js直接使用字符串的UTF-8字节作为AES密钥
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");

        // 2. 解码IV和认证标签(Base64转字节数组)
        byte[] ivBytes = Base64.getDecoder().decode(iv);
        byte[] tagBytes = Base64.getDecoder().decode(tag);

        // 3. 合并密文与标签:GCM标准格式为「密文 + 认证标签」,Node.js将两者拆分存储,需重新合并
        byte[] ciphertextBytes = Base64.getDecoder().decode(ciphertext);
        byte[] combinedData = new byte[ciphertextBytes.length + tagBytes.length];
        System.arraycopy(ciphertextBytes, 0, combinedData, 0, ciphertextBytes.length);
        System.arraycopy(tagBytes, 0, combinedData, ciphertextBytes.length, tagBytes.length);

        // 4. 初始化GCM解密器
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        GCMParameterSpec gcmSpec = new GCMParameterSpec(TAG_LENGTH_BITS, ivBytes);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);

        // 5. 解密并自动验证标签:标签不匹配时会抛出AEADBadTagException
        byte[] plaintextBytes = cipher.doFinal(combinedData);
        return new String(plaintextBytes, StandardCharsets.UTF_8);
    }

    // 测试用例
    public static void main(String[] args) throws Exception {
        String cipherText = "2LPVwa7s4+xyd8KF94r07TOCaOdf4X90NWqhHQCpoJGT+T3TYjKCWf3V+A==";
        String iv = "S4/yimaF8bu0jQW9uagIJA==";
        String tag = "L6BtTic18dd4fNL2maytFA==";
        String key = "password1232asdfpassword1232asdf";
        String expectedPlainText = "The quick brown fox jumps over the lazy dog";

        String decryptedText = decryptSymmetric128BitHexKeyUTF8(cipherText, iv, tag, key);
        System.out.println("解密结果:" + decryptedText);
        System.out.println("与预期匹配:" + decryptedText.equals(expectedPlainText));
    }
}

关键逻辑说明

  • 密钥匹配:Node.js中直接传入字符串作为密钥,Java通过String.getBytes(StandardCharsets.UTF_8)获取完全一致的字节数组,你的测试密钥正好是32字节(符合AES-256的要求)。
  • 标签处理:GCM模式的标准输出是密文加标签,Node.js代码将两者分离存储,因此Java需要先将密文和标签拼接,才能让解密器自动完成标签验证。
  • GCM参数配置:GCMParameterSpec指定标签长度(128位,与Node.js默认值一致)和初始化向量(IV),确保解密逻辑对齐。
  • 标签验证:调用cipher.doFinal()时,Cipher会自动验证标签有效性,若标签不匹配或数据被篡改,会抛出AEADBadTagException异常。

注意事项

  • 确保密钥长度与AES版本匹配:AES-256需要32字节密钥,AES-128需要16字节密钥,若密钥长度不符会抛出InvalidKeyException。
  • 标签长度需保持一致:GCM支持128/120/112/104/96位标签,需与加密端配置一致,否则解密会失败。
  • 异常处理:实际生产代码中需捕获并处理NoSuchAlgorithmException(算法不存在)、InvalidKeyException(密钥无效)、AEADBadTagException(标签验证失败)等异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 05:37:01