Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java AES GCM Tag mismatch

I have a problem with Java AES GCM encryption. I have followed the instructions on this page to generate the following code:

package aes;

import java.nio.ByteBuffer;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AES {
    private Cipher encryptCipher;
    private Cipher decryptCipher;
    private byte[] key;
    private int keyLength;
    private SecretKeySpec keySpec;
    private SecureRandom random;

    public AES(String key) {
        try {
            this.key = key.getBytes();
            this.keyLength = this.key.length*8; // key length in bits
            this.keySpec = new SecretKeySpec(this.key, "AES");
            this.encryptCipher = Cipher.getInstance("AES/GCM/NoPadding");
            this.decryptCipher = Cipher.getInstance("AES/GCM/NoPadding");
            this.random = SecureRandom.getInstance("SHA1PRNG");
        }
        catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
    public byte[] encrypt(byte[] plaintext) {
        try {
            byte[] iv = new byte[12]; // create new IV
            random.nextBytes(iv); 
            encryptCipher.init(Cipher.ENCRYPT_MODE, keySpec, new GCMParameterSpec(keyLength, iv));
            byte[] encrypted = encryptCipher.doFinal(plaintext);
            ByteBuffer byteBuffer = ByteBuffer.allocate(iv.length + encrypted.length);
            byteBuffer.put(iv);
            byteBuffer.put(encrypted);
            return byteBuffer.array(); // IV(0)...IV(11) + ENCRYPTED(0)...ENCRYPTED(N)
        }
        catch (Exception e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
    public byte[] decrypt(byte[] ciphertext) {
        try {
            ByteBuffer byteBuffer = ByteBuffer.wrap(ciphertext);
            byte[] iv = new byte[12];
            byteBuffer.get(iv);
            byte[] encrypted = new byte[byteBuffer.remaining()];
            byteBuffer.get(encrypted);
            decryptCipher.init(Cipher.DECRYPT_MODE, keySpec, new GCMParameterSpec(keyLength, iv));
            return decryptCipher.doFinal(ciphertext);
        }
        catch (Exception e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
            return null;
        }
    } 
}

In the main, I call the whole thing as follows:

package aes;

public class Main {
    static byte[] plaintext = new byte[] {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53};
    public static void main(String[] args) {
        AES aes = new AES("Random09Random09");

        byte[] encrypted = aes.encrypt(plaintext);
        byte[] decrypted = aes.decrypt(encrypted);  
    }
}

Now I always get a tag mismatch error like this:

Tag mismatch!
javax.crypto.AEADBadTagException: Tag mismatch!
    at com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:578)
    at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1049)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:985)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at javax.crypto.Cipher.doFinal(Cipher.java:2164)
    at aes.AES.decrypt(AES.java:55)
    at aes.Main.main(Main.java:9)

for which I can not determine the cause. The StackTrace is not helpful to me. I would be grateful if someone could help me with that. As you can see in the StackTrace, the error is in decryption in step

doFinal (...)
like image 332
Lukas Nothhelfer Avatar asked Jun 21 '26 13:06

Lukas Nothhelfer


1 Answers

I finally found the mistake by myself. The mistake was that in the decrypt method I tried to do doFinal (...) on the whole received message and not just on the extracted ciphertext. I left the mistake in my question and post here the relevant (now correct) part of the program. @kelalaka Thank you for your efforts.

    public byte[] decrypt(byte[] ciphertext) {
        try {
            ByteBuffer byteBuffer = ByteBuffer.wrap(ciphertext);
            byte[] iv = new byte[12];
            byteBuffer.get(iv);
            byte[] encrypted = new byte[byteBuffer.remaining()];
            byteBuffer.get(encrypted);
            decryptCipher.init(Cipher.DECRYPT_MODE, keySpec, new GCMParameterSpec(keyLength, iv));
            return decryptCipher.doFinal(encrypted); // here was the mistake
        }
        catch (Exception e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
            return null;
        }
    } 

And the main:

package aes;

public class Main {
    static byte[] plaintext = new byte[] {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53};
    public static void main(String[] args) {
        AES aes = new AES("Random09Random09");

        byte[] encrypted = aes.encrypt(plaintext);
        byte[] decrypted = aes.decrypt(encrypted);  
        System.out.println("Original:\n" + new String(plaintext) + "\nEncrypted:\n" + new String(encrypted) + "\nDecrypted:\n" + new String(decrypted));
    }
}

The (now correct) output of the program:

Original:
ABCDEFGHIJKLMNOPQRS
Encrypted:
�~q꽕kl�9���&�ZB=�WPU�"�'�H���]:?Bo
Decrypted:
ABCDEFGHIJKLMNOPQRS
like image 90
Lukas Nothhelfer Avatar answered Jun 24 '26 03:06

Lukas Nothhelfer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!