Book Home Java Security Search this book

Chapter 11. Key Management

Contents:

Overview of Key Management
The KeyStore Class
A Key Management Example
Summary

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.[1] 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.

[1]1.2 is now Java 2.

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:

Keys

The keys in a key management system can be used for several cryptographic operations, but in general we will use them to sign data, such as a JAR file. An entity in the key management database can have no keys, a public key, or both a public key and a private key.

Certificates

Certificates are used to verify that the association between a public key and an entity is valid. Verification of a digital signature requires the public key that belongs to the entity that created the digital signature; a certificate verifies that the public key itself has not been forged and does indeed belong to the desired identity.

Identities

Identities are an abstraction of individuals, companies, or any other entity that might have a key. The purpose of a key management system is to associate identities with their keys. This association must be stored somewhere; we refer to the database in which these associations are stored as the key database or the keystore.

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.

11.1.1. Principals

Classes that are concerned with identities and key management in the Java security package generally implement the Principal interface (java.security.Principal):

public interface Principal

Provide an interface that supports the notion of an entity. In particular, principals have a name, but little else.

There is a single method that implementors of the Principal interface must implement:

public String getName()

Return the name of the principal. This is typically an X.500 distinguished name, but it may be any arbitrary name.

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.



Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.