Chapter 11. Key Management
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.
The fluidity of key management is evident in the progress of Java itself. Key management with the 1.1 API is very different from key management in 1.2. Further complicating this picture is the fact that no Java-enabled browser (including HotJava, but not including the Java Plug-In) uses the technique for key management that comes with the JDK. Each requires keys to be kept in a different key database, and each uses a different technique to store and retrieve keys from that application-specific database. Key management remains application-specific.
In this chapter, we'll discuss the basic features of Java that are available for key management, including the default key management features of the JDK. We'll conclude with an example of implementing your own key management system. The key management features we're going to discuss apply primarily to Java 1.2. If you must implement a key management system under Java 1.1, you'll need to use the IdentityScope class as discussed in Appendix B, "Identity-Based Key Management". The IdentityScope class has been deprecated in 1.2.
11.1. Overview of Key Management
Keys are important to Java's security model because they allow us to create or verify a digital signature. In the sandbox model, we usually think of the use of digital signatures in the context of a signed JAR file. When a JAR file is signed, we are assured that the classes contained in that file were actually provided by the entity (the person or corporation) that signed the JAR file. This allows us to grant privileges to the signed classes because we know that the classes have not been forged by a third party. Of course, digital signatures have many other uses in a particular application.
We'll discuss the details of digital signatures in Chapter 12, "Digital Signatures". For now, it's enough to know that a digital signature is created with a private key, then transferred electronically (along with the data it signed). When the digital signature is received, it must be verified, which requires a public key that corresponds to the private key that generated the signature.
The purpose of a key management system is two-fold. When you need to digitally sign something, the key management system must provide your private key for the code that creates the digital signature. When you need to verify a digital signature, the key management system must provide the public key that will be used for verification. 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.
Hence, there are three elements of a key management system:
Java 1.1 comes with a key management system that is based upon the javakey utility. Javakey has several limitations; in particular, it stores public and private keys in the same, unprotected location (often called an identity database). This allows anyone with access to the javakey database to determine all the keys that were stored in the file. Since access is required to obtain your own private key to generate your own digital signature, this essentially gives all users access to each other's keys. This problem was a limitation of the javakey utility itself. It's possible to use the 1.1 classes to write a key database in such a way that your private key is held separately from a group of public keys (see Appendix B, "Identity-Based Key Management").
The javakey utility was an interim solution to the key management problem; it is no longer available. In 1.2, javakey has been replaced by a new utility called keytool. Keytool is a much better tool, in that individual private and public keys can be stored in the same database, and retrieval of each key can be made subject to a password. The keytool database is often referred to as the keystore.
Unfortunately, the default implementation of the keytool database still has certain limitations; in particular, it is difficult to share the keys in a keytool database among a widely dispersed group of people (like all the employees of XYZ Corporation). We can, however, use the framework that the keytool database uses to create a key management system that has whatever features we require.
That framework is the ultimate goal of this chapter. First, however, let's take a brief look at the notion of the identity to whom a key belongs. In Java's key management model, the association between a key and its owner is application-specific. There is an Identity class in Java that was used for this purpose in 1.1, but it has been deprecated (because, among other things, it used the wrong Certificate class). However, there is still one interface that can be useful in your own applications that use keys: the Principal interface.
There is a single method that implementors of the Principal interface must implement:
The only idea that the Principal interface abstracts is that principals have a name. The Java documentation claims that a principal is anything that can have an identity, but don't be confused by that statement; the word "identity" is being overloaded in this context. The deprecated Identity class is a principal, but there are classes implementing the Principal interface that are unrelated to the Identity class.
Further confusion about this interface can arise because there are two principal objects in Java 1.2: the java.security.Principal interface (introduced in 1.1), and the org.omg.CORBA.Principal class (introduced in 1.2). These classes are unrelated, and we'll discuss only the java.security.Principal interface throughout this book.
The name that is stored in a principal is often an X.500 distinguished name (DN). That is particularly true when a principal is used in certain certificates (like X509 certificates); it is not an absolute requirement by any means.
There are other methods listed in the Principal interface--namely, the equals(), toString(), and hashCode() methods. There's no reason for those methods to be listed in the Principal interface, since every class already inherits those methods from the Object class. If you implement the Principal interface, the only method you must implement is the getName() method. You should make sure that the other methods of the Principal interface are implemented correctly--but you should ensure that these methods of the Object class are implemented correctly for all your classes, not just those that implement the Principal interface.
Copyright © 2001 O'Reilly & Associates. All rights reserved.