Friday, 19 October 2012

Encryption and Decryption using AES Algorithm in JAVA

Encryption and Decryption

Encryption is the process of converting plaintext to cipher-text (had to understand) by applying mathematical transformations.  These transformations are known as encryption algorithms and require an encryption key.

Decryption is the reverse process of getting back the original data from the cipher-text using a decryption key.  In Symmetric cryptology- The encryption key and the decryption key could be the same as in symmetric or secret key cryptography, The key can different as in asymmetric or public key cryptography. 

Types of cryptography

Symmetric cryptography uses the same secret (private) key to encrypt and decrypt its data
Symmetric requires that the secret key be known by the party encrypting the data and the party decrypting the data.

Asymmetric Cryptography uses both a public and private key.  Asymmetric allows for distribution of your public key to anyone. Using the key they can encrypt the data they want to send securely and then it can only be decoded by the person having the private key

Symmetric Algorithms
Common  Algorithms

DES (Data Encryption Standard)Old Crypto algorithm. 64 Bits, 56 are effectively used, easy to break.3DES - derived from DES, works by cascading 3 instances of DES. This is slow
3DESderived from DES, works by cascading 3 instances of DES. This is slow
AES (Advanced Encryption Standard)Successor of DES. Accepts 128, 192, 256 bits. When in doubt use AES. This is supported after JDK 1.4 onwards




Symmetric key encryption/decryption uses a secret key during the process.   A String encrypted with a secret key cannot be decrypted using another secret key.   This is more effective if both the parties keep the key secret.

In our example we will be using a AES Algorithm with AES - 128 , AES has a fixed block size of 128 bits. We will be using a password based secret key. In the below table you will see the code comparison  of how encryption and decryption is easily done


Encryption CodeDecryption Code
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");  SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);

 String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
return encryptedString;
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
return decryptedString;
Below is an example standalone java class which can generate a encrypted string, and decrypt a given string.  The secret-key used for encryption/decryption is "thisIsASecretKey"- converted to bytes.  The encrypted string at last encoded using Base64.encodeBase64String that gives an ascii string.  During the decryption, the ascii base64encoded string  is decoded using Base64.decodeBase64 and then decrypted using cipher.doFinal().
 

How to run the program

Encryption

java cipher.CipherUtils -encrypt abcd

String to Encrypt : abcd
Encrypted : 0ualDZ4X/FUDjmrqLWROyw==


Decryption

java cipher.CipherUtils -decrypt 0ualDZ4X/FUDjmrqLWROyw==

String To Decrypt : 0ualDZ4X/FUDjmrqLWROyw==
Decrypted : abcd


Code

package cipher;


import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.codec.binary.Base64;

public class CipherUtils
{

    private static byte[] key = {
            0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79
    };//"thisIsASecretKey";

    public static String encrypt(String strToEncrypt)
    {
        try
        {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
            return encryptedString;
        }
        catch (Exception e)
        {
           e.printStackTrace();
        }
        return null;

    }

    public static String decrypt(String strToDecrypt)
    {
        try
        {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
            return decryptedString;
        }
        catch (Exception e)
        {
          e.printStackTrace();

        }
        return null;
    }


    public static void main(String args[])
    {

        CommandLineParser parser = new PosixParser();
        Options options = new Options();
        Option help = new Option("help", "Display help");
        Option encrypt = new Option("encrypt", true, " - string to encrypt");
        Option decrypt = new Option("decrypt", true, " - string to decrypt");
        options.addOption(help);
        options.addOption(encrypt);
        options.addOption(decrypt);
        try
        {
            CommandLine cmd = parser.parse(options, args);
            if (cmd.hasOption("encrypt"))
            {
                final String strToEncrypt = cmd.getOptionValue("encrypt");
                final String encryptedStr = CipherUtils.encrypt(strToEncrypt.trim());
                System.out.println("String to Encrypt : " + strToEncrypt);
                System.out.println("Encrypted : " + encryptedStr);
            }
            else if (cmd.hasOption("decrypt"))
            {
                final String strToDecrypt = cmd.getOptionValue("decrypt");
                final String decryptedStr = CipherUtils.decrypt(strToDecrypt.trim());
                System.out.println("String To Decrypt : " + strToDecrypt);
                System.out.println("Decrypted : " + decryptedStr);
            }
            else
            {
                HelpFormatter formatter = new HelpFormatter();
                formatter.printHelp("[-h] [-encrypt ]", options);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

    }
}

Dependencies: 

Required: commons-cli 1.2 and commons-codec 1.7

Eclipse Maven project to run this

https://www.dropbox.com/s/rg8tfz1mf592b92/cipher-project.zip




40 comments:

  1. Nice tutorial...helpful :)

