Unlocking the Secrets of Java Cryptography Extensions: The Basics
Listing 3.2 shows the reverse process of grabbing the encrypted key from the file and decrypting the data file.
package com.dlt.developer.crypto; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; import javax.crypto.*;import java.security.Key; import java.io.*; /** * @author David Thurmond * An example of decrypting a text file using Data Encryption * Standard encryption. */ public class DecryptFileExample { public static void main(String[] args) throws Exception { // First, create the encryption key... System.out.println("Reading key from file..."); BufferedInputStream in = new BufferedInputStream(new FileInputStream ("encrypted_key.txt")); byte[] keyBytes = new byte[in.available()]; in.read(keyBytes); System.out.println("Bytes read=" + keyBytes.length); in.close(); SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "DES"); // Now, create the cipher object with appropriate parameters... System.out.println("Decrypting file using DES/ECB/PKCS5Padding"); Cipher desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); desCipher.init(Cipher.DECRYPT_MODE, skeySpec); System.out.println("Reading encrypted file and decrypting..."); BufferedOutputStream outData = new BufferedOutputStream(new FileOutputStream ("decrypted_data.txt")); BufferedInputStream inData = new BufferedInputStream(new FileInputStream ("encrypted_data.txt")); while (inData.available() > 0) { // Read the next chunk of bytes... byte[] encryptedBytes = new byte[inData.available()]; inData.read(encryptedBytes); // Now, decrypt them and write them to the encrypted file... byte[] cleartextBytes = desCipher.update(encryptedBytes); outData.write(cleartextBytes, 0, cleartextBytes.length); } // while outData.write(desCipher.doFinal()); inData.close(); outData.flush(); outData.close(); System.out.println("Done!"); } // main }
Listing 3.2: DecryptFileExample.java
In Listing 3.2, the file encrypted_key.txt is read, and the key's raw bytes are retrieved and loaded into a key spec for use by the Cipher object:
FileInputStream("encrypted_key.txt")); byte[] keyBytes = new byte[in.available()]; ...Create the cipher object with the right decription... ...parameters and key spec... SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "DES"); Cipher desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); desCipher.init(Cipher.DECRYPT_MODE, skeySpec);
The remainder of the process is just the reverse of the previous example. Data is read from encrypted_data.txt, is decrypted by using the Cipher.update() and Cipher.doFinal() methods just as before, and is written out to decrypted_data.txt. Note that without the final invocation of doFinal(), a chunk of data would be missing at the end of the decrypted file. By examining decrypted_data.txt and cleartext.txt, the input to the file encryption program, you will see that the files are identical.
Password-Based Encryption
Although password-based encryption is not considered to be as secure as the secret-key encryption method shown above, it is probably the most commonly used method of encrypting and decrypting data. Listing 4.1 shows how to encrypt a file using a predetermined password, "mybigsecret". The password algorithm in this example uses a predetermined source of randomness, called a salt, and an iteration counter to determine a block size for the encryption, to make cracking the password a bit more difficult. In a real-world example, the salt and iteration counter might be determined based on some pre-determined agreement between the encrypting and decrypting parties, rather than being a hard-coded value.
package com.dlt.developer.crypto; import javax.crypto.*;import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.*; import java.io.*; /** * @author David Thurmond * An example of encrypting a text file using password-based * encryption. */ public class EncryptFilePasswordExample { public static void main(String[] args) throws Exception { PBEKeySpec pbeKeySpec; PBEParameterSpec pbeParamSpec; SecretKeyFactory keyFac; // Salt byte[] salt = {(byte)0x9f, (byte)0x33, (byte)0x4e, (byte)0xfe, (byte)0xd4, (byte)0xee, (byte)0x12, (byte)0x54}; // Iteration count int count = 17; // Create PBE parameter set pbeParamSpec = new PBEParameterSpec(salt, count); char[] password = {'m', 'y', 'b', 'i', 'g', 's', 'e', 'c', 'r', 'e', 't'}; pbeKeySpec = new PBEKeySpec(password); keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec); // Create PBE Cipher Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); // Initialize PBE Cipher with key and parameters pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec); System.out.println("Encrypting file using DES/ECB/PKCS5Padding"); System.out.println("Reading cleartext file and encrypting..."); BufferedOutputStream outData = new BufferedOutputStream(new FileOutputStream ("password_encrypted_data.txt")); BufferedInputStream in = new BufferedInputStream(new FileInputStream ("cleartext.txt")); while (in.available() > 0) { // Read the next chunk of bytes... byte[] cleartextBytes = new byte[in.available()]; in.read(cleartextBytes); // Now, encrypt them and write them to the encrypted file... byte[] encryptedBytes = pbeCipher .update(cleartextBytes); outData.write(encryptedBytes, 0, encryptedBytes.length); } // while // Take care of any pending padding operations outData.write(pbeCipher .doFinal()); in.close(); outData.flush(); outData.close(); System.out.println("Done!"); } // main }
Listing 4.1: EncryptFilePasswordExample.java
Page 5 of 6
This article was originally published on October 15, 2008