Table of Contents
Introduction
AES stands for advanced encryption standard and is the most commonly used symmetric algorithm to encrypt sensitive data and can be used in both software and hardware.
The AES algorithm is symmetric, meaning that it uses only one key for encryption and decryption, and due to this reason, the key must be shared between the sender and the receiver.
The standard has three key sizes, which include 128
, 192
, and 256
and each of the ciphers encrypts and decrypts data in blocks of 128
bits.
The key sizes perform 10
, 12
, and 14
rounds on the data for 128
, 192
, and 256
respectively, making 256
the stronger algorithm among them.
By default, the java implementation of the AES algorithm uses 128
key size, and in this tutorial, we will implement the algorithm to encrypt and decrypt a message.
To generate a key that will be used for both encryption and decryption of our message, we will use the getInstance()
method of the KeyGenerator
class in java and pass string AES
to the method.
The getInstance()
method throws a NoSuchAlgorithmException
if no provider supports a KeyGeneratorSpi
of the specified algorithm and a NullPointerException
if the algorithm provided is null
.
The KeyGenerator
will create an instance of the AES algorithm that we will use to generate a key using the generateKey()
method of the class.
This class generates a symmetric secret key, and once a key has been generated, the same object can be used to create other keys.
Use the encodeToString()
method of Base64.Encoder
to view the generated string of the key by logging the result to the console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.encryption; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.NoSuchAlgorithmException; import java.util.Base64; public class AESEncryption { public static void main(String[] args) throws NoSuchAlgorithmException { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); SecretKey secretKey = keyGenerator.generateKey(); String secretKeyString = Base64.getEncoder().encodeToString(secretKey.getEncoded()); System.out.println("generated key = "+secretKeyString); } } |
Output:
Further reading:
Encrypt a random text
To encrypt the message, create a Cipher
object and use the getInstance()
with parameter AES/CBC/PKCS5Padding
as the transformation to create an instance of the algorithm.
The transformation has a mode and padding, and in our case, we will use CBC
mode, which stands for cipher block chaining, and PKCS5Padding
as the padding.
The default mode is ECB
, but since it does not support multiple blocks of data, we will use CBC
, which is a mode of operation for a block cipher.
The cipher block chaining mode uses an initialization vector, also known as IV
, which is an input to the cryptographic algorithm used to provide the initial state and requires to be unique.
The padding is introduced to the algorithm so that if the string to be encrypted is not an exact multiple of the block size, then padding is done before encrypting by adding a padding string.
Since we will provide an initialization vector to the init()
method of the Cipher
create IvParameterSpec
class and pass the key bytes to its constructor, which be used as the initialization vector.
Call the init()
method and pass Cipher.ENCRYPT_MODE
, SecretKey
and finally the IvParameterSpec
object created.
Create a random text and call the doFinal()
method of the Cipher
and pass the message bytes to the method to perform encryption.
The doFinal()
method returns an array of bytes containing the encrypted message, and we can convert the bytes to string using the encodeToString()
method and log its content to the console to verify that the encryption was successful.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package com.encryption; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; public class AESEncryption { public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); SecretKey secretKey = keyGenerator.generateKey(); String secretKeyString = Base64.getEncoder().encodeToString(secretKey.getEncoded()); System.out.println("generated key = "+secretKeyString); //Encrypt Hello world message Cipher encryptionCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] InitVectorBytes = keyGenerator.generateKey().getEncoded(); IvParameterSpec parameterSpec = new IvParameterSpec(InitVectorBytes); encryptionCipher.init(Cipher.ENCRYPT_MODE,secretKey,parameterSpec); String message = "Hello world"; byte[] encryptedMessageBytes = encryptionCipher.doFinal(message.getBytes()); String encryptedMessage = Base64.getEncoder().encodeToString(encryptedMessageBytes); System.out.println("Encrypted message = "+encryptedMessage); } } |
Output:
Encrypted message = /PLOtvd+J/7KLGOdPaVZtg==
Decrypt the encrypted text
Since we already have an initialization vector and a secret key, we need to create a new Cipher
object as we did previously and use the AES/CBC/PKCS5Padding
transformation in the getInstance()
method.
The only parameter of the init()
method that changes is the mode as we are performing a decryption operation, and we need to pass Cipher.DECRYPT_MODE
as the first parameter of the method.
Convert the bytes returned by the doFinal()
method to a string by passing the returned result to the String()
constructor and log to the console to verify that the decrypted message was our original message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
package org.arpit.java2blog; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; public class AESEncryption { public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); SecretKey secretKey = keyGenerator.generateKey(); String secretKeyString = Base64.getEncoder().encodeToString(secretKey.getEncoded()); System.out.println("generated key = "+secretKeyString); //Encrypt Hello world message Cipher encryptionCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] InitVectorBytes = keyGenerator.generateKey().getEncoded(); IvParameterSpec parameterSpec = new IvParameterSpec(InitVectorBytes); encryptionCipher.init(Cipher.ENCRYPT_MODE,secretKey,parameterSpec); String message = "Hello world"; byte[] encryptedMessageBytes = encryptionCipher.doFinal(message.getBytes()); String encryptedMessage = Base64.getEncoder().encodeToString(encryptedMessageBytes); System.out.println("Encrypted message = "+encryptedMessage); //Decrypt the encrypted message Cipher decryptionCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); decryptionCipher.init(Cipher.DECRYPT_MODE,secretKey,parameterSpec); byte[] decryptedMessageBytes = decryptionCipher.doFinal(encryptedMessageBytes); String decryptedMessage = new String(decryptedMessageBytes); System.out.println("decrypted message ="+decryptedMessage); } } |
Output:
Encrypted message = /PLOtvd+J/7KLGOdPaVZtg==
decrypted message =Hello world
Conclusion
In this tutorial, you have learned how to encrypt and decrypt a random text using the symmetric AES algorithm with a single key generated using the KeyGenerator
class in java. You have also learned how to provide an initialization vector for the CBC
mode of the transformation by using the IvParameterSpec
provided by the Java API. In the next tutorial, you will learn how to encrypt and decrypt a message using AES 256
, which is more resistant to attacks compared to AES 128
and AES 192
.