    ReplyDelete
  2. thanks you so much ,you opened my furture...@@
    This code needed include the library is: Common-codec-1.7.jar
    thank again!

    ReplyDelete
    Replies
    1. where we have to open that .jar file actually iam new to this.
      thanks in advance.

      Delete
    2. Downloaded Library

      org.apache.common-codec-1.9.jar
      org.apache.commons.cli -1.2.jar
      org.apache.commons.logging 1.1.3.jar

      Delete
  3. Hi
    Thank you so much for your code it was very helpfull
    I would like to know how did how convert Sting in to byte like this
    \\\\\\\\\\\\\\\\
    private static byte[] key = {
    0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79
    };
    ////////////////
    because I try many ways but I get different result
    I will be glad if you show me the method you use

    Best
    Salim Hussein

    ReplyDelete
    Replies
    1. it is just the hex number of the character's ascii value.

      "thisIsASecretKey"; represents the above byte[]

      Refer to http://www.asciitable.com/ and check the hex value of the character's ascii value .You will have clarity on how this is converted.

      Delete
  4. thanks for your helpful code. could you please post the code for password protected key.my requirement is like i need to decrypt a file by using key and password using rsa algorithm.
    thanks in advance

    ReplyDelete
  5. hi thanks for the code. Working great.

    ReplyDelete
  6. thanks for the nice explanation.

    ReplyDelete
  7. Nice explanation.Good work.This is a good Article.Keep it up

    ReplyDelete
  8. hi, how can we change this algorithm to AES 256?
    please help me

    ReplyDelete
  9. hi sri..really very nice explanation....Impressive..

    ReplyDelete
  10. I have one question...is there a way of detecting weather data is coming from the source who actually have the key so that if not u just discard the incoming that data and pay no attention to it

    ReplyDelete
  11. hi Sryvidhya,

    Thanks for your code, but I have a question. Why must we you Base64 library in AES algorithm, is it necessary?

    ReplyDelete
  12. This comment has been removed by a blog administrator.

    ReplyDelete
  13. This comment has been removed by the author.

    ReplyDelete
  14. This comment has been removed by a blog administrator.

    ReplyDelete
  15. hi mam while i am trying to execute this code i am getting error saying java.lang.ExceptionInInitializerError.i am executing this code in netbeans ide.it is showing error mark in import org.apache.commons......showing red mark on org

    please do help .i need it very urgent .thanks in advance

    ReplyDelete
  16. package javaapplication1;

    import java.security.MessageDigest;
    import java.security.SecureRandom;
    import java.util.Scanner;

    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;

    public class ende {
    public static void main(String[] args) throws Exception {
    String keyString = "averylongtext!@$@#$#@$#*&(*&}{23432432432dsfsdf";
    String input = "";
    System.out.println("Enter your name:-" );
    Scanner s = new Scanner(System.in);
    input = s.next();
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    byte[] iv = new byte[cipher.getBlockSize()];
    new SecureRandom().nextBytes(iv);
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.update(keyString.getBytes());
    byte[] key = new byte[16];
    System.arraycopy(digest.digest(), 0, key, 0, key.length);
    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
    byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8"));
    System.out.println("encrypted: " + new String(encrypted));
    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
    byte[] decrypted = cipher.doFinal(encrypted);
    System.out.println("decrypted: " + new String(decrypted, "UTF-8"));
    }
    }




    TRY THIS.....

    ReplyDelete
    Replies
    1. This a also very good example throgh this we can make the key dynamin and can do AES 256 encryption. Great code

      Delete
  17. package index;

    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    import java.util.Scanner;

    public class ende {

    public static void main(String args[]) {

    try {
    String urname="";
    Scanner s = new Scanner(System.in);
    urname= s.next();

    String name = "";

    String encodedname = URLEncoder.encode(name, "UTF-8");

    System.out.println("Encoded URL " +encodedname );

    String decodedname = URLDecoder.decode(name, "UTF-8");

    System.out.println("Decoded URL " + decodedname);

    } catch (UnsupportedEncodingException e) {

    System.err.println(e);

    }
    }
    }


