Tutorial #76: Implement AES-256 encryption/decryption using Java

The Advanced Encryption Standard (AES) is an encryption algorithm designed for securing electronic data established by the U.S National Institute of Standards and Technology (NIST) in 2001. AES is based on Rijndael cipher developed by cryptographers Joan Daemen and Vincent Rijmen. AES carries out its operation on a 4×4 column major order matrix of bytes. The key size used for an AES cipher specifies the number of repetitions of transformation rounds that convert the input, called the plaintext, into the final output, called the ciphertext.

AES is currently available in three key sizes: 128, 192 and 256 bits.The design and strength of all key lengths of the AES algorithm are sufficient to protect classified information up to the SECRET level. As far as security is concerned, AES is considered to be more secure than its predecessor DES. For more information please refer this link.

In this tutorial, we will learn how to implement AES-256 encryption using Java. We will use the Java Cryptography Extension for encryption, decryption, key generation etc. Before proceeding make sure you have downloaded the jurisdiction policy for your respective Java platform from over here. Place the policy files in the {JDK_HOME}\jre\lib\security folder.

Pre-requisites: Eclipse IDE, JDK 1.6 or above

Step 1: Create Java project

Open Eclipse IDE and create a new Java console application project called TestAESExample.

Step 2: Create Java class

Create a new Java class called AESDemo with package name com.example and add the following code!

AESDemo.java

import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class AESDemo {

	private static final String password = "test";
	private static String salt;
	private static int pswdIterations = 65536  ;
	private static int keySize = 256;
	private byte[] ivBytes;

	public String encrypt(String plainText) throws Exception {   
		
		//get salt
		salt = generateSalt();		
		byte[] saltBytes = salt.getBytes("UTF-8");
		
		// Derive the key
		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
		PBEKeySpec spec = new PBEKeySpec(
				password.toCharArray(), 
				saltBytes, 
				pswdIterations, 
				keySize
				);

		SecretKey secretKey = factory.generateSecret(spec);
		SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

		//encrypt the message
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, secret);
		AlgorithmParameters params = cipher.getParameters();
		ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
		byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
		return new Base64().encodeAsString(encryptedTextBytes);
	}

	@SuppressWarnings("static-access")
	public String decrypt(String encryptedText) throws Exception {

		byte[] saltBytes = salt.getBytes("UTF-8");
		byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);

		// Derive the key
		SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
		PBEKeySpec spec = new PBEKeySpec(
				password.toCharArray(), 
				saltBytes, 
				pswdIterations, 
				keySize
				);

		SecretKey secretKey = factory.generateSecret(spec);
		SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

		// Decrypt the message
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
	

		byte[] decryptedTextBytes = null;
		try {
			decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}

		return new String(decryptedTextBytes);
	}

	public String generateSalt() {
		SecureRandom random = new SecureRandom();
		byte bytes[] = new byte[20];
		random.nextBytes(bytes);
		String s = new String(bytes);
		return s;
	}
}

Note: In the above example, salt is generated randomly by the generateSalt() method. To implement Base64 encoding and decoding, you need to download the commons-codec library from over here.

Finally, lets add our main class Test.java as follows!

Test.java

package com.example;

public class Test {
	
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub

		AESDemo d = new AESDemo();
			
		System.out.println("Encrypted string:" + d.encrypt("Hello"));			
		String encryptedText = d.encrypt("Hello");
		System.out.println("Decrypted string:" + d.decrypt(encryptedText));			

	}
}

Save all changes. Make sure no errors are present. Run the application. Depending upon the plainText provided you will get the encrypted data.

output

Reference: Performance of encryption algorithms

Karan Balkar About Karan Balkar
self proclaimed extraterrestrial fandroid, computer engineer, amateur gamer and die hard punk rock fan!

