All Permissions
9.5 Keys, Certificates, and Object Serialization
Before we conclude this chapter, a brief word on object serialization, keys, and certificates. Keys and certificates are often transmitted electronically, and a reasonable mechanism for transmitting them between Java programs is to send them as serialized objects. In theory −− and, most of the time, in practice −− this is a workable solution. If you modify some of the examples in this chapter to save and restore serialized keys or certificates, that will certainly work in a testing environment.
A problem arises, however, when you send these serialized objects between virtual machines that have two different security providers. Let's take the case of a DSA public key. When you create such a key with the Sun security provider, you get an instance of the sun.security.provider.DSAPublicKey class. When you create such a key with a third−party security provider, you may get an instance of the
com.xyz.XYZPublicKey class. Although both public keys are extensions of the PublicKey class, they cannot be interchanged by object serialization. Serializing a public key created with the Sun security provider
requires that the sun.security.provider.DSAPublicKey class be used, and deserialization creates an object of that type, no matter what security providers the deserializing virtual machine has installed.
Whether or not the Sun security provider has been installed in the destination virtual machine is irrelevant.
The process of deserializing the object uses that class if it is available, and deserialization fails if that class is not available.
Hence, while they are serializable objects, keys and certificates should only be transmitted as encoded data.
For keys, you also have the option of transmitting the data contained in the key specification as we did earlier;
the key specification classes are not serializable themselves, so you still have to rely on transmitting only the data that those objects contain.
This rule applies not only to keys and certificates that stand alone, but also to classes that embed one of those objects. Take, for example, this class:
public class Message implements Serializable { String msg;
X509Certificate cert;
byte signature[];
}
If you want to send an object of this class to a remote virtual machine (or save the object to a file), you should override the writeObject( ) and readObject( ) methods of the class so that when it is transmitted, the certificate is transmitted only as its encoded data and not as an instance of the
sun.security.x509.X509CertImpl class. We'll do just that in Chapter 12.
9.6 Comparison with Previous Releases
Keys are present in Java 1.1 and the Java 2 platform, but much of the support for them that we've discussed here is only available in the Java 2 platform. Key factories and key specifications are only available in Java 2.
In Java 1.1, you can get the encoded key data directly from a key, but that's a one−way operation; there's no practical way to import a key in Java 1.1.
In Java 1.1, the KeyPairGenerator class extends only the Object class; in Java 2, this class extends the KeyPairGeneratorSpi class. As is usual with this architecture, some of the methods we used are methods of the KeyPairGenerator class in Java 1.1 and methods of the KeyPairGeneratorSpi class in 1.2; for the developer, the end result is the same.
Java 1.1 only supports DSA keys. The RSA−based key interfaces were introduced in Java 2, version 1.2.
However, there is no standard security provider in that release that implements RSA keys; only the security providers that come in Java 2, version 1.3 and with JSSE provide an RSA implementation.
9.7 Summary
Keys are a basic feature of any cryptographic system; they provide one of the inputs required to produce a digital signature (as well as other potential cryptographic operations). In this chapter, we looked at the basic classes that implement the notion of a key within the Java security package.
Keys are closely tied to the notion of certificates; a certificate contains a public key as well as an assurance from some known entity that the public key belongs to a specific entity. In a general sense, there are a great many things you can do with certificates, but for our purposes, we're interested in certificates only from the perspective of the certificate's user −− that is, we want to be able to import and verify a certificate, but we're not too interested in creating our own certificates or in becoming a certificate authority.
Given that the operations we want to perform on keys and certificates are simple −− importing and exporting those certificates −− you'd expect that we could leave our discussion of keys for the time being.
Unfortunately, the topic of finding a key for a particular entity (which is really just a case of importing a key) is a particularly troublesome topic, which we'll examine in the next chapter.
In this chapter, we're going to discuss key management and the facilities in Java that enable key management.
The problem of key management turns out to be a hard one to solve: there is no universally accepted approach to key management, and although many features in Java (and on the Internet) are available to assist with key management, all key management techniques remain very much works in progress.
Keys are important because they allow us to perform a number of cryptographic operations, from digital signatures to encrypted data streams. We'll discuss the details of these algorithms in the next few chapters. For now, it's enough to know that you must provide some sort of key or certificate for many of these algorithms:
sometimes you need a private key, sometimes you need a secret key, and sometimes you need a public key contained within a certificate. The purpose of a key management system is to store such keys and allow you to retrieve them programatically (or through certain tools). A key management system may encompass other operations (it may, for example, provide information about the degree to which a particular individual should be trusted), but it exists primarily to serve up keys and certificates.
In this chapter, we'll discuss Java's key management system, which is built around the notion of a keystore.
Keystores are created and manipulated though an administrative tool (keytool), and there is a Java API that allows you to use keystores programatically. We'll start this chapter by looking at keytool, which will allow us to become familiar with the concepts embodied by a keystore. Then we'll see how you can use the keystore programatically. Because Sun's implementation of the keystore is not necessarily suitable for all facilities (in particular, it is not the best system for enterprise−wide key management), we'll then look at the facilities available to build your own key management system. Finally, we'll conclude with other techniques to manage secret keys since secret keys are often managed outside of a traditional keystore.