    This is also working.................

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  18. This comment has been removed by the author.

    ReplyDelete
  19. Hi,
    I executed the above code using the command prompt by saving the code in a .java text file with name CipherUtils.java
    But I got several errors on compilation itself, like

    CipherUtils.java:6: error: package org.apache.commons.cli does not exist
    import org.apache.commons.cli.CommandLine;
    ^
    CipherUtils.java:7: error: package org.apache.commons.cli does not exist
    import org.apache.commons.cli.CommandLineParser;
    ^
    CipherUtils.java:8: error: package org.apache.commons.cli does not exist
    import org.apache.commons.cli.HelpFormatter;

    and many more errors.
    I have jdk1.7.0_07. Have i done it wrongly?? Please help..

    -harsha

    ReplyDelete
    Replies
    1. U must to download the apache library and add it in youe project ..

      download it from this link: http://commons.apache.org/proper/commons-codec/download_codec.cgi?Preferred=http%3A%2F%2Fapache.mirrors.hoobly.com%2F

      Delete
  20. This will help for how to use Eliptic Curve Cryptography Sign/verify http://javaconceptzz.blogspot.com/2013/08/java-eliptic-curve-cryptography.html

    ReplyDelete
  21. I am getting error at two places in above code [ final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
    final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));]
    saying no method found encodeBase64String and decodeBase64(String) cannot invoke.. Please help me out.. I am using all the libraries suggested in the above posts..

    ReplyDelete
    Replies
    1. Updated the above code, attached a eclipse project, that is working. Please take a look

      Delete
  22. hi it does not show the proper output.
    it show me output like this.
    usage: [-h] [-encrypt ]
    -decrypt - string to decrypt
    -encrypt - string to encrypt
    -help Display help

    ReplyDelete
    Replies
    1. you have to run the file in windows cmd prompt

      Delete
  23. Srividhya ,I want to run file in java eclipse console,what changes are required.

    ReplyDelete
  24. Hi.
    Do you know if I can use this example to transfer a file encrypted from a virtual machine to another virtual machine?

    ReplyDelete
  25. Thank! Helped a lot! but with this one works perfectly! its vary easy to use check on
    encoder decoder online

    ReplyDelete
  26. Hi,

    Please help me in resolving the issue i am facing. I am using the same code for encrypting and decrypting the password using a random generated key. This key is transmitted over a web service call and i am storing in a singleton class for a desktop application. For multiple logins i am getting "Given final block not properly padded" error.
    Please help me resolving this issue.
    Code:
    public String decryptForDataBasePassword( char[] encryptedTextChar ) {

    Cipher cipher;
    String encryptedString = null;
    String text = new String( encryptedTextChar );
    // byte[] encryptText = null;
    byte[] raw;

    SecretKeySpec skeySpec;
    try {
    cipher = Cipher.getInstance( "AES" );
    raw = Base64.decodeBase64( secretKey );
    skeySpec = new SecretKeySpec( raw, "AES" );
    cipher.init( Cipher.DECRYPT_MODE, skeySpec );
    encryptedString = new String( cipher.doFinal( Base64.decodeBase64( text ) ) );
    }
    catch( Exception e ) {
    Logger.getLogger( "Error in encrypting the password using key " + e.getMessage() );
    GlobalUtils.displayErrorMessage( "Error in decrypting the password using key " + e.getMessage() );
    }
    return encryptedString;
    }

    ReplyDelete
    Replies
    1. I have tried it only with a standalone app. However that should not make any difference. I think there should be some problem when you are passing the key back to decrypt.

      I did a little googling and found this http://stackoverflow.com/questions/8049872/given-final-block-not-properly-padded

      But I would suggest you to add some logging to verify if the encrypt key password is the same as you get back from we services.

      If you still have problems. Send me a working code I will try to help you out, send me an email to Srividhya.umashanker at gmail

      Delete
    2. Thanks for the reply.. I have mailed you. Please let me know if you need more information.

      Delete
  27. Hi, Is there any utility or tools available for encrypting the jar file?

    ReplyDelete
  28. Is it possible to encrypt a JAVA JAR file?

    ReplyDelete
  29. Hi
    Thanks for code. its working great.
    I have one question same code is working fine in java but i need same code for c# language. can you please provide it if you have ..

    ReplyDelete