Page 4 of 5
Cryptography may sound intimidating, sparking visions of complex algorithms and bit-level mathematics, but the Java security and cryptography packages make crypto tasks relatively simple to apply.
You'll need to install the Java Cryptography Extension (JCE) and a provider (the SunJCE provider included in the JCE will do fine) to execute the following example. Pointers to that can be found in Resources.
I wrote a simple utility, CryptoUtil.java, to encrypt and decrypt files. I then wrote MetadataSecureSample.java, a new class based on Listing 7 above that uses CryptoUtil to decrypt the XML file before it is parsed. I also reencrypt the file in a finally block since I don't want it sitting around in plain text after I'm done with it and want to be sure it is reencrypted even
if an Exception is thrown during the parsing process.
Though woefully inadequate for enterprise deployment, a simple secret key will serve to illustrate the concept. The first
time it's used, CryptoUtil will generate such a key. A sample key is also available in the article source code.
You'll need to encrypt the MetadataSecureSample.xml file before using it in that example. Invoke CryptoUtil.encryptFile() from the command line, pass MetadataSecureSample.xml as an argument, and it creates MetadataSecureSample.xml.enc.
The init() method undergoes a few changes, too, as noted in Listing 8.
Listing 8. The init() method with decryption and encryption
private void init() {
File encryptedFile = null;
File decryptedFile = null;
try {
// figure out the name of the props file
String propsfilename = getClass().getName() + ".xml";
// decrypt the file
encryptedFile = new File(propsfilename + CryptoUtil.FILE_EXTENSION);
decryptedFile = CryptoUtil.decryptFile(encryptedFile);
// ... CODE SNIPPED ... //
// set last modified
lastMod = encryptedFile.lastModified();
} catch (Exception e) {
throw new RuntimeException("UNABLE TO INITIALIZE, EXITING...");
}
finally {
// re-encrypt the file after using it
try {
if (decryptedFile != null)
encryptedFile = CryptoUtil.encryptFile(decryptedFile);
} catch (Exception cre) {
System.err.println("UNABLE TO RE-ENCRYPT FILE!");
}
}
}
Cryptographic operations cost significant overhead, and you wouldn't want to incur that cost often. Since the code reads the properties at timed intervals rather than upon request, that should not cause problems, but it is something to consider when using any sort of cryptography. As in any design decision, you must weigh the costs and gains carefully with regard to your specific application.
How do you figure out which properties are best left outside the application and which are best left in the source code? While that decision is largely subjective, below are a few suggestions.
The following kinds of details should find a home in the application metadata:
You can consider leaving the following sorts of details in the application code: