Java > Java Security > Cryptography > AES, RSA, and other encryption algorithms
AES Encryption and Decryption Example
This code snippet demonstrates AES (Advanced Encryption Standard) encryption and decryption using Java's built-in security features. AES is a symmetric-key algorithm widely used for securing data due to its speed and strong security. This example shows how to generate a key, encrypt a string, and decrypt it back to its original form.
Concepts Behind the Snippet
AES is a block cipher, meaning it encrypts data in fixed-size blocks (128 bits for AES-128, which is commonly used). The encryption process involves several rounds of substitutions, permutations, and mixing operations, guided by a secret key. Decryption reverses these operations using the same key. The `javax.crypto` package provides classes for performing cryptographic operations, including AES. Key generation, encryption, and decryption are handled by different classes and methods within this package.
Key Generation
This section shows how to generate an AES secret key. `KeyGenerator.getInstance("AES")` creates a key generator for the AES algorithm. `keyGenerator.init(128)` initializes the key size to 128 bits. You can use 192 or 256 bits for stronger encryption, but this might require installing the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files depending on your Java environment. `keyGenerator.generateKey()` generates the actual key.
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
public class AESExample {
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128); // You can use 128, 192, or 256 bits
SecretKey secretKey = keyGenerator.generateKey();
return secretKey;
}
Encryption
This part demonstrates the encryption process. `Cipher.getInstance("AES")` creates a Cipher object for AES encryption. `cipher.init(Cipher.ENCRYPT_MODE, secretKey)` initializes the cipher to encryption mode using the generated secret key. `cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8))` encrypts the plaintext and returns the encrypted bytes. `Base64.getEncoder().encodeToString(encryptedBytes)` encodes the encrypted bytes into a Base64 string for easier storage and transmission.
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.security.NoSuchAlgorithmException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.BadPaddingException;
public class AESExample {
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128); // You can use 128, 192, or 256 bits
SecretKey secretKey = keyGenerator.generateKey();
return secretKey;
}
public static String encrypt(String plainText, SecretKey secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
Decryption
This section demonstrates the decryption process. `Cipher.getInstance("AES")` creates a Cipher object. `cipher.init(Cipher.DECRYPT_MODE, secretKey)` initializes the cipher to decryption mode using the same secret key used for encryption. `Base64.getDecoder().decode(encryptedText)` decodes the Base64 encoded ciphertext back into encrypted bytes. `cipher.doFinal(encryptedBytes)` decrypts the bytes, and `new String(decryptedBytes, StandardCharsets.UTF_8)` converts the decrypted bytes back into a String.
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.security.NoSuchAlgorithmException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.BadPaddingException;
public class AESExample {
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128); // You can use 128, 192, or 256 bits
SecretKey secretKey = keyGenerator.generateKey();
return secretKey;
}
public static String encrypt(String plainText, SecretKey secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
public static String decrypt(String encryptedText, SecretKey secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
Complete Example
This is the complete example bringing all components together. It generates a key, encrypts a plain text message, prints the encrypted text, decrypts it, and prints the decrypted text. The `main` method handles potential exceptions during the process.
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.security.NoSuchAlgorithmException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.BadPaddingException;
public class AESExample {
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128); // You can use 128, 192, or 256 bits
SecretKey secretKey = keyGenerator.generateKey();
return secretKey;
}
public static String encrypt(String plainText, SecretKey secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
public static String decrypt(String encryptedText, SecretKey secretKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
public static void main(String[] args) {
try {
SecretKey secretKey = generateKey();
String plainText = "This is a secret message.";
String encryptedText = encrypt(plainText, secretKey);
System.out.println("Encrypted Text: " + encryptedText);
String decryptedText = decrypt(encryptedText, secretKey);
System.out.println("Decrypted Text: " + decryptedText);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Real-Life Use Case
AES is commonly used for encrypting sensitive data stored in databases, configuration files, and network communications. For example, you might use AES to encrypt user passwords before storing them in a database or to protect sensitive data transmitted over an API.
Best Practices
Interview Tip
Be prepared to discuss the differences between symmetric and asymmetric encryption, the advantages and disadvantages of AES, and common security vulnerabilities related to cryptographic implementations (e.g., weak key generation, improper IV handling).
When to Use AES
Use AES when you need fast and strong symmetric-key encryption, especially when dealing with large amounts of data. It's suitable for encrypting data at rest (e.g., in databases) or in transit (e.g., network communications).
Memory Footprint
AES itself doesn't have a significant memory footprint. The primary memory usage comes from storing the key and the data being encrypted. The size of the data has a more substantial impact on memory consumption than the AES algorithm itself.
Alternatives
Alternatives to AES include other symmetric-key algorithms like DES (now considered weak), Triple DES (3DES, also considered less secure than AES), Blowfish, and Twofish. ChaCha20 is another modern stream cipher.
Pros
Cons
FAQ
-
What is the difference between symmetric and asymmetric encryption?
Symmetric encryption uses the same key for both encryption and decryption, while asymmetric encryption uses a pair of keys: a public key for encryption and a private key for decryption. Symmetric encryption is generally faster but requires secure key exchange. Asymmetric encryption is slower but simplifies key distribution. -
What is the Java Cryptography Extension (JCE)?
The JCE is a part of the Java Security API that provides a framework and implementations for cryptography, including encryption, decryption, key generation, and message authentication. It allows Java applications to perform various security-related tasks. -
Why is Base64 encoding used in the example?
Base64 encoding is used to convert the raw encrypted bytes (which may contain non-printable characters) into a string format that can be easily stored, transmitted, and displayed. It ensures that the encrypted data can be handled without issues in systems that are not designed to handle arbitrary binary data.