AES/GCM/NoPadding AEADBadTagException

10,593

I've corrected a few typos, and used Java 8's base64 utilities, and it seems to work fine for me. Here is my version and you can compare it to yours.

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

public class Main {
    private final static int GCM_IV_LENGTH = 12;
    private final static int GCM_TAG_LENGTH = 16;

    private static String encrypt(String privateString, SecretKey skey) throws Exception {
        byte[] iv = new byte[GCM_IV_LENGTH];
        (new SecureRandom()).nextBytes(iv);

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, iv);
        cipher.init(Cipher.ENCRYPT_MODE, skey, ivSpec);

        byte[] ciphertext = cipher.doFinal(privateString.getBytes("UTF8"));
        byte[] encrypted = new byte[iv.length + ciphertext.length];
        System.arraycopy(iv, 0, encrypted, 0, iv.length);
        System.arraycopy(ciphertext, 0, encrypted, iv.length, ciphertext.length);

        String encoded = Base64.getEncoder().encodeToString(encrypted);

        return encoded;
    }

    private static String decrypt(String encrypted, SecretKey skey) throws Exception {
        byte[] decoded = Base64.getDecoder().decode(encrypted);

        byte[] iv = Arrays.copyOfRange(decoded, 0, GCM_IV_LENGTH);

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, iv);
        cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec);

        byte[] ciphertext = cipher.doFinal(decoded, GCM_IV_LENGTH, decoded.length - GCM_IV_LENGTH);

        String result = new String(ciphertext, "UTF8");

        return result;
    }

    public static void main(String[] args) throws Exception {
        SecretKey key = new SecretKeySpec(new byte[16], "AES"); // key is 16 zero bytes
        String s = decrypt(encrypt("This is the first string to test", key), key);
        System.out.println(s);
    }
}
Share:
10,593

Related videos on Youtube

Cille
Author by

Cille

Updated on September 14, 2022

Comments

  • Cille
    Cille almost 2 years

    I am trying to use AES/GCM/NoPadding for encryption in Java8. But I can't figure out why I am having a AEADBadTagException when decrypting.

    Here's my code:

    private final int GCM_IV_LENGTH = 12;
    private final int GCM_TAG_LENGTH = 16;
    
    private static String encrypt(String privateString, SecretKey skey) {
        byte[] iv = new byte[GCM_IV_LENGTH];
        (new SecureRandom()).nextBytes(iv);
    
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, iv);
        cipher.init(Cipher.ENCRYPT_MODE, skey, ivSpec);
    
        byte[] ciphertext = cipher.doFinal(privateString.getBytes("UTF8"));
        byte[] encrypted = new byte[iv.length + ciphertext.length];
        System.arraycopy(iv, 0, encrypted, 0, iv.length);
        System.arraycopy(ciphertext, 0, encrypted, iv.length, ciphertext.length);
    
        Base64Encoder encoder = new Base64Encoder();
        String encoded = encoder.encode(encrypted);
    
        return encoded;
    }
    
    private static String decrypt(String encrypted, SecretKey skey) {
        Base64Decoder decoder = new Base64Decoder();
        String decoded = encoder.encode(encrypted);
    
        byte[] iv = Arrays.copyOfRange(decoded, 0, GCM_IV_LENGTH);
    
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec ivSpec = new GCMParameterSpec(GCM_TAG_LENGTH * Byte.SIZE, iv);
        cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec);
    
        byte[] ciphertext = cipher.doFinal(decoded, GCM_IV_LENGTH, decoded.length - GCM_IV_LENGTH);
    
        String newString = new String(ciphertext, "UTF8");
    
        return newString;
    }
    

    Hope someone can help me fix this exception. Thanks!

    • President James K. Polk
      President James K. Polk almost 7 years
      is this java? Your methods claim to return String but actually try to return byte[]. Please post code the compiles. How to create a MCVE
  • Cille
    Cille almost 7 years
    Oh I figured it out now. I tried using java.util.Base64 and found out that I missed to configure my eclipse to java 8. I really believed it's already running in java 8. How stupid lol. Thank you very much!
  • IgorGanapolsky
    IgorGanapolsky about 6 years
    getDecoder only works on Android API 26. What do we do with older platforms?
  • President James K. Polk
    President James K. Polk about 6 years
    @IgorGanapolsky: Use android.util.Base64.
  • Prudhvi
    Prudhvi over 4 years
    If you provide GCMParameterSpec while you encrypt here cipher.init(Cipher.ENCRYPT_MODE, skey, ivSpec); you get Caller-provided IV not permitted as a reason in the exception.