AES Encryption and Decryption in Java

AES Encryption and Decryption in Java thumbnail

Transmitting confidential information such as passwords, API keys or personal data over a network is always vulnerable to attacks. To protect sensitive information, applications use encryption algorithms along with secure communication protocols such as TLS/SSL.

Java provides strong cryptographic support through the Java Cryptography Architecture (JCA). One of the most widely used encryption algorithms is AES (Advanced Encryption Standard). AES is fast, secure and commonly used in APIs, databases, cloud applications and banking systems.

What is AES Encryption?

AES (Advanced Encryption Standard) is a symmetric encryption algorithm standardized by NIST in 2001. Symmetric encryption means the same secret key is used for both encryption and decryption.

AES supports 3 key sizes:

  • AES-128 -> 128-bit key (16 bytes)
  • AES-192 -> 192-bit key (24 bytes)
  • AES-256 -> 256-bit key (32 bytes)

AES-256 provides the strongest security and is widely used in modern enterprise applications.

AES Architecture

aes

The input can be of 128 bit or 192 bit or 256 bit and corresponding bit of cipher text is generated.

But, as a developer behind Edu Jungles reports, if you are selecting 128 bits for encryption, then the secret key must be of 16 bits long and 24 and 32 bits for 192 and 256 bits of key size.

Symmetric vs Asymmetric Encryption

Encryption algorithms are broadly categorized into two types:

Symmetric Encryption

Symmetric encryption uses a single secret key for both encryption and decryption. It is extremely fast and suitable for encrypting large amounts of data. AES is an example of symmetric encryption and it can be visualised with this online AES encryption tool.

Asymmetric Encryption

Asymmetric encryption uses two different keys:

  • Public Key
  • Private Key

Data encrypted using the public key can only be decrypted using the corresponding private key. RSA is a common example of asymmetric encryption and it can be visualised with this online RSA encryption tool.

Asymmetric encryption is slower and mainly used for secure key exchange, SSL/TLS and digital signatures.

AES Encryption Modes

AES is a block cipher and requires a mode of operation for encrypting data securely. The most commonly used AES modes are ECB, CBC and GCM.

ECB Mode (Not Recommended)

ECB (Electronic Codebook) encrypts each block independently using the same key. If the plaintext contains repeating patterns, the encrypted output will also contain visible patterns. Because of this weakness, ECB mode should never be used for sensitive data.

CBC Mode

CBC (Cipher Block Chaining) mode introduces an Initialization Vector (IV) to randomize encryption. Even if the same plaintext is encrypted multiple times using the same key, the ciphertext will be different because of the random IV.

CBC mode is more secure than ECB but still requires integrity protection.

GCM Mode (Recommended)

GCM (Galois/Counter Mode) is the recommended AES mode for modern applications. It provides both confidentiality and authentication, protecting encrypted data from tampering attacks.

AES/GCM is widely used in modern APIs, TLS implementations and cloud systems.

Understanding Initialization Vector (IV)

An Initialization Vector (IV) is a random sequence of bytes used along with the encryption key. The IV ensures that encrypting the same plaintext multiple times produces different ciphertexts.

Important points about IV:

  • IV should always be random
  • IV is not secret and can be stored with ciphertext
  • Never reuse the same IV with the same encryption key
  • CBC typically uses 16-byte IV
  • GCM typically uses 12-byte IV

Understanding Padding in AES

AES works on fixed-size blocks of 16 bytes. If the plaintext size is not a multiple of 16 bytes, padding is added to complete the final block.

The most common padding scheme in Java is:

  • PKCS5Padding

For example:

  • "hello" -> padded to 16 bytes before encryption

In GCM mode, padding is not required because GCM works like a stream cipher internally. Hence we use:


AES/GCM/NoPadding

Secret Key Format in AES

AES secret keys are binary keys represented as byte arrays. The key length must exactly match the AES variant being used.

AES Variant Key Length
AES-128 16 bytes
AES-192 24 bytes
AES-256 32 bytes

In Java, AES keys are represented using:


SecretKey secretKey

IV Format in AES

The IV is also represented as a byte array. In Java, IV is commonly wrapped using:


IvParameterSpec iv

For GCM mode, Java uses:


GCMParameterSpec

AES Encryption in Java using CBC

The following example demonstrates AES encryption using CBC mode with PKCS5 padding.


import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.SecureRandom;
import java.util.Base64;

public class AESCBCEncryption {

    public static void main(String[] args) throws Exception {

        String plainText = "Hello AES CBC Encryption";

        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(256);

        SecretKey secretKey = keyGenerator.generateKey();

        byte[] iv = new byte[16];
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.nextBytes(iv);

        IvParameterSpec ivParameterSpec =
                new IvParameterSpec(iv);

        Cipher cipher =
                Cipher.getInstance("AES/CBC/PKCS5Padding");

        cipher.init(
                Cipher.ENCRYPT_MODE,
                secretKey,
                ivParameterSpec
        );

        byte[] encryptedBytes =
                cipher.doFinal(plainText.getBytes());

        String encryptedText =
                Base64.getEncoder()
                        .encodeToString(encryptedBytes);

        System.out.println("Encrypted Text:");
        System.out.println(encryptedText);
    }
}

