AEADBadTagException: mac check in GCM failed during AES decryption with BouncyCastle

I am encountering a javax.crypto.AEADBadTagException: mac check in GCM failed error when attempting to decrypt data using AES in GCM mode with BouncyCastle. The error occurs during the AES decryption step, after I’ve decrypted an AES key using RSAES-OAEP and attempted to use it for decryption.

I have verified that the AES key and IV seem correct, but the MAC verification fails. This usually happens when the data or associated tag is altered or incorrect.

Investigation:
I’m using GCMParameterSpec for the IV and a 128-bit tag length for AES decryption.
The error suggests a mismatch between the ciphertext and the authentication tag, which may indicate an issue with either the IV, the AES key, or the data integrity during encryption/decryption.

public class Encryption {
    static String certificatePath =
        "C:\\Users\\PSAD07564\\Desktop\\Peppol\\IVLenght\\peppol."
        + "lx.erf01.net.crt";
    private static final String RSA_TRANSFORMATION =
        "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
    private static final String AES_TRANSFORMATION = "AES/GCM/NoPadding";
    private static final int GCM_TAG_LENGTH = 128;
    // static String privateKey = "D:\Mahipalsing\POC
    // CERT\PROD\NEW_SAN\uxplpiacp01.lx.erf01.net_GUI.key";


    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        // Path to the .key file
        String keyFilePath =
            "C:\Users\PSAD07564\Desktop\Peppol\IVLenght\peppol.lx.erf01."
            + "net.key";

        // Read the private key file
        String keyContent =
            new String(Files.readAllBytes(Paths.get(keyFilePath)));

        // Remove PEM headers and clean up the content
        keyContent = keyContent.replace("-----BEGIN PRIVATE KEY-----", "")
                         .replace("-----END PRIVATE KEY-----", "")
                         .replaceAll("\s+", ""); // Remove all whitespace

        // Debugging: Print the cleaned-up key content
        // System.out.println("Cleaned Key Content: " + keyContent);

        // Decode the Base64-encoded private key
        byte[] keyBytes = Base64.getDecoder().decode(keyContent);

        // Generate a PrivateKey instance
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory =
            KeyFactory.getInstance("RSA"); // Use the appropriate algorithm
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        String plainText = "AES 256 GCM Testing";

        // Create a CertificateFactory instance
        CertificateFactory certificateFactory =
            CertificateFactory.getInstance("X.509");

        // Read the certificate from the file
        FileInputStream fis = new FileInputStream(certificatePath);
        X509Certificate certificate =
            (X509Certificate) certificateFactory.generateCertificate(fis);

        CMSEnvelopedDataGenerator cmsEnvelopedDataGenerator =
            new CMSEnvelopedDataGenerator();
        CMSEnvelopedData data = null;
        cmsEnvelopedDataGenerator.addRecipientInfoGenerator(
            new JceKeyTransRecipientInfoGenerator(
                certificate, rsaesOaepIdentifier())
                .setProvider(BouncyCastleProvider.PROVIDER_NAME));

