Chapter 10. Keys and CertificatesContents:
Keys
In this chapter, we discuss the classes in the Java security package that handle keys and certificates. Keys are a necessary component of many cryptographic algorithms--in particular, keys are required to create and verify digital signatures. The keys we're going to discuss in this chapter are public keys and private keys, since those are the keys most often used in a digital signature. Secret keys--used for encryption algorithms--are discussed in Chapter 13, "Encryption". We defer that discussion because secret keys do not come with standard Java implementations; they come only with the Java Cryptography Extension. We also cover the implementation of certificates in this chapter. Certificates are used to authenticate keys; when keys are transmitted electronically, they are often embedded within certificates. Keys and certificates are normally associated with some person or organization, and the way in which keys are stored, transmitted, and shared is an important topic in the security package. Management of keys is left for the next chapter, however; right now, we're just concerned about the APIs that implement keys and certificates. As usual, we'll show how a programmer interacts with keys and certificates, as well as how you might implement your own versions of each. The classes and engines we discuss in this chapter are outlined in Figure 10-1. There are two engines that operate on keys:
Figure 10-1. The interaction of key classesThere are a number of classes and interfaces we'll discuss to facilitate support for Figure 10-1; in addition to the engine classes themselves, there are several classes and interfaces that represent the key objects and the key specifications (the encoded key data is always an array of bytes). In an effort to provide the complete story, we'll delve into the details of all of these classes; for the most part, however, the important operations that most developers will need are:
This means that, for the most part, the data objects we explore in this chapter--the Key classes and interfaces as well as the various KeySpec classes (key specification classes)--can be treated by most programmers as opaque objects. We'll show their complete interface (which you might be curious about, and which is absolutely needed if you're writing your own security provider), but we'll try not to lose sight of the two goals of this chapter. Also note that the idea of the key factory and key specifications is available only with Java 1.2.[1] In Java 1.1, you can get the encoded key data directly from a key, but that's a one-way operation.
10.1. KeysLet's start with the various classes that support the notion of keys within Java. 10.1.1. The Key InterfaceThe concept of a key is modeled by the Key interface (java.security.Key):
As we discussed in Chapter 8, "Security Providers", there might be several algorithms available for generating (and understanding) keys, depending on the particular security providers that are installed in the virtual machine. Hence, the first thing a key needs to be able to tell us is what algorithm generated it:
We listed the standard algorithm names for key generation in Chapter 8, "Security Providers", but with the default provider with the JDK, this string is always DSA. When a key is transferred between two parties, it is usually encoded as a series of bytes; this encoding must follow a format defined for the type of key. Keys are not required to support encoding--in which case the format of the data transferred between the two parties in a key exchange is either obvious (e.g., simply the serialized data of the key) or specific to a particular implementation. Keys tell us the format they use for encoding their output with this method: For DSA keys produced by the Sun security provider, this format is always PKCS#8 for private keys and X.509 for public keys. The encoded data of the key itself is produced by this method:
Those are the only methods that a key is guaranteed to implement (other than methods of the Object class, of course; most implementations of keys override many of those methods). In particular, you'll note that there is nothing in the key interface that says anything about decoding a key. We'll say more about that later. There are two additional key interfaces in the Java security API:
These interfaces contain no additional methods. They are used simply for type convenience. A class that implements the PublicKey interface identifies itself as a public key, but it contains no methods that are different from any other key. 10.1.1.1. DSA keysThe keys supported by the Sun security provider are built around the DSA algorithm. DSA-generated keys are important enough to have several interfaces built around them; these interfaces enhance your ability to work with these specific types of keys. These interfaces are necessary because DSA keys have certain pieces of information that are not reflected in the default key interfaces: the DSA algorithm-specific parameters p, q, and g that are used to generate the keys. Knowledge of these variables is abstracted into the DSAParams interface (java.security.interfaces.DSAParams): Class Definitionpublic interface DSAParams { public BigInteger getP(); public BigInteger getQ(); public BigInteger getG(); } Keys that are generated by DSA will typically implement the DSAKey interface (java.security.interfaces.DSAKey):
Implementing this interface serves two purposes. First, it allows the programmer to determine if the key is a DSA key by checking its type. The second purpose is to allow the programmer to access the DSA parameters using this method in the DSAKey interface: These methods and interfaces allow us to do specific key manipulation like this: Class Definitionpublic void printKey(Key k) { if (k instanceof DSAKey) { System.out.println("key is DSA"); System.out.println("P value is " + ((DSAKey) k).getParams().getP()); } else System.out.println("key is not DSA"); } The idea of a DSA key is extended even further by these two interfaces (both of which are in the java.security.interfaces package):
DSA keys are often used in the Java world (and elsewhere in cryptography), and if you know you're dealing with DSA keys, these interfaces can be very useful. In particular, if you're writing a security provider that provides an implementation of DSA keys, you should ensure that you implement all of these interfaces correctly. For most programmers, however, keys are opaque objects, and the algorithm-specific features of DSA keys are not needed. 10.1.2. The KeyPair ClassThere are no classes in the core JDK that implement any of the Key interfaces. However, there is one concrete class, the KeyPair class (java.security.KeyPair), that extends the abstraction of keys:
The KeyPair class is a very simple data structure class, containing two pieces of information: a public key and a private key. When we need to generate our own keys (which we'll do next), we'll need to generate both the public and private key at once. This object will contain both of the necessary keys. If you're not interested in generating your own keys, this class may be ignored. The KeyPair class contains only two methods:
A key pair object is instantiated through a single constructor:
In theory, a key pair should not be initialized without both members of the pair being present; there is nothing, however, that prevents us from passing null as one of the keys. Similarly, there are no security provisions within the KeyPair class that prevent the private key from being accessed--no calls to the security manager are made when the getPrivate() method is invoked. Hence the KeyPair class should be used with caution. Copyright © 2001 O'Reilly & Associates. All rights reserved. |
|