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
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