home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book Home Java Security Search this book

Appendix A. Security Tools

In this appendix, we'll discuss the tools that come with the JDK that allow developers, end users, and system administrators to deal with the security aspects of the Java platform. These tools are only available in Java 1.2,[1] since they primarily deal with operations that require the support of 1.2.[2] As Java's security model advances, these tools have become primary interfaces to establishing a secure sandbox for Java applications.

[1]1.2 is now Java 2.

[2]The javakey utility in 1.1 can be used to sign JAR files and to operate like the keytool; that utility is obsolete in 1.2.

To a lesser extent, these tools have become an interface for establishing a secure sandbox for Java applets as well. However, as we've seen, not all the security features of the Java platform have yet been uniformly adopted by all browsers. In part, it is a problem with logistics. As this book went to press, Java 1.2 was still a new release. Clearly it will take some time before these new features can be propagated to browsers. Part of the problem, though, lies in the fact that Java applications (and Java browsers) ultimately decide upon their own security features.

This last fact is true of your own applications as well: you can certainly use the keytool utility that comes with the JDK to manage your public key/private key databases. But if it is appropriate, you may want to replace (or at least supplement) the keytool with your own key management tool that handles some of the situations we discussed in Chapter 11, "Key Management".

A.1. The keytool

In Chapter 11, "Key Management" we discussed the KeyStore class, which provides an interface to a key management system. The Java platform comes with a tool--keytool--that provides an administrative interface to that class. Keytool allows end users and system administrators to add, delete, and modify entries in the keystore (provided that they have sufficient permissions, of course).

