Password Based Encryption Using AES

In a recent engagement, I needed to encrypt an object then write it to disk. I wanted to use Advanced Encryption Standard (AES), but unfortunately Java does not provide a way to use password based encryption with AES. Bouncy Castle does provide the required libraries that will allow us to use password based encryption with AES.

In this scenario, I wanted the user to provide the pass phrase.

import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.SealedObject;
import javax.crypto.Cipher;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.security.Security;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

class seal {

    static String algorithm = "PBEWITHSHA256AND128BITAES-CBC-BC";
    static char[] passPherase = "secretpass".toCharArray();
    static byte[] salt = "a9v5n38s".getBytes();
    static String secretData = "Very Secret Data!!";

In real world you should generate the salt randomly. We need to create a key spec based on the user input then create a cipher for encrypting or decrypting the data.

Encrypting the data,

static SealedObject encrypt(String data) throws Exception{
    PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt,20);
    PBEKeySpec pbeKeySpec = new PBEKeySpec(passPherase);
    SecretKeyFactory secretKeyFactory = 
        SecretKeyFactory.getInstance(algorithm);
    SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);

    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(Cipher.ENCRYPT_MODE,secretKey,pbeParamSpec);

    return new SealedObject(data,cipher);
}

Decrypting the data back again,

static String decrypt(SealedObject sealedObject) throws Exception{
    PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt,20);
    PBEKeySpec pbeKeySpec = new PBEKeySpec(passPherase);
    SecretKeyFactory secretKeyFactory = 
        SecretKeyFactory.getInstance(algorithm);
    SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);

    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(Cipher.DECRYPT_MODE,secretKey,pbeParamSpec);
    return (String)sealedObject.getObject(cipher);
}

Using a SealedObject you can basically encrypt any object you want, and serialize it to a file.

    public static void main(String[] args) {
        try{
            Security.addProvider(new BouncyCastleProvider());
            SealedObject encryptedString = encrypt(secretData);
            String decryptedString = decrypt(encryptedString);
            System.out.println(decryptedString);
        }catch( Exception e ) { 
            System.out.println(e.toString());
        }
    }
}