Chapter 4
84
Creating and Using an IV
To create the IV with those random bytes, just construct a new instance of IVParameterSpec:
IVParameterSpec iv = new IVParameterSpec(randomBytes);
Now we can use the IV to initialize a cipher, like so:
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
And we're ready to use that cipher in a cipher output stream.
Keeping Track of the IV
It's important to realize that that same IV needs to be used to initialize a cipher for decrypting as well. It's a
lot like the salt used with password-based encryption. Just like the salt, it doesn't need to be hidden like the
key does. We can safely expose it along with the ciphertext that we've encrypted.
A common way to handle this is to place the initialization vector at the beginning of the ciphertext. That's
exactly what we're going to do in the next example, which will encrypt and decrypt a file, and also keep a
symmetric key stored in the filesystem encrypted with a password.
CipherStream Example FileEncryptor
We're going to write a program that encrypts and decrypts files using cipher streams. We'll use AES
(sometimes known as Rijndael) as the algorithm to encrypt the file. In order to decrypt it, we'll need to use
the same key, so we'll store the key encrypted in a file with password-based encryption.
We'll offer three options when running our little application: key creation, file encryption, and file
decryption. Each of those options will cause a different method to get called: createKey(), encrypt(),
or decrypt().
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
/**
* FileEncryptor.java
*
* This class encrypts and decrypts a file using CipherStreams
* and a 256-bit Rijndael key stored in the filesystem.
*/
public class FileEncryptor
{
private static String KEY_FILENAME="rijndaelkey.bin";
private static int ITERATIONS=1000;