When we discussed the KeyStore class, we mentioned that it had some limitations that may lead you to write your own implementation of that class. The good news is that if you write such a class, you may still use keytool to administer your set of keys. Since keytool uses the standard interface provided by the KeyStore class, it will be (mostly) compatible with any new class that you install into that interface (we'll remind you how to do that at the end of this appendix). However, there are some exceptions to this: keytool itself places some restrictions upon the algorithms that may be used to support particular keys.

Before we examine the workings of keytool, let's review a few objects that we talked about in Chapter 11, "Key Management". When we discussed the KeyStore class, we defined the following terms:

keystore

The keystore is the file that actually holds the set of keys; keytool operates on this file. In other implementations of the KeyStore class, the keystore may not be a file--the keys in that implementation may be held in a database or some other structure. Regardless, we refer to the set of keys on disk (or wherever they are located) as the keystore.

In keytool, this file is called .keystore and is held in the directory specified by the property user.home. On Unix systems, this directory defaults to the user's home directory (e.g., $HOME); on Windows systems, this directory defaults to the concatenation of the HOMEDRIVE and HOMEPATH environment variables (e.g., C:\).

alias

An alias is a shortened, keystore-specific name for an entity that has a key in the keystore. I choose to store my public and private key in my local keystore under the alias "sdo"; if you have a copy of my public key, you may use that alias, or you may use another alias (like "ScottOaks"). The alias used for a particular entity is completely up to the discretion of the individual who first enters that entity into the keystore.

DN (distinguished name)

The distinguished name for an entity in the keystore is a subset of its full X.500 name. This is a long string; for example, my DN is:

Class Definition

CN=Scott Oaks, OU=SMCC, O=Sun Microsystems, L=New York, S=NY, C=US

DNs are used by certificate authorities to refer to the entities to whom they supply a certificate. Hence, unlike an alias, the DN for a particular key is the same no matter what keystore it is located in: if I send you my public key, it will have the DN encoded in the public key's certificate.

However, nothing prevents me from having two public keys with different DNs (I might have one for personal use that omits references to my place of employment). And there is no guarantee that two unrelated individuals will not share the same DN (in fact, you can count on this type of namespace collision to occur).

key entries and certificate entries

There are two types of entries in the keystore: key entries and certificate entries. A key entry is an entry that has a private key as well as a corresponding public key. The public key in this case is embedded in a certificate, and there is a chain of certificates that vouch for the public key.

A certificate entry, on the other hand, does not contain a private key; it contains only a public key held in a certificate. In addition, there is only a single certificate associated with this entry.

With that in mind, we'll look at the various commands that keytool provides. At present, keytool only has a command-line interface; we'll look at the typical commands that add, modify, list, and delete entries in the keystore.

A.1.1. Global Options to keytool

Keytoolimplements a number of global options--options that are available to most of its commands. We'll list these as appropriate for each command, but here's an explanation of what they do:

-alias alias

Specify the alias the operation should apply to (e.g., -alias sdo). The default for this value is "mykey."

-dname distinguishedName

Specify the distinguished name. There is no default for this value, and if you do not specify it on the command line, you will be prompted to enter it when it is needed. Letting keytoolprompt you is generally easier, since the tool will prompt for the name one field at a time. Otherwise, you must enter the entire name in one quoted string, e.g.:

Class Definition

-dname \
"CN=Scott Oaks, OU=SMCC, O=Sun Microsystems, L=New York, S=NY, C=US"
-keypass password

Specify the password used to protect the entire keystore. Access to any element in the keystore requires this global password (programmatically, this is the password that is passed to the load() method of the KeyStore class). If this password is not provided on the command line, you will be prompted for it. This is generally more secure than typing it on a command line or in a script where others might see it. Passwords must be at least six characters long.

Note that even though the KeyStore class allows you to read entries from the keystore without this password, keytool does not.

-keystore filename

Specify the name of the file that holds the keystore (programmatically, this file will be opened and passed as the input stream argument to the load() method of the KeyStore class). The default value of this is the .keystore file described above.

-storepass password

Specify the password used to protect a particular entry's private key. This is usually not (and should not be) the same as the global password. There should be a different password for each private key that is specific to that entry. This allows the keystore to be shared among many users. If this password is not provided on the command line, you will be prompted for it, which is generally the more secure way to enter this password.

-storetype storetype

Specify the type of keystroke that the keytool should operate on. This defaults to the keystroke type in the java.security file, which defaults to JKS, the keystore type provided by the Sun security provider.

-v

Verbose--print some information about the operations keytool is performing.

A.1.2. Adding a Certificate Entry

In order to add a certificate entry to the database, you use this command:

-import

Import a certificate into the database. This command either creates a new certificate entry or imports a certificate for an existing key entry. This command supports the following options:

-alias alias
-keypass keypass
-keystore keystore
-storepass storepass
-storetype storetype
-v
-file inputFile

The file containing the certificate that is being imported. The certificate must be in RFC 1421 format. The default is to read the data from System.in.

-noprompt

Do not prompt the user about whether or not the certificate should be accepted.

-trustcacerts

Use the cacerts file to obtain trusted certificates from certificate autorities that have signed the certificate that is being imported.

When you import a certificate, the information contained in that certificate is printed out; this information includes the distinguished names of the issuer and the principal, and the fingerprint of the certificate. Well-known certificate authorities will publish their fingerprints (on the Web, in trade papers, and elsewhere). It is very important for you to verify the displayed fingerprint with the published fingerprint in order to verify that the certificate does indeed belong to the principal named in the certificate.

Let's say that I have a certificate for the ACME certificate authority in the file amce.cer. I can import it with this command:

Class Definition

piccolo% keytool -import -alias acme -file acme.cer
Enter keystore password:  ******
Owner: CN=ACME, OU=ACME CA Services, O=ACME Inc., L=New York, S=NY, C=US
Issuer: CN=ACME, OU=ACME CA Services, O=ACME Inc., L=New York, S=NY, C=US
Serial Number: 34cbd057
Valid from: Sun Jan 25 18:52:55 EST 1998 until: Sat Apr 25 19:52:55 EDT 1998
Certificate Fingerprints:
	MD5:  51:4E:52:2C:1B:14:38:52:DB:30:5D:46:A9:46:FF:BB
	SHA1: 9F:B2:18:4A:63:8B:F8:EB:A6:A0:56:DB:C7:1B:B3:CC:F5:4B:BA:72
Trust this certificate? [no]:  yes

After typing in the command, keytool prints the given names, serial number, and fingerprints, and asks for verification before it actually enters the certificate into the keystore. After receiving a yes answer, the entry is made.

A.1.3. Adding a Key Entry

To add a key entry to the database (that is, an entry containing a private key), use this command:

-genkey

Generate a key pair and add that entry to the keystore. This command supports these options:

-alias alias
-dname DN
-keypass keypass
-keystore keystore
-storepass storepass

-storetype storetype

-keyalg AlgorithmName

Use the given algorithm to generate the key pair. For the default Sun security provider, the name must be DSA, which is also the default value for this option. Despite the presence of this option, you cannot really specify another algorithm name, nor, for that matter, can you use a non-Sun DSA provider. Internally, keytool expects the key generator to produce keys that belong to a specific class in the sun package.

-keysize keysize

Use the given keysize to initialize the key pair generator. The default value for this option is 1024. Since the key is a DSA key, the value must be between 512 and 1024 and be a multiple of 64.

-sigalg signatureAlgorithm

Specify the signature algorithm that will be used to create the self-signed certificate; this defaults to SHA-1/DSA, which is supported by the Sun security provider. Like the key algorithm, this option is not particularly useful at present, since you cannot use your own security provider classes to implement the signature.

-validity nDays

Specify the number of days for which the self-signed certificate should be valid. The default value for this option is 90 days.

The key entry that is created in this manner has the generated private key. In addition, the public key is placed into a self-signed certificate; that is, a certificate that identitifies the holder of the public key (using the distinguished name argument) and is signed by the holder of the key itself. This is a valid certificate in all senses, although other sites will probably not accept the certificate since it is not signed by a known certificate authority (CA). But the self-signed certificate can be used to obtain a certificate from a CA.

In order to use this self-signed certificate to obtain a certificate from a CA, you must first generate a certificate signing request (CSR). The CSR contains the distinguished name and public key for a particular alias and is signed using the private key of the alias; the CA can then verify that signature and issue a certificate verifying the public key. CSRs are generated with this option:

-certreq

Generate a certificate signing request. This command supports the following options:

-alias alias
-keypass keypass
-keystore keystore
-storepass storepass

-storetype storetype

-v
-sigalg signatureAlgorithm

Use the given algorithm to sign the CSR. This option is not presently useful, as the internal design of keytool only supports SHA-1/DSA signatures created by the Sun security provider.

-file outputFile

Store the CSR in the given file. The format of the CSR is defined in PKCS#10. The default is to write the CSR to System.out.

Once you have the CSR in a file, you must send it to the CA of your choice. Different CAs have different procedures for doing this, but all of them will send you back a certificate they have signed that verifies the public key you have sent to them. There are a few different formats in which the CA will send back a certificate; the only format that is presently supported by keytool is RFC 1421 (so you should use a CA that supports this format, of course). You must also use a CA for whom you have a certificate entry (but the CA will often send you its self-signed certificate anyway).

Once you've received the file containing the new certificate, you can import it into the keystore using the -import command we discussed previously.

Here's an example of how all these commands can be used to create an entry with a private key and a certified public key. First, we must create the entry:

Class Definition

piccolo% keytool -genkey -alias sdo
Enter keystore password:  ******
What is your first and last name?
  [Unknown]:  Scott Oaks
What is the name of your organizational unit?
  [Unknown]:  SMCC
What is the name of your organization?
  [Unknown]:  Sun Microsystems
What is the name of your City or Locality?
  [Unknown]:  New York
What is the name of your State or Province?
  [Unknown]:  NY
What is the two-letter country code for this unit?
  [Unknown]:  US
Is <CN=Scott Oaks, OU=SMCC, O=Sun Microsystems, L=New York, S=NY, C=US> correct?
  [no]:  yes

Enter key password for <sdo>
        (RETURN if same as keystore password):  ******

At this point, we now have an entry for sdo in the keystore. That entry has a self-signed certificate; note that we had the tool prompt us for all the entries that comprise the DN rather than attempting to type it all in on the command line. The next step is to generate the CSR:

Class Definition

piccolo% keytool -certreq -alias sdo -file sdoCSR.cer
Enter keystore password:  ******

The file sdoCSR.cer contains the CSR which must now be sent to a CA. Note that we must send the CSR to an authority for whom we already have a certificate entry--that is, for whom we already have a public key. Otherwise, when the response to the CSR comes, we will be unable to verify the signature of the CA that issued the new certificate.

When the response does come, we must save it to a file. If we save it to the file sdo.cer, we can import it with this command:

Class Definition

piccolo% keytool -import -file sdo.cer -alias sdo
Enter keystore password:  ******

Assuming that the certificate is valid, this imports the new certificate into the keystore. The certificate is invalid if the public key for sdo does not match the previously defined public key in the database, or if the certificate was issued by an authority for whom we do not possess a public key, or if the certificate signature is invalid (which would be the case if data in the certificate had been modified in transit).

The state of the sdo entry in the keystore has changed during this example:

  • After the first command, the sdo entry has a single certificate; that certificate is issued by sdo.

  • After the import command, the sdo entry has two certificates in its certificate chain: the first certificate is issued by Acme and has a principal of sdo; the second certificate is Acme's self-signed certificate (a copy of the one that was imported when the Acme certificate entry was created).

In programmatic terms, the getCertificateChain() method of the KeyStore class will return an array of one and two elements, respectively, for these cases.

We've mentioned in this section that in order to import a certificate like this, the self-signed certificate of the certificate authority must already be in the keystore. However, there's a bootstrapping issue involved in this: how do you get the initial certificates for the certificate authorities into a keystore?

The JDK comes with a set of five pre-installed certificates: four from VeriSign, which issues certificates at different levels, and one from RSA Data, Inc. These certificates are in the cacerts file in the ${JAVAHOME}/lib/security directory. While those certificates are not present in your .keystore file, you can still import certificates into your .keystore file by using the -trustcacerts option: in that case, as long as the certificate you're importing has been signed by one of the authorities in the cacerts file, the import operation will succeed.

Hence, if we'd sent our CSR request in the above example to VeriSign and the returned certificate from VeriSign was stored in the sdo.cer file, we could import it with this comand:

Class Definition

piccolo% keytool -import -file sdo.cer -alias sdo -trustcacerts

If you want to use the certificates of the certificate authorities programatically, you may do so by creating a keystore of type JKS, and loading that keystore from the cacerts file.

A.1.4. Modifying Keystore Entries

There is no practical way to modify a certificate entry in the keystore. You may delete an existing entry and add a new one if required.

There is one command that can modify the data within a key entry:

-selfcert

Change the certificate chain associated with the target key entry. Any previous certificates (including ones that may have been imported from a valid certificate authority) are deleted and replaced with a new self-signed certificate; this certificate can be used to generate a new CSR. The public and private keys associated with the alias are unchanged, but you may specify a new value for the DN on the command line. Hence, one use for this command is to change the DN for a particular entry.

This command supports the following options:

-alias alias
-dname DN
-keypass keypass
-keystore keystore
-storepass storepass
-storetype storetype
-sigalg algorithmName

Use the given algorithm to generate the signature in the self-signed certificate; as in other cases, this option only supports the DSA algorithm no matter what algorithms may be supported by your security provider.

-validity nDays

The number of days for which the self-signed certificate is valid. The default is 90 days.

The -keyclone command is often used with this command, which can create a copy of the original entry before the DN is changed:

-keyclone

Clone the target entry. The cloned entry will have the same private key and certificate chain as the original entry. This command supports the following options:

-alias alias
-keypass keypass
-keystore keystore
-storepass storepass
-storetype storetype
-v
-dest newAlias

The new alias name of the cloned entry. If this is not specified, you will be prompted for it.

-new newPassword

The new password for the cloned entry. If this is not specified, you will be prompted for it.

To change the password associated with a particular key entry, use this command:

-keypasswd

Change the password for the given key entry. This command supports the following options:

-alias alias
-keystore keystore
-storepass storePassword
-storetype storetype
-keypass originalPassword
-new newPassword

Specify the new password for the entry. If this option is not supplied, you will be prompted for the new password.

A.1.5. Deleting Keystore Entries

There is a single command to delete either a key entry or a certificate entry:

-delete

Delete the entry of the specified alias. If a certificate entry for a certificate authority is deleted, there is no effect upon key entries that have been validated by the authority. This command supports the following options:

-alias alias

-keystore keystore

-storepass storepass

-storetype storetype

-v

A.1.6. Examining Keystore Data

If you want to examine one or more entries in the keystore, you may use the following commands:

-list

List (to System.out) one or more entries in the keystore. If an alias option is given to this command, only that alias will be listed; otherwise, all entries in the keystore are listed. This command supports the following options:

-alias alias
-keystore keystore
-storepass storepass
-storetype storetype
-v
-rfc

When displaying certificates, display them in RFC 1421 standard. This option is incompatible with the -v option.

-export

Export the certificate for the given alias to a given file. The certificate is exported in RFC 1421 format. If the target alias is a certificate entry, that certificate is exported. Otherwise, the first certificate in the target key entry's certificate chain will be exported. This command supports the following options:

-alias alias
-keystore keystore
-storepass storepass
-storetype storetype
-v
-file outputFile

The file in which to store the certificate. The default is to write the certificate to System.out.

-printcert

Print out a certificate. The input to this command must be a certificate in RFC 1421 format; this command will display that certificate in readable form so that you may verify its fingerprint. Unlike all other commands, this command does not use the keystore itself, and it requires no keystore passwords to operate. It supports the following options:

-v
-file certificateFile

The file containing the RFC 1421 format certificate. The default is to read the certificate from System.in.

A.1.7. Importing a 1.1-Based Identity Database

The keystore in 1.2 is incompatible with the identity database in 1.1, but the keytool is capable of converting between the two. To convert a 1.1 identity database to a 1.2 keystore, use this command:

-identitydb

Convert a 1.1 identity database. This command has the following options

-v
-keystore keystore
-keypass keypass
-storepass storepass
-stereotype stereotype
-file db_file

The file name of the 1.1 identity database. The default for this is identitydb.obj in the user's home directory.

With this command, each trusted entry in the identity database will be created as a key entry in the keystore. All other entries in the identity database will be ignored.

A.1.8. Miscellaneous Commands

There are two remaining commands. The first allows you to change the global password of the keystore:

-storepasswd

Change the global password of the keystore. This command supports the following options:

-keystore keystore
-storepass storepass
-storetype storetype
-v
-new newPassword

The new global password for the keystore. If you do not specify this value, you will be prompted for it.

Finally, you can get a summary of all commands with this command:

-help

Print out a summary of the usage of keytool.



Library Navigation Links

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