Chapter 4
86
Now we can use the cipher to encrypt the encoded form of the key:
// Encrypt the key
byte[] encryptedKeyBytes = cipher.doFinal(key.getEncoded());
In order to be able to decrypt the key, we need to have the salt. We'll write the salt that we generated to the
first 8 bytes of the file, and then we'll write the encrypted key and close the file.
// Write out the salt, and then the encrypted key bytes
FileOutputStream fos = new FileOutputStream(KEY_FILENAME);
fos.write(salt);
fos.write(encryptedKeyBytes);
fos.close();
}
Before we can do any file encryption or decryption, we'll need to have access to the key. We're going to
write a method called loadKey() that will load a key, with a password specified as an argument. This is
essentially the reverse of the createKey() method: we read in the salt, and the encrypted key bytes, and
then decrypt the key with a PBE cipher. We'll use javax.crypto.spec.SecretKeySpec to create a key
from the decrypted key bytes.
/**
* Loads a key from the filesystem
*/
private static Key loadKey(char[] password)
throws Exception
{
// Load the bytes from the encrypted key file.
FileInputStream fis = new FileInputStream(KEY_FILENAME);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i = 0;
while ((i=fis.read()) != -1) {
baos.write(i);
}
fis.close();
byte[] saltAndKeyBytes = baos.toByteArray();
baos.close();
// Get the salt, which is the first 8 bytes
byte[] salt = new byte[8];
System.arraycopy(saltAndKeyBytes,0,salt,0,8);
// get the encrypted key bytes
int length = saltAndKeyBytes.length - 8;
byte[] encryptedKeyBytes = new byte[length];
System.arraycopy(saltAndKeyBytes,8,encryptedKeyBytes,0,length);
// Create the PBE cipher
PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(
"PBEWithSHAAndTwofish-CBC");
SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, ITERATIONS);
Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");
cipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);