AES Decryption in Java using CBC

The following example demonstrates AES decryption using the same secret key and IV.


import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.util.Base64;

public class AESCBCDecryption {

    public static String decrypt(
            String encryptedText,
            SecretKey secretKey,
            byte[] iv
    ) throws Exception {

        Cipher cipher =
                Cipher.getInstance("AES/CBC/PKCS5Padding");

        IvParameterSpec ivParameterSpec =
                new IvParameterSpec(iv);

        cipher.init(
                Cipher.DECRYPT_MODE,
                secretKey,
                ivParameterSpec
        );

        byte[] decodedBytes =
                Base64.getDecoder()
                        .decode(encryptedText);

        byte[] decryptedBytes =
                cipher.doFinal(decodedBytes);

        return new String(decryptedBytes);
    }
}

AES Encryption in Java using GCM

AES/GCM is the recommended encryption mode because it provides both encryption and authentication.


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

public class AESGCMEncryption {

    private static final int AES_KEY_SIZE = 256;
    private static final int GCM_IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 128;

    public static void main(String[] args) throws Exception {

        String plainText = "Hello AES GCM";

        KeyGenerator keyGenerator =
                KeyGenerator.getInstance("AES");

        keyGenerator.init(AES_KEY_SIZE);

        SecretKey secretKey =
                keyGenerator.generateKey();

        byte[] iv = new byte[GCM_IV_LENGTH];

        SecureRandom secureRandom =
                new SecureRandom();

        secureRandom.nextBytes(iv);

        GCMParameterSpec parameterSpec =
                new GCMParameterSpec(
                        GCM_TAG_LENGTH,
                        iv
                );

        Cipher cipher =
                Cipher.getInstance("AES/GCM/NoPadding");

        cipher.init(
                Cipher.ENCRYPT_MODE,
                secretKey,
                parameterSpec
        );

        byte[] encryptedBytes =
                cipher.doFinal(plainText.getBytes());

        String encryptedText =
                Base64.getEncoder()
                        .encodeToString(encryptedBytes);

        System.out.println(encryptedText);
    }
}

Generating AES Key using Password

Instead of directly using passwords as AES keys, it is recommended to derive secure keys using PBKDF2. PBKDF2 applies hashing iterations and salt to generate strong cryptographic keys. This online PBKDF2 Hash generator tool can be used to generate PBKDF2 Hash.


import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

public class AESKeyGenerator {

    public static SecretKeySpec generateKey(
            String password
    ) throws Exception {

        byte[] salt = new byte[16];

        SecureRandom secureRandom =
                new SecureRandom();

        secureRandom.nextBytes(salt);

        PBEKeySpec spec =
                new PBEKeySpec(
                        password.toCharArray(),
                        salt,
                        65536,
                        256
                );

        SecretKeyFactory factory =
                SecretKeyFactory.getInstance(
                        "PBKDF2WithHmacSHA256"
                );

        byte[] key =
                factory.generateSecret(spec)
                        .getEncoded();

        return new SecretKeySpec(key, "AES");
    }
}

Security Concerns and Best Practices

While AES itself is highly secure, improper implementation can make the system vulnerable.

  • Never hardcode AES keys in source code
  • Always use random IVs
  • Do not reuse IV with the same key
  • Prefer AES/GCM over AES/CBC
  • Never use ECB mode for sensitive information
  • Store encryption keys securely using vaults or environment variables
  • Use PBKDF2 for password-based encryption
  • Always transmit encrypted data over HTTPS

Testing AES Encryption and Decryption


public class AESMain {

    public static void main(String[] args)
            throws Exception {

        String plainText = "password123";

        System.out.println(
                "Original Text: " + plainText
        );
    }
}

Frequently Asked Questions

Is AES better than RSA?

AES is much faster and used for bulk data encryption, while RSA is mainly used for secure key exchange.

Which AES mode is most secure?

AES/GCM is currently the recommended AES mode for modern applications.

Can AES-256 be cracked?

AES-256 is currently considered computationally infeasible to crack using brute force attacks.

Conclusion

AES is one of the most secure and widely used symmetric encryption algorithms available today. Java provides strong support for AES encryption through the Java Cryptography Architecture.

For modern applications, AES/GCM should be preferred over CBC mode because it provides authenticated encryption.Always use random IVs, secure key generation and proper key management practices while implementing AES encryption in Java.

In the next post we will be discussing about interoperability of AES between javascript and java

❤️ Liked this article?

If it saved you time, consider buying me a coffee to support future improvements.

About The Author

author-image
I write about cryptography, web security, and secure software development. Creator of practical crypto validation tools at Devglan.

References