34 thoughts on “Tutorial #76: Implement AES-256 encryption/decryption using Java

  1. Exception in thread “main” java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1021)
    at javax.crypto.Cipher.implInit(Cipher.java:796)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:859)
    at javax.crypto.Cipher.init(Cipher.java:1229)
    at javax.crypto.Cipher.init(Cipher.java:1166)
    at viz_3_aes_rsa.AESDemo.encrypt(AESDemo.java:41)

  2. i am getting same exception even after placing policy in security folder..

    Exception in thread “main” java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1021)
    at javax.crypto.Cipher.implInit(Cipher.java:796)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:859)
    at javax.crypto.Cipher.init(Cipher.java:1229)
    at javax.crypto.Cipher.init(Cipher.java:1166)
    at viz_3_aes_rsa.AESDemo.encrypt(AESDemo.java:41)

  3. i want to encrypt a file using rsa algorithm and decrypt the file using the same rsa key in 128 bit using java and store the file in the database.pls canu tel how to do?

  4. Encryption key is given by client and also the key which is used in the encryption.

    Now, I wanted to decrypt using the same key which used in encryption.

    Could you please help me on how to decrypt ?? Any sample code please share ?

  5. I am using the same code in my application. while decryption of the multiple entries of table from database , it is returning …

    javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
    at javax.crypto.Cipher.doFinal(Cipher.java:2121)
    at com.encryption.AESDemo.decrypt(AESDemo.java:75)
    at com.encryption.FromAES256.doGet(FromAES256.java:84)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
    java.lang.NullPointerException
    at java.lang.String.(Unknown Source)
    at com.encryption.AESDemo.decrypt(AESDemo.java:83)
    at com.encryption.FromAES256.doGet(FromAES256.java:84)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

    please give the solution…

  6. Dear Sir
    i have run that code and i am facing the following problems
    at first the Method encodeASstring is undefined in base64 while i found it in the method list of it
    second the method decodebase64 is not applicable for string
    and then i found the errors attached
    return new Base64().encodeAsString(encryptedTextBytes);
    }

    @SuppressWarnings(“static-access”)
    public String decrypt(String encryptedText) throws Exception {

    byte[] saltBytes = salt.getBytes(“UTF-8”);
    byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);

    errors

    Exception in thread “main” java.lang.Error: Unresolved compilation problems:
    The method encodeAsString(byte[]) is undefined for the type Base64
    Syntax error on token “encryptedText”, VariableDeclaratorId expected after this token
    encryptedText cannot be resolved to a variable

    at com.example.AESDemo.(AESDemo.java:47)
    at com.example.Test.main(Test.java:8)

    could you help me please?
    Also , could you support finding a code for ECC ?

    thanks and BRs

  7. the code below doesnt work, does anyone know why?

    AESDemo d = new AESDemo();
    String encryptedText = d.encrypt(“Hello”);
    String encryptedText1 = d.encrypt(“Hello”);
    String encryptedText2 = d.encrypt(“Hello”);
    String encryptedText3 = d.encrypt(“Hello”);
    String encryptedText4 = d.encrypt(“Hello”);
    String encryptedText5 = d.encrypt(“Hello”);

    System.out.println(“Encrypted string:” +encryptedText);
    System.out.println(“Encrypted string:” +encryptedText1);
    System.out.println(“Encrypted string:” +encryptedText2);
    System.out.println(“Encrypted string:” +encryptedText3);
    System.out.println(“Encrypted string:” +encryptedText4);
    System.out.println(“Encrypted string:” +encryptedText5);
    System.out.println(“Decrypted string:” + d.decrypt(encryptedText5));
    System.out.println(“Decrypted string:” + d.decrypt(encryptedText1));
    System.out.println(“Decrypted string:” + d.decrypt(encryptedText2));
    System.out.println(“Decrypted string:” + d.decrypt(encryptedText3));
    System.out.println(“Decrypted string:” + d.decrypt(encryptedText4));
    System.out.println(“Decrypted string:” + d.decrypt(encryptedText));

    • I am facing the same problem. If I encrypt more than one string, the decrypt cannot return all the original strings like your test case “Text” to “Text4” except the last one “Text5”, it returns the correct string. Did you got a solution for your problem? Please share with me if you do.

      Here is my test cases and issue (I am using the code without any change):

      Encrypt string “It is a sunny day” and decrypt it just like your AESDemo() in your lesson 76. Works perfect. The println() for decrypted string shows “It is a sunny day”.
      Encrypt string one “It is a sunny day” and Encrypt another string tow “tomorrow will be hot”. Decrypt string one and decrypt string two, the println() for string one are some unknown character. However, the string two is decrypted correctly. I am using 1.7 Java JRE. If anyone has solution, please share some light.

      Thanks,
      Amy

  8. Hai Karan, thx for your code tutorial aes encryption in this site, i have a question, what this code include encpryption and decryption with CBC Mode ?because I use CBC mode for my task. Please tell me and if you have the code CBC mode please send to my email or give me link if code in website..
    thx before Karan..

    • Hi,

      There are basically two different operating modes available while performing AES encryption i.e ECB or CBC. You can find more information over here. It’s upto you which one you want to use while encryption.

      • okey thank’s karan, I use CBC mode in android in my task, I search any website and article its nothing work in android, I using lib. bouncy castle but not work, it’s have a error..
        would you like give me a solution for CBC code for android ? I confuse for this..hahaha
        thank’s karan…

      • yes, I use CBC mode for my task, but I implement this code for java android, I search any article and tutorial in website but no one is work..
        do you give me an article or tutorial encryption CBC mode with lib. or no in android version..
        thank’s full karan..

  9. I cannot decrypt an encrypted String previous generated.

    javax.crypto.BadPaddingException: Given final block not properly padded

  10. Thanks Karan for the code. I used your code without any change. They work perfectly when I encrypt one string and decrypt it right away in my test code. However, if I encrypt two string first, I noted that I can only decrypt the second encrypted string correctly but the first encrypted string could not be decrypted right; it gives me some strange characters. My use cases is like this:

    1) encrypt all passwords, say, I have 10 of them in the system and save the encrypted 10 strings in db
    2) decrypt the one that user ask later.

    Please give me some pointers on this issue I am facing.

    Thanks,
    Amy

    • Hi Amy,

      Thanks for posting your question. In your case, you need to encrypt all passwords, say 10 and store them in the built-in SQLite database. Once stored, you can create a function that will query the database and fetch the encrypted string based on what the user asks. Pass that encrypted string to the decrypt method to get the password back.

  11. Hi Karan,

    I post one question regarding decrypt issue yesterday. I did not see it got posted in here. I am not sure if it got sent. Here is my question again:

    Hi Karan,

    Thank you for posting the encryption and decryption code. I used it as is and tested some scenarios. I am facing some issues but could not figure out why. Here is the description of the test cases and issue:

    1) Encrypt string “It is a sunny day” and decrypt it just like your AESDemo() in your lesson 76. Works perfect. The println() for decrypted string shows “It is a sunny day”.
    2) Encrypt string one “It is a sunny day” and Encrypt another string tow “tomorrow will be hot”. Decrypt string one and decrypt string two, the println() for string one are some unknown character. However, the string two is decrypted correctly.
    I would like to know if you see issue like that? I am using 1.7 Java JRE.

    Thanks,
    Amy

  12. Hi Sir, I am new to java…I’m getting error over this line
    ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
    error is: The method getIV() is undefined for the type T
    Please help me through

    • It was a small mistake..when I modified as
      ivBytes = ((Cipher) params.getParameterSpec(IvParameterSpec.class)).getIV();

      It got resolved…:-)

  13. I’m getting error when i execute the code:
    \Exception in thread “main” java.lang.Error: Unresolved compilation problems:
    Unhandled exception type Exception
    Unhandled exception type Exception
    Unhandled exception type Exception

    Can anyone help me..Please

Leave a Reply

Your email address will not be published. Required fields are marked *