How to Encrypt and Decrypt Data In Java

  • Post last modified:August 19, 2022
  • Reading time:5 mins read
Photo by Markus Spiske on Unsplash

Introduction

  • Encryption and Decryption of Secret data is very common process in building any kind of application.
  • We often need to encrypt some kind of secret data/config value such as db-password, hashing token etc.
  • We can encrypt our data either using symmetric or asymmetric encryption. Usually when we talk about symmetric encryption algorithm we use AES and RSA for asymmetric encryption. In Some cases we also use hybrid approach.
  • AES is faster and can encrypt large data sizes while RSA is suitable for encrypting smaller data sizes.
  • This article mainly discusses about Symmetric encryption with AES.

BouncyCastle Dependency

  • BouncyCastle is a great and popular library that supports all the necessary features that we need to encrypt and decrypt the data.
  • You can get latest version from here.
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.64</version>
        </dependency>

Encrypt Data

  • Let’s use this library to encrypt byte array which we passed as argument. We have also passed Secret Key and IvParameterSpec.
  • Our Cipher is using AES in CBC mode with PKC padding.
    public static byte[] encrypt(byte[] input, Key secretKey, IvParameterSpec ivParameterSpec) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException { ;
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE,secretKey, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(input);
        return encrypted;
    }
  • Secret Key is something that we would need to protect our input byte array. so that only someone who has access to this secret key can decrypt it. Secret key can be of 128 bits, 192 bits or 256 bits , we are using 192 bits here.
    public static Key getSecretKey() throws NoSuchAlgorithmException {
        KeyGenerator aes = KeyGenerator.getInstance("AES");
        aes.init(192);
        Key secretKey = aes.generateKey();
        System.out.println("encoded : "+secretKey.getEncoded());
        return secretKey;
    }
  • But what is IvParameterSpec ? IV stands for Initialization Vector, which is kind of random bytes that introduces randomness in the input bytes to avoid detecting pattern. It is used by AES in CBC mode. AES encryption can be done in 5 modes.
   public static IvParameterSpec getIvParameterSpec() throws NoSuchAlgorithmException {
        SecureRandom secureRandom =  SecureRandom.getInstance("SHA1PRNG");
        byte[] random = new byte[16];
        secureRandom.nextBytes(random);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(random);
        return ivParameterSpec;
    }
  • Now let’s execute client code to run encryption process.
  • As we can see in the output , our data is not readable at all.
  • Now let’s decrypt and make sure we get our input data back.

Decrypt Data

  • First and foremost lets write decrypt method , it might look like similar to encrypt method but there are some differences.
  • Of course we have to pass same secret key and iv vector that we used for encryption. Other than that we again use Cipher object of AES algorithm with CBC mode and PKCS5 padding.
public static byte[] decrypt(byte[] encryptedInput, Key secretKey, IvParameterSpec ivParameterSpec) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE,secretKey, ivParameterSpec);
        byte[] decryptedInput = cipher.doFinal(encryptedInput);
        System.out.println("decrypted input bytes: "+ decryptedInput);

        return decryptedInput;
    }
  • As we can see in we can read our original text back and decryption process is successful.

Entire Code

  • Below is the entire code that we used for demonstration above.

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.io.IOException;
import java.security.*;

public class EncryptDecrypt {

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, IOException {
        String text= "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of \"de Finibus Bonorum et Malorum\" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, \"Lorem ipsum dolor sit amet..\", comes from a line in section 1.10.32.The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from \"de Finibus Bonorum et Malorum\" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.";
        Key secretKey = getSecretKey();
        IvParameterSpec ivParameterSpec = getIvParameterSpec();
        byte[] encrypted = encrypt(text.getBytes(), secretKey, ivParameterSpec);
        System.out.println("encrypted .. " + new String(encrypted));

        byte[] decrypted = decrypt(encrypted, secretKey, ivParameterSpec);
        System.out.println("decrypted .. " + new String(decrypted));
    }


    public static byte[] encrypt(byte[] input, Key secretKey, IvParameterSpec ivParameterSpec) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException { ;
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE,secretKey, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(input);
        return encrypted;
    }

    public static byte[] decrypt(byte[] encryptedInput, Key secretKey, IvParameterSpec ivParameterSpec) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE,secretKey, ivParameterSpec);
        byte[] decryptedInput = cipher.doFinal(encryptedInput);
        System.out.println("decrypted input bytes: "+ decryptedInput);

        return decryptedInput;
    }

    public static Key getSecretKey() throws NoSuchAlgorithmException {
        KeyGenerator aes = KeyGenerator.getInstance("AES");
        aes.init(192);
        Key secretKey = aes.generateKey();
        System.out.println("encoded : "+secretKey.getEncoded());
        return secretKey;
    }

    public static IvParameterSpec getIvParameterSpec() throws NoSuchAlgorithmException {
        SecureRandom secureRandom =  SecureRandom.getInstance("SHA1PRNG");
        byte[] random = new byte[16];
        secureRandom.nextBytes(random);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(random);
        return ivParameterSpec;
    

Conclusion

  • In this article we discuss how we can encrypt and decrypt sensitive data by using AES encryption which is symmetric encryption algorithm.
  • We saw that Bouncy Castle library indeed very helpful in achieving our goal.
  • We can extend this idea to encrypt and decrypt entire file as next step which we will cover in upcoming blogs.

Leave a Reply