Symmetric Encryption 91 When constructing the sealed object, we need to use a fully initialized cipher. When decrypting, we can use either a cipher or just the key, and the sealed object will remember the settings for the cipher used to encrypt the object. Let's try an example of sealing an object with a DESede key. This example doesn't really do anything interesting externally, but rather simply expresses the syntax of using a SealedObject to seal a String object: import java.io.*; import javax.crypto.*; import java.security.*; public class SealedObjectExample { public static void main (String[] args) throws Exception { String creditCard = "1234567890"; KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede"); System.out.println("Creating a key."); Key key = keyGenerator.generateKey(); Cipher cipher = Cipher.getInstance("DESede"); cipher.init(Cipher.ENCRYPT_MODE, key); System.out.println("Encrypting the object."); SealedObject so = new SealedObject(creditCard, cipher); System.out.println("Unencrypting the object."); String unencryptedCreditCard = (String)so.getObject(key); System.out.println("Credit card number: "+unencryptedCreditCard); } } There is a bug, err, feature in the JDK1.2 that prevents extensions from using the class loader to create classes that are neither standard objects nor extensions. This means that if we create a custom object, say, a CreditCard  object, as opposed to a simple String, we won't be able to decrypt it. Instead, we'll need to build our own implementation of SealedObject to accomplish that. We've written an EncryptedObject class to do exactly that. It's functionally equivalent to SealedObject, but can be used with custom classes. We just need to have it in our classpath to use it. It's called EncryptedObject to avoid namespace collision with SealedObject, but they are otherwise identical, and you can use this EncryptedObject class as a drop-in replacement for SealedObject because its method signatures are exactly the same. It is provided for you in Appendix D of this book. Summary Symmetric encryption is a valuable tool for security. It provides us with the ability to hide data from prying eyes in various formats. Symmetric-key encryption has one big problem though: key distribution. In order to send encrypted messages to someone, we need to share a key with them. As we demonstrated in Chapter 3 with our Hamlet examples, this can be very difficult to do properly. In essence, we need to have a shared secret at some point in order to share secret messages in the future. What's really needed is some way to bootstrap the process, some way to create a shared secret by exchanging purely public information. Asymmetric-key encryption, or public-key encryption does exactly that. In the next chapter, we'll show how to incorporate public-key encryption into our Java programs.