Key Storage
One of the primary difficulties in establishing good security through cryptography is key storage. In order
for a key to be useful, it must be persistent. But by keeping the key around, we risk it being compromised.
Let's imagine that we want to encrypt some personal files on our computer so that no one can read them.
We create a 448-bit Blowfish key and encrypt our files with it, thinking that our files will now be secure. But
if someone were to get into our machine, they'd be able to read the key and decrypt the files. In order for
the files to be safe, we have to protect the key that we used to encrypt those files.
One way to protect the key is to keep it on a floppy disk and only use it when a file needs to be encrypted
or decrypted. Another possibility is to use a smart card, which is a tiny computer, the size of a credit card.
Its purpose is to store keys and perform cryptographic operations directly on the card, without ever
exposing the key. Smart cards and floppy disks are somewhat inconvenient, however, because they require
some external physical medium to store the key.
Let's return to the idea of keeping the key on our computer in the filesystem. Anyone with read access
could decrypt our files. One way to work around this is to encrypt the keys using password-based
encryption, using a good strong password that no one is likely to guess. This is what Netscape
Communicator does when storing private certificates for encrypted e-mail.
Storing the keys in the filesystem reduces their security, even if they're encrypted: they're now protected by
PBE, which is almost always going to be less strong than the keys the key store contains. It's a good idea to
protect any key storage mechanism in additional ways, like setting file permissions and physically securing
the box the keys are on. Let's discuss encrypting keys for storage and transmission.
Key Wrapping and Unwrapping
JCE 1.2.1, which some providers implement, provides an easy means of encrypting a key. As we mentioned
earlier, javax.crypto.Cipher has a method wrap(), which takes a key as an argument and returns a
byte array, which is the encrypted value of the key. We need to initialize the cipher in WRAP_MODE instead
of ENCRYPT_MODE. If we had a PBE cipher, just like in the previous example, we could wrap a secret key
like so:
cipher.init(Cipher.WRAP_MODE, passwordKey, paramSpec);
byte[] encryptedKeyBytes = cipher.wrap(secretKey);
To decrypt the key, we initialize it in UNWRAP_MODE, and then call cipher.unwrap() with the algorithm
of the wrapped key and the type SECRET_KEY, because that's the type of key that was wrapped:
cipher.init(Cipher.UNWRAP_MODE, passwordKey, paramSpec);
Key key = cipher.unwrap(encryptedKeyBytes, "Blowfish", Cipher.SECRET_KEY);
Key Encryption without Wrapping
If we don't have wrap() and unwrap() in our provider's cipher implementation, then we'll need to
perform the encryption and decryption using java.security.Key's getEncoded() method and
javax.crypto.SecretKeySpec.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.