Cryptography, Java

SHA512 Hash in Java

For one of my projects recently, I got a chance to look into SHA512 Hashing in Java. The purpose of Hashing is to take any arbitrary input and produce a fix length output string. The Hashing is mainly done to ensure that the data has not been tampered with during its transmission. Also, Hash is one way function, that is, it is not possible to go from the output to the input.

Hashing in Java

I recommend using Apache Commons Codec library for Hashing in Java. Here is the step by step process for generating SHA512 Hash in Java:

1. Download the jar from the Apache Commons website. Add the commons-codec-x.x jar file to the class path of your application.
OR
If using Maven, add the dependency in pom.xml.

		
 		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>1.6</version>
		</dependency>
 

2. Generate the SHA512 hash. Here is the sample code:



	private static String data = "<Name><FirstName>Devesh</FirstName><LastName>Sharma</LastName></Name>";
	private static String salt = "ThisIsMySaltForAddedSecurity";
	
	public static String calculateHash(String data, String salt) {
		return DigestUtils.sha512Hex(data + salt);
	}
	
	public static void main(String args[]) {
		System.out.println("SHA512 Hash: " +calculateHash(data, salt));
	}
	
 
Cryptography, Java

AES Encryption in Java

Advanced Encryption Standard (AES) is an encryption algorithm for securing sensitive information. It was adopted by National Institute of Standards and Technology (NIST) in 2001 to replace Data Encryption Standard (DES). It is a symmetric algorithm, that is same key is used for encryption and decryption.

Here is the code to implement AES in Java:


	private static String Encrypt(String plainText, String key) throws 
		NoSuchAlgorithmException, 
		NoSuchPaddingException, 
		InvalidKeyException, 
		IllegalBlockSizeException, 
		BadPaddingException, 
		UnsupportedEncodingException 
	{
		SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
		
		// Instantiate the cipher
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, keySpec);
		
		byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
		
		return new Base64().encodeAsString(encryptedTextBytes);
	}
	
	private static String Decrypt(String encryptedText, String key) throws 
		NoSuchAlgorithmException, 
		NoSuchPaddingException, 
		InvalidKeyException, 
		IllegalBlockSizeException, 
		BadPaddingException, 
		UnsupportedEncodingException  
	{
		
		SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

		// Instantiate the cipher
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.DECRYPT_MODE, keySpec);
		
		byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
		byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
		
		return new String(decryptedTextBytes);
	}
	
	public static void main(String[] args) {
		
		String plainText = "Hello World";
		String key = "770A8A65DA156D24EE2A093277530142";
		
		System.out.println("Plain Text: " +plainText);
		
		// Encryption
		String encryptedText = null;
		try {
			encryptedText = Encrypt(plainText, key);
			System.out.println("Encrypted Text: " +encryptedText);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		// Decryption
		try {
			String decryptedText = Decrypt(encryptedText, key);
			System.out.println("Decrypted Text: " +decryptedText);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

Output:
Plain Text: Hello World
Encrypted Text: 4HYnfGGXcJSQn0GtssoOQQ==
Decrypted Text: Hello World

Please note that in the Encrypt() method, I am encoding the encrypted text and decoding the encrypted text again in the Decrypt() method. If you need any help with Base64 Encoding/Decoding in Java, please refer this post.

Note: If you are doing 256-bit encryption, you need to download and install Unlimited Strength Jurisdiction Policy Files. Please refer this post for more details.

If you need help with 256-bit AES Password Based Encryption in Java, please refer this post.

Cryptography, Java

256-bit AES Password Based Encryption in Java

Recently I got a chance to look into 256-bit AES Password Based Encryption in Java. While writing the program, I got stuck quite a lot since there ain’t much resources available over the web. Therefore, I am posting my program here thinking it will be helpful to you all.


    private static final String password = &lt;your_password&gt;;
	private static String initializationVector = &lt;your_iv&gt;;
	private static String salt = &lt;your_salt&gt;;
	private static String plainText = &lt;your_plainText&gt;;
	private static int pswdIterations = &lt;your_iterations&gt;;
	private static int keySize = &lt;your_keysize&gt;;

    public static String encrypt(String plainText) throws 
		NoSuchAlgorithmException, 
		InvalidKeySpecException, 
		NoSuchPaddingException, 
		InvalidParameterSpecException, 
		IllegalBlockSizeException, 
		BadPaddingException, 
		UnsupportedEncodingException, 
		InvalidKeyException, 
		InvalidAlgorithmParameterException 
	{	
		byte[] saltBytes = salt.getBytes("UTF-8");
		byte[] ivBytes = initializationVector.getBytes("UTF-8");

		// Derive the key, given password and salt.
		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");
		
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(ivBytes));

		byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
		return new Base64().encodeAsString(encryptedTextBytes);
	}

	public static String decrypt(String encryptedText) throws 
		NoSuchAlgorithmException, 
		InvalidKeySpecException, 
		NoSuchPaddingException, 
		InvalidKeyException, 
		InvalidAlgorithmParameterException,
		UnsupportedEncodingException
	{
		byte[] saltBytes = salt.getBytes("UTF-8");
		byte[] ivBytes = initializationVector.getBytes("UTF-8");
		byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
		
		// Derive the key, given password and salt.
		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, given derived key and initialization vector.
		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);
	}

Note: If you are doing 256-bit encryption, you need to download and install Unlimited Strength Jurisdiction Policy Files. Please refer this post for more details.

Please note that in the Encrypt() method, I am encoding the encrypted text and decoding the encrypted text again in the Decrypt() method. If you need any help with Base64 Encoding/Decoding in Java, please refer this post.

Please refer this post for details about AES Encryption in Java.

Cryptography, Java

Fixing java.security.InvalidKeyException: Illegal key size exception

If you are performing 256-bit AES encryption in Java, it is likely that you must be very familiar with this exception. Nothing to panic though. This exception is not your fault and you are not doing anything wrong. This exception is thrown because of a restriction imposed by default JDK. On a default JDK installation, AES is limited to 128 bit key size. In order to perform 256-bit AES encryption, you will need to download and install Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files. Here are the steps to fix java.security.InvalidKeyException: Illegal key size exception:

1. Go to Oracle’s website and search for ‘Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files’.

2. Depending upon the Java version installed on your machine, download the zip file and extract it on your drive.

3. From the extracted folder, copy local_policy.jar and US_export_policy.jar files.

4. Go to your_java_installation_directory/jre/lib/security and paste the copied files. These files will already be there, you just need to copy and replace.

5. Refresh your project and you will not encounter this exception anymore.(fingers crossed) 🙂