        data = cmsEnvelopedDataGenerator.generate(
            new CMSProcessableByteArray(plainText.getBytes()),
            new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_GCM)
                .setProvider("BC")
                .build());

        byte[] data1 = data.getEncoded();

        System.out.println("Data:");
        System.out.println(data);
        System.out.println(data1);

        CMSEnvelopedDataParser cmsEnvelopedDataParser =
            new CMSEnvelopedDataParser(data1);
        Collection<?> recipients =
            cmsEnvelopedDataParser.getRecipientInfos().getRecipients();
        Iterator<RecipientInformation> it =
            (Iterator<RecipientInformation>) recipients.iterator();
        RecipientInformation recipient = it.next();

        InputStream decryptedStream =
            recipient
                .getContentStream(
                    new JceKeyTransEnvelopedRecipient(privateKey)
                        .setAlgorithmMapping(
                            PKCSObjectIdentifiers.id_RSAES_OAEP,
                            "RSA/GCM/OAEPWithSHA-256AndMGF1Padding"))
                .getContentStream();

        System.out.println(
            "decryptedStream : " + convertInputstreamToString(decryptedStream));

        ContentInfo info =
            ContentInfo.getInstance(ASN1Primitive.fromByteArray(data1));
        EnvelopedData envData = EnvelopedData.getInstance(info.getContent());
        ASN1Set s = envData.getRecipientInfos();
        RecipientInfo recipientInfo =
            RecipientInfo.getInstance(s.getObjectAt(0));
        byte[] encryptedKey;
        if (recipientInfo.getInfo() instanceof KeyTransRecipientInfo) {
            KeyTransRecipientInfo keyTransRecipientInfo =
                KeyTransRecipientInfo.getInstance(recipientInfo.getInfo());
            encryptedKey = keyTransRecipientInfo.getEncryptedKey().getOctets();
            AlgorithmIdentifier keyEncryptionAlgorithm =
                keyTransRecipientInfo.getKeyEncryptionAlgorithm();
            System.out.println(keyEncryptionAlgorithm.getAlgorithm().getId());
            System.out.println(encryptedKey);
            System.out.println("Encrypted Key Length: " + encryptedKey.length);
            // Decrypt the AES key using the private key
            OAEPParameterSpec oaepSpec = new OAEPParameterSpec("SHA-256",
                "MGF1", new MGF1ParameterSpec("SHA-256"),
                PSource.PSpecified.DEFAULT);
            Cipher rsaCipher = Cipher.getInstance(
                RSA_TRANSFORMATION, BouncyCastleProvider.PROVIDER_NAME);
            System.out.println("Step: 1");
            rsaCipher.init(Cipher.DECRYPT_MODE, privateKey, oaepSpec);
            System.out.println("Step: 2");
            System.out.println(
                "rsaCipher Blocksize: " + rsaCipher.getBlockSize());
            byte[] aesKeyBytes = rsaCipher.doFinal(encryptedKey);
            System.out.println(aesKeyBytes);
            System.out.println("aesKeyBytes Key Length: " + aesKeyBytes.length);
            // Reconstruct the AES key
            AlgorithmIdentifier contentEncryptionAlgorithm =
                envData.getEncryptedContentInfo()
                    .getContentEncryptionAlgorithm();
            System.out.println("Symmetric Encryption Algorithm  : "
                + contentEncryptionAlgorithm.getAlgorithm().getId());
            System.out.println("Octect Encrypted data           : "
                + Hex.toHexString(envData.getEncryptedContentInfo()
                                      .getEncryptedContent()
                                      .getOctets()));

            SecretKey aesKey = new SecretKeySpec(aesKeyBytes, "AES");
            System.out.println("Step: 3");
            // Process the AES decryption as needed...

            Cipher aesCipher = Cipher.getInstance(
                AES_TRANSFORMATION, BouncyCastleProvider.PROVIDER_NAME);
            System.out.println("Step: 4");
            byte[] iv = new byte[16];
            ASN1Primitive iv1 = envData.getEncryptedContentInfo()
                                    .getContentEncryptionAlgorithm()
                                    .getParameters()
                                    .toASN1Primitive();
            System.out.println(iv1);
            SecureRandom randomGenerator = new SecureRandom();
            randomGenerator.nextBytes(iv);

            GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
            System.out.println("Step: 5");
            aesCipher.init(Cipher.DECRYPT_MODE, aesKey, gcmSpec);
            System.out.println("Step: 6");

            byte[] FinalContain =
                aesCipher.doFinal(envData.getEncryptedContentInfo()
                                      .getEncryptedContent()
                                      .getOctets());
            System.out.println("Step: 7");
            System.out.println("FinalContain: ");
            System.out.println(FinalContain);
        } else {
            throw new IllegalStateException("expected KeyTransRecipientInfo");
        }
        AlgorithmIdentifier contentEncryptionAlgorithm =
            envData.getEncryptedContentInfo().getContentEncryptionAlgorithm();
        System.out.println("Symmetric Encryption Algorithm  : "
            + contentEncryptionAlgorithm.getAlgorithm().getId());
        System.out.println("Octect Encrypted data           : "
            + Hex.toHexString(envData.getEncryptedContentInfo()
                                  .getEncryptedContent()
                                  .getOctets()));
    }

    private static String convertInputstreamToString(
        InputStream decryptedStream) throws IOException {
        try (BufferedReader reader =
                 new BufferedReader(new InputStreamReader(decryptedStream))) {
            return reader.lines().collect(
                Collectors.joining(System.lineSeparator()));
        }
    }

    private static AlgorithmIdentifier rsaesOaepIdentifier() {
        // TODO Auto-generated method stub
        AlgorithmIdentifier hash = new AlgorithmIdentifier(
            NISTObjectIdentifiers.id_sha256, DERNull.INSTANCE);
        AlgorithmIdentifier mask =
            new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hash);
        AlgorithmIdentifier pSource =
            new AlgorithmIdentifier(PKCSObjectIdentifiers.id_pSpecified,
                new DEROctetString(new byte[0]));
        return new AlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP,
            new RSAESOAEPparams(hash, mask, pSource));
    }
}

Logs:

Data:
org.bouncycastle.cms.CMSEnvelopedData@368247b9
[B@1a6d8329
decryptedStream : AES 256 GCM Testing
1.2.840.113549.1.1.7
[B@710c2b53
Encrypted Key Length: 256
Step: 1
Step: 2
rsaCipher Blocksize: 256
[B@5386659f
aesKeyBytes Key Length: 32
Symmetric Encryption Algorithm  : 2.16.840.1.101.3.4.1.46
Octect Encrypted data           : 4b72ef2cc6624f297d701ab38627f73ac8a72fb50ed9d615f0616815d757b89bf8aeac     
Step: 3
Step: 4
[#461ab7477bacd84583cc743d, 16]
Step: 5
Step: 6

Exception:

Exception in thread "main" javax.crypto.AEADBadTagException: mac check in GCM failed
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)      
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)
        at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
        at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$AEADGenericBlockCipher.doFinal(Unknown Source)
        at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)     
        at java.base/javax.crypto.Cipher.doFinal(Unknown Source)
        at peppoltest.demo.Encryption.main(Encryption.java:197)

Question:
What could be causing this AEADBadTagException in GCM mode, and how can I resolve it? Should I check the IV or encryption parameters, or is the issue related to something else in the decryption process?

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật