Java File Encryption Decryption using AES Password Based Encryption (PBE)

Last modified on November 19th, 2014 by Joe.

This Java tutorial is to learn about using AES password based encryption (PBE) to encrypt and decrypt a file. In the previous tutorial we saw about using TripleDES PBE to encrypt and decrypt a file. AES is more advanced and secure than TripleDES.

In this tutorial we will have simple text file with plain text. This can be any type of file. We will encrypt this into another file with an extension .des For encryption we will use a plain text password, then an iv which is used to initialize the cipher and a salt which is used for encoding.

security

All these three, password, iv and salt should be passed on to the recipient in a secure mechanism and not along with the encrypted file. The recipient will use the plain text password, iv (to initialize the cypher) and the salt to decrypt the file. In our example tutorial, we will again write back the decrypted content to a plain text file. So once the process is over the input text file and the output text file content should match.

File Encryption

Following Java code is to encrypt a file. To test this, put a file named “plainfile.txt” in project root.

AESFileEncryption.java

package com.javapapers.java.security;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class AESFileEncryption {
	public static void main(String[] args) throws Exception {

		// file to be encrypted
		FileInputStream inFile = new FileInputStream("plainfile.txt");

		// encrypted file
		FileOutputStream outFile = new FileOutputStream("encryptedfile.des");

		// password to encrypt the file
		String password = "javapapers";

		// password, iv and salt should be transferred to the other end
		// in a secure manner

		// salt is used for encoding
		// writing it to a file
		// salt should be transferred to the recipient securely
		// for decryption
		byte[] salt = new byte[8];
		SecureRandom secureRandom = new SecureRandom();
		secureRandom.nextBytes(salt);
		FileOutputStream saltOutFile = new FileOutputStream("salt.enc");
		saltOutFile.write(salt);
		saltOutFile.close();

		SecretKeyFactory factory = SecretKeyFactory
				.getInstance("PBKDF2WithHmacSHA1");
		KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536,
				256);
		SecretKey secretKey = factory.generateSecret(keySpec);
		SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

		//
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, secret);
		AlgorithmParameters params = cipher.getParameters();

		// iv adds randomness to the text and just makes the mechanism more
		// secure
		// used while initializing the cipher
		// file to store the iv
		FileOutputStream ivOutFile = new FileOutputStream("iv.enc");
		byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
		ivOutFile.write(iv);
		ivOutFile.close();

		//file encryption
		byte[] input = new byte[64];
		int bytesRead;

		while ((bytesRead = inFile.read(input)) != -1) {
			byte[] output = cipher.update(input, 0, bytesRead);
			if (output != null)
				outFile.write(output);
		}

		byte[] output = cipher.doFinal();
		if (output != null)
			outFile.write(output);

		inFile.close();
		outFile.flush();
		outFile.close();

		System.out.println("File Encrypted.");
		
	}

}

File Decryption

Following Java code is to decrypt the file. Run the above program prior to running this.

AESFileDecryption.java

package com.javapapers.java.security;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class AESFileDecryption {
	public static void main(String[] args) throws Exception {

		String password = "javapapers";

		// reading the salt
		// user should have secure mechanism to transfer the
		// salt, iv and password to the recipient
		FileInputStream saltFis = new FileInputStream("salt.enc");
		byte[] salt = new byte[8];
		saltFis.read(salt);
		saltFis.close();

		// reading the iv
		FileInputStream ivFis = new FileInputStream("iv.enc");
		byte[] iv = new byte[16];
		ivFis.read(iv);
		ivFis.close();

		SecretKeyFactory factory = SecretKeyFactory
				.getInstance("PBKDF2WithHmacSHA1");
		KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536,
				256);
		SecretKey tmp = factory.generateSecret(keySpec);
		SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

		// file decryption
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
		FileInputStream fis = new FileInputStream("encryptedfile.des");
		FileOutputStream fos = new FileOutputStream("plainfile_decrypted.txt");
		byte[] in = new byte[64];
		int read;
		while ((read = fis.read(in)) != -1) {
			byte[] output = cipher.update(in, 0, read);
			if (output != null)
				fos.write(output);
		}

		byte[] output = cipher.doFinal();
		if (output != null)
			fos.write(output);
		fis.close();
		fos.flush();
		fos.close();
		System.out.println("File Decrypted.");
	}
}

Comments on "Java File Encryption Decryption using AES Password Based Encryption (PBE)"

  1. Anil Sharma says:

    Good explanation…

  2. Peter says:

    Your IV and salt can be stored(embedded) in the file and it not be a security concern.

  3. Nav says:

    Getting below error while running this program.
    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 com.javapapers.java.AESFileEncryption.main(AESFileEncryption.java:51)

  4. nivethika says:

    I want to store encrypted bytes in ms sql db and later decrypt it with same key

  5. sanket says:

    Is there any implementation part of UMARAM algorithm

  6. Anonymous says:

    Its showing me the same errors that Nav is getting:

    Exception in thread “main” java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011)
    at javax.crypto.Cipher.implInit(Cipher.java:786)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
    at javax.crypto.Cipher.init(Cipher.java:1213)
    at javax.crypto.Cipher.init(Cipher.java:1153)
    at aesencrypt.main(aesencrypt.java:37)

  7. pp says:

    sir
    iam facing the same errors too
    can you give explanation

  8. Dragan Bjedov says:

    If you get the java.security.InvalidKeyException you have to install the Java Cryptography Extension (JCE) unlimited strength jurisdiction policy files:

    Java 6 link: http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

    Java 7 link: http://www.oracle.com/technetwork/java/embedded/embedded-se/downloads/jce-7-download-432124.html

    Java 8 link: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

    If you use JDK copy unzipped jar files into folder: ${jdk.home}/jre/lib/security/
    If you use JRE copy unzipped jar files into folder: ${jre.home}/lib/security/

    Note that ${jdk.home} and ${jre.home} point to installation directory which depend on your OS.

    Hope it helps.

    Greetings,
    Dragan Bjedov

  9. Narendra says:

    By default java uses 128 Bit encryption. So change 256 to 126 in both codes. And it runs fine. :) I am not qa java expert. ;)

  10. Grace says:

    Yeah the same error occurred when i tried running the code too. But the key size 128 instead of 256 resolved it.

  11. Yohannes M Alemu says:

    changing the 256 to 128 solves the problem in both cases. Thanks!

  12. Michael Kangethe says:

    Thanks Man this is exactly what I have been searching for. Kudos n Big up

  13. Robin says:

    Getting the following exception during decryption. Please help.

    Exception in thread “main” javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
    at javax.crypto.Cipher.doFinal(Cipher.java:1970)
    at encryption.AESFileDecryption.main(AESFileDecryption.java:53)

  14. Ron Wates says:

    Thanks, very useful and interesting.
    Thanks too, Dragan, for your advice on how to overcome the exception error

  15. Jon says:

    This is an AES encryption program, so why does it save the text to a .des file and not a .aes one?

Comments are closed for "Java File Encryption Decryption using AES Password Based Encryption (PBE)".