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

Pycryptodome AES-GCM加密后Java解密报Tag mismatch问题求助

Fixing AES-GCM Tag Mismatch Between Pycryptodome and Java

Let's break down why you're hitting that AEADBadTagException and fix it step by step:

Root Causes

  • Missing Authentication Tag: AES-GCM is an AEAD (Authenticated Encryption with Associated Data) algorithm, which requires three components for decryption: the nonce, the ciphertext, and the authentication tag. Your Python code only sends the ciphertext to Java, but doesn't include the tag generated during encryption.
  • Java Code Variable Mix-Up: In your original Java snippet, you reference an undefined iv variable in GCMParameterSpec, and create an IvParameterSpec that's never used (GCM doesn't need this—GCMParameterSpec handles the nonce directly).

Fixed Python Encryption Code

You need to capture the tag after encryption and bundle it with the ciphertext (appending it works perfectly since you set mac_len=16 for a fixed-length tag):

import os
from Crypto.Cipher import AES

message = b"your target plaintext here"
cek = os.urandom(16)
nonce = os.urandom(12)
cipher = AES.new(cek, AES.MODE_GCM, nonce=nonce, mac_len=16)
ciphertext = cipher.encrypt(message)
# Capture the authentication tag generated during encryption
tag = cipher.digest()

# Bundle nonce + ciphertext + tag to send to Java (concatenation is a simple approach)
data_to_send = nonce + ciphertext + tag

Fixed Java Decryption Code

On the Java side, split the received data into its three components, then initialize the GCM cipher correctly:

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

public class GCMDecrypt {
    public static void main(String[] args) throws Exception {
        byte[] receivedData = /* Your combined data from Python: nonce + ciphertext + tag */;
        byte[] cek = /* The same CEK bytes used in Python encryption */;
        
        // Split the received data into components
        byte[] nonce = Arrays.copyOfRange(receivedData, 0, 12);
        byte[] tag = Arrays.copyOfRange(receivedData, receivedData.length - 16, receivedData.length);
        byte[] ciphertext = Arrays.copyOfRange(receivedData, 12, receivedData.length - 16);
        
        // Initialize AES-GCM cipher
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec gcmSpec = new GCMParameterSpec(128, nonce); // 128 bits = 16-byte tag
        SecretKeySpec secretKeySpec = new SecretKeySpec(cek, "AES");
        
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gcmSpec);
        
        // Combine ciphertext and tag before decryption
        byte[] ciphertextWithTag = new byte[ciphertext.length + tag.length];
        System.arraycopy(ciphertext, 0, ciphertextWithTag, 0, ciphertext.length);
        System.arraycopy(tag, 0, ciphertextWithTag, ciphertext.length, tag.length);
        
        byte[] decryptedBytes = cipher.doFinal(ciphertextWithTag);
        String decryptedMessage = new String(decryptedBytes);
        System.out.println("Decrypted content: " + decryptedMessage);
    }
}

Key Notes

  • Tag Handling: Pycryptodome generates the tag separately via cipher.digest()—never skip sending this to Java. Java's doFinal() expects the ciphertext followed by the tag (you can also use update() for ciphertext and doFinal() for the tag, but concatenation is simpler).
  • Nonce Best Practice: You're using the recommended 12-byte nonce for GCM, which avoids security risks associated with shorter nonces—keep that up!
  • Variable Consistency: Double-check all variable references (like fixing the iv/nonce mix-up in your original Java code) to avoid accidental mismatches.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:15:23