File Encryption and Decryption using PBE

Password-Based Encryption (PBE) derives an encryption key from a password. In order to make the task of getting from password to key very time-consuming for an attacker, most PBE implementations (as the one shown below) will mix in a random number, known as a salt, to create the key.

PBE algorithm supported in j2se1.4 (Other algorithms are supported in later versions of the SunJCE and other providers)




FileEncryptor.java

01: /**
02:  * This demonstrates password-based encryption (PBE) using the
03:  * DES algorithm.  As mentioned before, DES is not very secure,
04:  * but the SDK version used for this example does not support
05:  * other (stronger) PBE algorithms
06:  *
07:  * The text file "clear.txt" will be read, encrypted and written back
08:  * as "clear.txt.des".
09:  *
10:  * I've done all the "hardcoding" of the file names and password for
11:  * simplicity of discussion.
12:  *
13:  */
14: 
15: import java.io.*;
16: import java.security.*;
17: import javax.crypto.*;
18: import javax.crypto.spec.*;
19: import java.util.*;
20: 
21: public class FileEncryptor
22: { 23: private static String filename; 24: private static String password; 25: private static FileInputStream inFile; 26: private static FileOutputStream outFile; 27: 28: /** 29: * Note: As with the pervious example, all kinds of exceptions 30: * can be thrown in main. See the API documentation for each 31: * method used. 32: */ 33: 34: public static void main(String[] args) throws Exception
35: { 36: 37: // File to encrypt. It does not have to be a text file! 38: 39: filename = "clear.txt"; 40: 41: // Password must be at least 8 characters (bytes) long 42: 43: String password = "super_secret"; 44: 45: inFile = new FileInputStream(filename); 46: outFile = new FileOutputStream(filename + ".des"); 47: 48: // Use PBEKeySpec to create a key based on a password. 49: // The password is passed as a character array 50: 51: PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray()); 52: SecretKeyFactory keyFactory = 53: SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 54: SecretKey passwordKey = keyFactory.generateSecret(keySpec); 55: 56: // PBE = hashing + symmetric encryption. A 64 bit random 57: // number (the salt) is added to the password and hashed 58: // using a Message Digest Algorithm (MD5 in this example.). 59: // The number of times the password is hashed is determined 60: // by the interation count. Adding a random number and 61: // hashing multiple times enlarges the key space. 62: 63: byte[] salt = new byte[8]; 64: Random rnd = new Random(); 65: rnd.nextBytes(salt); 66: int iterations = 100; 67: 68: //Create the parameter spec for this salt and interation count 69: 70: PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, iterations); 71: 72: // Create the cipher and initialize it for encryption. 73: 74: Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES"); 75: cipher.init(Cipher.ENCRYPT_MODE, passwordKey, parameterSpec); 76: 77: // Need to write the salt to the (encrypted) file. The 78: // salt is needed when reconstructing the key for decryption. 79: 80: outFile.write(salt); 81: 82: // Read the file and encrypt its bytes. 83: 84: byte[] input = new byte[64]; 85: int bytesRead; 86: while ((bytesRead = inFile.read(input)) != -1) 87: { 88: byte[] output = cipher.update(input, 0, bytesRead); 89: if (output != null) outFile.write(output); 90: } 91: 92: byte[] output = cipher.doFinal(); 93: if (output != null) outFile.write(output); 94: 95: inFile.close(); 96: outFile.flush(); 97: outFile.close(); 98: 99: } 100: }







FileDecryptor.java
01: /**
02:  * Simple modification of "FileEncrypor.java".  The
03:  * previously encrypted "clear.txt.des" is read, decrypted
04:  * and written back as "clear.txt.dcr"
05:  */
06: 
07: import java.io.*;
08: import java.security.*;
09: import javax.crypto.*;
10: import javax.crypto.spec.*;
11: import java.util.*;
12: 
13: public class FileDecryptor
14: { 15: private static String filename; 16: private static String password; 17: private static FileInputStream inFile; 18: private static FileOutputStream outFile; 19: 20: /** 21: * Note: All kinds of exceptions can be thrown in main. 22: * See the API documentation for each method used. 23: */ 24: 25: public static void main(String[] args) throws Exception
26: { 27: 28: // File to decrypt. 29: 30: filename = "clear.txt.des"; 31: 32: String password = "super_secret_password"; 33: 34: inFile = new FileInputStream(filename); 35: outFile = new FileOutputStream(filename + ".dcr"); 36: 37: PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray()); 38: SecretKeyFactory keyFactory = 39: SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 40: SecretKey passwordKey = keyFactory.generateSecret(keySpec); 41: 42: // Read in the previouly stored salt and set the iteration count. 43: 44: byte[] salt = new byte[8]; 45: inFile.read(salt); 46: int iterations = 100; 47: 48: PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, iterations); 49: 50: // Create the cipher and initialize it for decryption. 51: 52: Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES"); 53: cipher.init(Cipher.DECRYPT_MODE, passwordKey, parameterSpec); 54: 55: 56: byte[] input = new byte[64]; 57: int bytesRead; 58: while ((bytesRead = inFile.read(input)) != -1) 59: { 60: byte[] output = cipher.update(input, 0, bytesRead); 61: if (output != null) 62: outFile.write(output); 63: } 64: 65: byte[] output = cipher.doFinal(); 66: if (output != null) 67: outFile.write(output); 68: 69: inFile.close(); 70: outFile.flush(); 71: outFile.close(); 72: } 73: }