AES 256 Encryption and Decryption in Java using password based approach.
AES Overview:
The symmetric-key block cipher is a crucial component of encryption
systems. It indicates that encryption and decryption are accomplished using
the same key. One popular symmetric-key encryption scheme is called Advanced
Encryption Standard (AES).
Six modes of operation exist for the AES algorithm:
- Electronic Code Book (ECB)
- Block Chaining Cipher (CBC)
- Circuit Feedback (CFB)
- Feedback from Output
- Galois/Counter Mode (GCM)
- CTR (Counter)
In This Post we will be working with CBC mode of encryption.
Short
intro about CBC mode:
To strengthen the encryption, CBC mode makes
use of an Initialization Vector (IV). First, CBC combines the IV and plaintext
block xor. It then encrypts the outcome to the block of ciphertext. The
encryption result is used in the following block to xor with the plaintext
block until the last block.
Encryption cannot be parallelized in
this mode, but decryption can. Data padding is also necessary.
Before diving into the code for Encryption and Decryption using
AES, lets understand what we will be doing here.
We will be using a
data in form of a string to encrypt and a password (32 chars) as key for
encryption. IV vector will be a random 16 byte array that we would be using in
this case.
The Key size of AES algorithm can be 128,192 256 bits.
Here we are using 32 chars string so the size will be 256 bits.
Key Size Calculation:
1 char=1 Byte
1
Byte=8 bits
32 Chars=32 bytes
Therefore 32*8=256
bits.
The Initialization Vector (IV).
IV is an
equivalent-sized pseudo-random variable to the encrypted block. A random IV
can be created using the SecureRandom class.
AES 256 Encryption Code in Java Password-Based:
public static String encrypt(
String dataToBeEncrypted,
String encryptionKey
)
throws NoSuchPaddingException,
NoSuchAlgorithmException,
InvalidAlgorithmParameterException,
InvalidKeyException,
IllegalBlockSizeException,
BadPaddingException
{
//Encryption Key
String key=encryptionKey;
Cipher cipher= Cipher.getInstance("AES/CBC/PKCS5Padding");
//generate IV for encryption, Same IV must be used for decryption
byte[] iv=new byte[16];
new SecureRandom().nextBytes(iv);
IvParameterSpec ivParameterSpec=
new IvParameterSpec(iv);
//generate KeySpec using custom encryption key
byte[] keyByte=key.getBytes();
SecretKeySpec secretKeySpec=
new SecretKeySpec(keyByte,"AES");
//Initialize the Cipher and encrypt the data using doFinal method.
cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,ivParameterSpec);
byte[] encryptedDataInBytes =
cipher.doFinal(dataToBeEncrypted.getBytes());
/*Data is now encrypted but as we need to use same IV for decrypting
we need to store it somewhere.
we can store it anywhere but as IV will be random for each encryption
its maintainence is difficult.
So we will pad the iv with the encrypted data and store it.
As we only know IV is at what index it cannot be broken easily.
to make it more random we will add some random byte in beginning
*/
//generate some random bytes for padding in the beginning
byte[] randomBytesForPadding=new byte[4];
new SecureRandom().nextBytes(randomBytesForPadding);
//This Byte array will have final computed data that we will store at our end.
byte[] ivAndEncryptedDataCombinedInBytes =
new byte[
randomBytesForPadding.length
+ iv.length
+ encryptedDataInBytes.length
];
//Using System.arrayCopy we will merge the 3 byte arrays
System.arraycopy(
randomBytesForPadding,
0,
ivAndEncryptedDataCombinedInBytes,
0,
randomBytesForPadding.length
);
System.arraycopy(
iv,
0,
ivAndEncryptedDataCombinedInBytes,
randomBytesForPadding.length,
iv.length
);
System.arraycopy(
encryptedDataInBytes,
0,
ivAndEncryptedDataCombinedInBytes,
iv.length+randomBytesForPadding.length,
encryptedDataInBytes.length
);
//Finally return the encrypted data into Base64 format for storing.
return Base64.
getEncoder().
encodeToString(ivAndEncryptedDataCombinedInBytes);
}
AES Decryption code in java password based:
public static String decrypt(
String data,
String encryptionKey
)
throws NoSuchPaddingException,
NoSuchAlgorithmException,
InvalidAlgorithmParameterException,
InvalidKeyException,
IllegalBlockSizeException,
BadPaddingException
{
//Encryption Key
String key=encryptionKey;
//We have encoded the encrypted data before storing it,
// so we need to first decode it before doing any operations.
byte[] decodedByte=Base64.
getDecoder().
decode(data);
/*
* We have added 4 random bytes to our final byte array,
* we need to skip those bytes.
* Our IV is from 4th index and
* as IV length is 16 bytes the last index will be 20
* So to get the IV used for encryption
* we can slice the byte array from index 4:20
* */
byte[] iv=Arrays.
copyOfRange(decodedByte,4,20);
/*
* Our encrypted data was merged after the IV
* thus the encrypted bytes will be from index 20 to end of array
* */
byte[] encryptedData=Arrays.
copyOfRange(
decodedByte,
20,
decodedByte.length
);
//generate the KeySpec
byte[] keyByte=key.getBytes();
SecretKeySpec secretKeySpec=
new SecretKeySpec(keyByte,"AES");
/*
* Once we have the IV , encrypted data, Key.
* Now we can initialize the Cipher for Decrypting
* */
Cipher cipher= Cipher.
getInstance("AES/CBC/PKCS5Padding");
cipher.init(
Cipher.DECRYPT_MODE,
secretKeySpec,
new IvParameterSpec(iv)
);
//use the doFinal method to decrypt the data ,
// as the output will be a byte array we will convert it into the String and return.
return new String(cipher.doFinal(encryptedData));
}
Main Method:
public static void main(String[] args)
throws NoSuchPaddingException,
NoSuchAlgorithmException,
InvalidAlgorithmParameterException,
IllegalBlockSizeException,
BadPaddingException,
InvalidKeyException
{
String encryptionKey = "Get@Solutions@KODESRC#werty54321";
String dataToEncrypt = "Welcome to kodeSrc!";
String encryptedData = encrypt(dataToEncrypt, encryptionKey);
System.out.println("Encrypted data: " + encryptedData);
String decryptedData = decrypt(encryptedData, encryptionKey);
System.out.println("Decrypted Data: " + decryptedData);
}
Output:
Feel Free to reach out !
Please Let me Know, If you have any doubts.
Please Let me Know, If you have any doubts.