Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

Security, Digital Certificates

Java Programming, Lecture Notes # 725, Revised 5/19/99.


Preface

Students in Prof. Baldwin's Advanced Java Programming classes at ACC will be responsible for knowing and understanding all of the material in this lesson beginning with the summer semester of 1999.

This lesson was originally written on April 26, 1999 and has been updated several times since.

The program in this lesson was tested using JDK 1.2 under Win95

Disclaimer

I claim absolutely no expertise in the area of security. I am simply a college professor attempting to gather information about Java on one hand and present it to my students on the other. I disclaim any responsibility for any security problems that may occur as a result of anyone using any of the material in any of my tutorial lessons.

You are responsible for your own actions. With regard to security, you should study not only the material that I will present, but also material provided by others who possess expertise in the security area. Hopefully my material will be useful in getting you started in that direction.

Two good books on security published by O'Reilly & Associates are:

I highly recommend both of these books.

Introduction

Message digests and digital signatures, the basis of certificates

Previous lessons introduced you to message digests and digital signatures. These two topics form the basis for Digital Certificates, which is the primary topic of this lesson.

Tools for certificate management

There are two major aspects of Digital Certificates insofar as Java is concerned. The first aspect involves the tools provided with the JDK that allow you to manage keys, certificates, and signed jar files from the command line.

Writing code to manage certificates

The second aspect involves the manner in which you can manage certificates under program control. This lesson addresses the management of keys and certificates from the command line, and also addresses the management of certificates under program control.

Mechanics versus procedures

For the most part, my tutorial lessons concentrate on the mechanics of using the Java tools and the Java API. I won't attempt to give advice on overall security procedures. Rather, I will leave that to others who have given more thought to the topic than I have.

Terminology

The jargon of the trade

The topic of Digital Signatures involves a lot of special terminology. In order to prepare you for discussions to follow in later sections, this section contains definitions or descriptions for much of that terminology.

Entity - A person, company, organization, program, computer, business, bank, or something else that you are trusting to some degree.

Certificate - A digitally signed statement from one entity (the issuer), saying that the public key (and other information) of another entity (the subject) has some specific value. All the data in a certificate is encoded using two related standards called ASN.1/DER.

Public Key - One half of a public/private key pair. A cryptographic key associated with a particular entity. It is intended that everyone who needs to have trusted interactions with that entity also have access to the key.

Private Key - One half of a public/private key pair. A cryptographic key intended to be known only to the particular entity that owns it. Private and public keys exist in pairs in public key cryptography systems. Data that has been encrypted using a private key can be decrypted using the corresponding public key. Similarly, data that is encrypted using the public key can be decrypted using the private key.

Digitally Signed - Digitally signed data is stored with the identity of an entity, and a digital signature that are intended to authenticate the source of the data and to confirm the integrity of the data. The data is signed using the entity's private key. Assuming that the public key of the source entity is known with confidence, it is possible to confirm the integrity of the data to a very high degree of confidence.

Signature - Typically an encrypted version of a message digest computed across the data that the signature is intended to represent. The digest is encrypted using an entity's private key so that it can be decrypted by another entity using the corresponding public key. Assuming that the public key is known with confidence, the receiving entity can compute the digest of the received data and compare it with the decrypted signature to authenticate the source of the data and confirm the integrity of the data.

Identity - A known way of addressing an entity. In some systems the identity is the public key. In others it can be anything from a Unix UID to an Email address or an X.509 Distinguished Name.

Certification Authority (CA) - A trusted third party whose public key is widely known with confidence. The CA serves as the root of a chain of certificates which, taken as a whole, can be used to verify the public key of the entity at the end of the chain. As of 4/28/99, some existing Certification Authorities were VeriSign, Thawte, and Entrust. You can also operate your own CA within your organization.

keytool - A program provided with JDK 1.2 that makes it possible to display, import, and export certificates. It is also possible to generate self-signed certificates. As of 4/28/99, keytool handles X.509 certificates.

X.509 Certificates - The X.509 standard defines what information can be contained in a certificate, and the data format of the certificate. X.509 certificates contain the following data, in addition to the signature:

Descriptions of some of the items in an X509 certificate follow.

Version - Identifies which version of the X.509 standard applies to the certificate. This determines the information that can be specified in it. As of 4/28/99, keytool can import and export v1, v2, and v3 certificates. It generates only v1 certificates.

Serial Number - A number created by the entity that issued the certificate that distinguishes it from other certificates issued by that same entity.

Signature Algorithm Identifier - Identifies the cryptographic algorithm used by the CA to sign the certificate.

Issuer Name - The X.500 Distinguished Name of the entity that signed the certificate.

Validity Period - Each certificate is valid for a specified amount of time. This is the period during which the certificate is valid.

Subject Name - The name of the entity whose public key is identified by the certificate.

Subject Public Key Information - Public key of the entity being named, an algorithm identifier which specifies the public key cryptographic system to which this key belongs, and any associated key parameters.

X.500 Distinguished Names - Used to identify entities, such as those that are named by the subject and issuer fields of X.509 certificates. keytool supports the following subparts:

Discussion

Privacy and security goals

An earlier lesson suggested that when exchanging data electronically, the parties to the communication might be interested in the following three aspects of that communication:

This lesson deals with only the first and third items: authentication and integrity. Generally, some type of encryption is required to achieve confidentiality. Encryption is the topic of a different lesson.

Digitally signed documents

In an earlier lesson, you learned about public and private keys and how these keys can be used to create a digitally signed document. If the originator of the document uses the private key to sign the document, the recipient of the document can use the corresponding public key to authenticate and confirm the integrity of the document. In other words, if the recipient has the public key corresponding to the private key used by the originator to sign the document, the recipient can confirm that:

However, the if in the above statement is a big if. In an earlier lesson on digital signatures, I assumed that the originator could provide her public key to the recipient via a secure communication channel. However, this is not always the case.

The major problem in public key cryptography

The major problem in public key cryptography is management of the keys. If I sign a document and send it to you along with my public key via the Internet, you can't be sure that the entire message and the key weren't intercepted and corrupted somewhere along the way.

The attacker could corrupt and digitally sign the document, and send you a different public key corresponding to the private key that was used to sign the corrupted document. If you believe that the substitute key is really my public key, you might verify and use the document using the bogus public key believing that it has not been corrupted.

Digital certificates, the solution to the problem

That brings us to digital certificates. A digital certificate is nothing more than a digitally signed document from one party (signer) that verifies the identity and public key of another party (subject).

If you know with certainty the public key of the signer, and if you trust the signer, you can determine the identity and public key of the subject with confidence. You can than use the public key of the subject to authenticate and verify the integrity of documents signed by her.

A hypothetical example

Consider the following hypothetical example. The CEO of the small company where you work posts her public key on her office door in plain view of all employees. Each time she enters or leaves the office, she pauses and confirms that the posted version of her public key hasn't been modified.

In certificate jargon, she might be known as the Certification Authority or CA having a well-known public key. She may even take other actions to expose her public key such as publishing it each week in the company newsletter.

Certifying the identity and public keys of department heads

The company has three departments managed by Katherine, Dick, and Cynthia. The CEO generates three self-signed certificates, one for each of the department heads. Each of these certificates verifies the identity of a department head, and also provides the public key for that department head.

Having a copy of the CA certificate for one of the department heads, you can then extract the information from the certificate and obtain the true identity and public key for that department head.

You can trust that the information about the department head is true because the information has been attested to and digitally signed by the CEO. You have extracted the information from the certificate signed by the CEO using her well-known public key. Since the CEO's public key is well known (it's posted on her office door), you can be confident that a bogus public key hasn't been substituted for the CEO's public key.

Certifying the identity and public keys of ordinary employees

Each of the department heads has five or six employees under their supervision. Some of those employees need to digitally sign documents (or code). The department heads create and digitally sign certificates for each of those employees. These certificates contain identifying information about the employee along with the public key for that employee.

Using a certificate chain

The combination (of the CA certificate describing the department head and the department head certificate describing the employee) is commonly referred to as a certificate chain.

Sue is one of the employees who report to Katherine. If you receive a digitally signed document from Sue along with copies of the digital certificates produced by the CEO and the Department Head, you will know with confidence the value of Sue's public key. You can then use her public key to verify her document.

In other words,

Confidence in the validity of the CA public key is a must

This is possible only because you are absolutely confident that the CEO's public key that you use to verify Katherine's public key is a valid public key for the CEO. Therefore, you must have received the public key for the CEO in a manner that prevented it from being replaced by a bogus key (such as posting on the CEO's office door, or publication each week in the company newsletter).

Digital certificates on the Internet

While this hypothetical example might be practical within a small company, a different approach is required for the use of digital certificates across the Internet as a whole. After all, there is (thankfully) no CEO for the Internet whose public key is completely trustworthy.

There are several companies and organizations whose public keys are widely published and well known. They will, for a price, issue a self-signed digital certificate verifying the identity and public key for a subject. The subject could be an individual, a company, or any other entity that needs to digitally sign documents or code.

All certificates are not created equal

Unfortunately, not all certificates are issued with the same level of certainty regarding the identity and public key for the subject. According to Scott Oaks, author of Java Security,

"certificate authorities have different levels at which they assess the identity of the entity named in the certificate. Some of these levels are very stringent and require the CA to do an extensive verification that (the subject) is who he says he is. Other levels are not stringent at all, and if (the subject) can produce a few dollars and a credit card, he is assumed to be (the subject). Hence, one of the steps in the process of deciding whether or not to trust the entity named in the certificate includes the level at which the certificate authority generated the certificate."

For example, as of 4/26/99, the following statement appears on the VeriSign page at http://digitalid.verisign.com/ns_pick.htm.

"The first step in applying for a Digital ID for Netscape Object Signing technology is choosing the class of Digital ID you need. The class of a Digital ID indicates the degree of assurance VeriSign provides about the identity of the holder of the Digital ID. The higher the class number, the more assurance the Digital ID carries. "

Don't assume that a certificate equates with trustworthy

Just because someone has a digital certificate that was issued by a Certification Authority, you shouldn't necessarily consider that certificate to provide a high level of assurance regarding the identity of that person.

You need to do some further checking with the issuer of the certificate to determine the level of assurance associated with the certificate. It could be that all that was required to get the Certification Authority to issue the certificate was to send a request along with a credit card number. It is a well-known fact that credit cards are easy to get, even for people with bad habits.

Key Management

This section is concerned primarily with the command-line tool named keytool provided with JDK 1.2 for the management of keys and certificates. A later section will deal with managing or manipulating certificates under program control.

The official Sun description of keytool, as copied from the documentation for JDK 1.2 is:

"Manages a keystore (database) of private keys and their associated X.509 certificate chains authenticating the corresponding public keys. Also manages certificates from trusted entities."

A further description of keytool from the JDK 1.2 documentation reads as follows:

"keytool is a key and certificate management utility. It enables users to administer their own public/private key pairs and associated certificates for use in self-authentication (where the user authenticates himself/herself to other users/services) or data integrity and authentication services, using digital signatures. It also allows users to cache the public keys (in the form of certificates) of their communicating peers."

Authenticity and integrity

As you are aware, digitally signed data can be verified to check the integrity of the data and the authenticity of the source. Integrity means that the data has not been modified or tampered with since it was signed. Authenticity means that the data came from whoever claims to have created and signed it.

The keystore

The keytool program stores keys and certificates in a special database referred to as a keystore. The default implementation writes the keystore into a file. The file can either be a file named .keystore (note the period) in the user's home directory, or a file having a different name somewhere else on the disk. The default implementation protects the keystore with one password and protects private and secret keys with a separate password.

The jarsigner tool

I will discuss another tool named jarsigner in detail in a different lesson. This tool uses information from a keystore to generate digital signatures for Java ARchive (JAR) files.

The jarsigner tool can also be used to verify the digital signature of a JAR file, using the certificate that comes with it. The certificate is included in the signature block file of the JAR file.

The tool then checks to see if the public key of that certificate is "trusted." By definition, a public key contained in the Trusted Certificate section of a specified keystore is trusted. (Therefore, you need to be very careful how you put keys in your keystore.)

Big changes in JDK 1.2 relative to JDK 1.1

The following statement appears in the JDK 1.2 documentation as an explanation regarding key management changes of JDK 1.2 relative to JDK 1.1:

"the keytool and jarsigner tools completely replace the javakey tool provided in JDK 1.1. These new tools provide more features than javakey, including the ability to protect the keystore and private keys with passwords, and the ability to verify signatures in addition to generating them. The new keystore architecture replaces the identity database that javakey created and managed."

The documentation goes on to point out that it is possible to import the information from a JDK 1.1 identity database into a keystore, using the identitydb command of the keytool program.

Types of entries in a keystore

There are two different types of entries in a keystore:

Key entries

As indicated by the name, each key entry holds cryptographic key information such as secret keys or private keys. Private keys have been discussed extensively in earlier lessons. Secret keys are keys used in the encryption and decryption process using classes and methods from the Java Cryptography Extension (JCE 1.2). As mentioned in an earlier lesson, U.S. Law prohibits me from providing any detailed electronic information about the classes in the JCE.

The information for both types of keys is stored in a protected format to prevent unauthorized access. The certificate chain for the corresponding public key typically accompanies the storage of a private key.

Possibly also because of U.S. government restrictions on the exporting of cryptographic information, the keytool and jarsigner tools only handle private keys and their associated certificate chains. They do not handle secret keys.

Trusted certificate entries

Each entry of this type contains a single public key certificate (or certificate chain) belonging to another party. It is called a trusted certificate because the owner of the keystore trusts that the public key in the certificate belongs to the identity identified as the subject of the certificate. (It shouldn't have been entered into the keystore until trust was verified.) The issuer (signer) of the certificate vouches for the truth of the belief in trust. (As mentioned earlier, the issuer may or may not have performed a satisfactory investigation so as to support the truth of this belief.)

The unique alias

Each key or certificate entry is accessed using a unique (not sensitive to case) alias. A pair of public and private keys can be added to the keystore using the genkey command.

A certificate or certificate chain can be added to the list of trusted certificates using the import command. In each case, you must specify a unique alias. Subsequent keytool commands must use the same alias to refer to the entity.

Creating a pair of keys

For example, the following command could be used at the prompt to create a new pair of keys and to wrap the public key into a self-signed certificate. This command specifies an initial password of joespassword. This password is required by subsequent commands to access the private key associated with the alias joe.

keytool -genkey -alias joe -keypass joespassword 

If you execute this command, you will be prompted to provide the following information:

Prior to being asked to enter the key password, you will be asked to confirm the entries for CN, OU, O, L, ST, and C. If you have made an error during the entry of the data, you can answer no. In that case you will be given an opportunity to enter the information again. If you answer yes, the keys and the certificate will be generated and stored in a keystore file as described later.

As indicated, the request for you to enter the keystore password in JDK 1.2 seems to be redundant since it was already entered on the command line. You will receive the same request even if you don't enter it on the command line.

Changing the password

Another keytool command could be used later, if desired to change the password associated with the alias joe. The alias and the initial password are required to associate a new password with the alias.

Storage of the keystore database

By default, the keystore is stored in a file named .keystore (note the period in front of the k) in the user's home directory. The user's home directory is determined by the value of the user.home system property. For example, given the user name Baldwin, the user.home property defaults to the following values on a Windows system:

C:\Winnt\Profiles\Baldwin on multi-user Windows NT systems
C:\Windows\Profiles\Baldwin on multi-user Win95 systems
C:\Windows on single-user Windows 95 systems 

It is also possible to use the keystore option of the keytool program to specify a name and location for the file that is different from the default.

Creating a keystore database

A keystore is created whenever you use any of the following commands to add data to a keystore that doesn't already exist:

Creating a pair of keys in a new keystore database

You can create a keystore file named Security09.cer in the directory in which you execute the command by

Quite a long period of time is required on my machine to complete the execution of this command, so be patient.

This keystore file will contain a pair of public and private keys wrapped in a self-signed certificate for the alias dick.

keytool -genkey -alias dick -keystore Security09.cer 

You can cause the file to be written somewhere other than in the current directory by specifying a fully qualified path to the file.

Displaying the contents of a certificate using the -v option for list

You can display the contents of the certificate by executing the following command:

keytool -list -alias dick -keystore Security09.cer -v

This command requires you to enter the keystore password. For the information that I provided, this command displays the following information. If you provide different information when you create the certificate, that information will be displayed. Note that I manually inserted line breaks into the data to force it to fit in the allocated space for this presentation.

Alias name: dick
Creation date: Mon Apr 26 16:17:46 CDT 1999
Entry type: keyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX,
C=US
Issuer: CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX,
C=US
Serial number: 3724d7d7
Valid from: Mon Apr 26 16:17:11 CDT 1999 until: Sun Jul 25
16:17:11 CDT 1999
Certificate fingerprints:
MD5:  B7:80:2C:FC:CB:F4:C1:60:2E:03:49:B5:E8:76:F4:42
SHA1: E9:C5:B3:C1:6F:9C:1E:87:1D:33:EB:4F:4F:26:66:09:49:
D5:9C:37 

The fingerprints shown above are message digests computed according to two different algorithms, MD5 and SHA1.

Displaying the contents of a certificate using the -rfc option

Another way to display the contents of the same certificate is by executing the following command using the rfc option instead of the v option.

keytool -list -alias dick -keystore Security09.cer -rfc

This command also requires you to enter the keystore password and displays the following information. Note that I manually inserted extra line breaks into the data to force it to fit in the allocated space for this presentation.

Alias name: dick
Creation date: Mon Apr 26 16:17:46 CDT 1999
Entry type: keyEntry
Certificate chain length: 1
Certificate[1]:
-----BEGIN CERTIFICATE-----
MIIC8TCCAq8CBDck19cwCwYHKoZIzjgEAwUAMF
4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUWDEP
MA0GA1UEBxMGQXVzdGluMQwwCgYDVQQKEwNBQ0
MxDDAKBgNVBAsTA0NJUzEVMBMGA1UEAxMMRGlj
ayBCYWxkd2luMB4XDTk5MDQyNjIxMTcxMVoXDT
k5MDcyNTIxMTcxMVowXjELMAkGA1UEBhMCVVMx
CzAJBgNVBAgTAlRYMQ8wDQYDVQQHEwZBdXN0aW
4xDDAKBgNVBAoTA0FDQzEMMAoGA1UECxMDQ0lT
MRUwEwYDVQQDEwxEaWNrIEJhbGR3aW4wggG4MI
IBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS
30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUf
tZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZ
UKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDw
T7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZ
ndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9Q
KBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5
V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTC
gWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFu
o38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z
8GkotmXoB7VSVkAUw7/s9JKgOBhQACgYEAjP3q
/FyUrK54187i8RKVQ1lEOfsTLpzKw0tHeAt5cI
RifHXk3rVvo6TyJUD0oOaMqwavVNFkUqcpPDMR
AnPHXu6+uat3TlpRwTcWdh33HCT4ThKv1N8RBj
65lZmKbvRD7JlF3XcWcwuFmd9MTrwvMQXhAI6E
Na3fjJYu4A/XXRYwCwYHKoZIzjgEAwUAAy8AMC
wCFE9MOdL1cPKle4MUsADr38pWS9DuAhQ0DsNI
FbIOvyc+ptj3JF7k2iBV7g==
-----END CERTIFICATE-----

When the rfc option is specified, the certificate is output in the Base 64 encoding format.

In this format, the encoded certificate data is bounded at the beginning and the end by the lines:

-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----

The characters between these two lines are a Base 64 representation of the certificate.

I will have more to say later about the difference between the v and rfc options.

Displaying the contents of a certificate using the default option

A third alternative way to display the contents of the same certificate is by executing the following command using the default display option (neither -rfc nor -v). This is the default display format for the list command.

keytool -list -alias dick -keystore Security09.cer

This command also requires that you enter the keystore password and displays the following information. Note that as before, I manually inserted extra line breaks into the data to force it to fit in the allocated space for this presentation.

dick, Mon Apr 26 16:17:46 CDT 1999, keyEntry,
Certificate fingerprint (MD5):
B7:80:2C:FC:CB:F4:C1:60:2E:03:49:B5:E8:76:F4:42

I will have more to say about this format later also.

Programming with certificates

I will also use this certificate file later to illustrate some of the programming features of Java that are used with certificates and keystores. For example, the Keystore class provides an interface that can be used to access and modify the information in a keystore.

Exporting a certificate

Having created a keystore in the file named Security09.cer and having populated it with a key pair and a certificate associated with the alias dick, you can export the certificate containing the public key into a file suitable for sending to someone else by executing the following command. Note that I manually inserted a line break to force the command to fit in the allocated space for this document.

keytool -export -alias dick -file Security09A.cer 
-keystore Security09.cer

Displaying an exported certificate using printcert

The exported certificate will then reside in a file named Security09A.cer. Having exported it into that file, you (or someone that you send it to) can display the certificate by executing the following command.

keytool -printcert -file Security09A.cer

This command produces the following output for my certificate. Note that I manually inserted line breaks to force the material to fit on my page.

Owner: CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, 
C=US
Issuer: CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, 
C=US
Serial number: 3724d7d7
Valid from: Mon Apr 26 16:17:11 CDT 1999 until: 
Sun Jul 25 16:17:11 CDT 1999
Certificate fingerprints:
MD5:  B7:80:2C:FC:CB:F4:C1:60:2E:03:49:B5:E8:76:F4:42
SHA1: E9:C5:B3:C1:6F:9C:1E:87:1D:33:EB:4F:4F:26:66:09:49:
D5:9C:37

Importing a trusted certificate

Finally, assuming that you were to receive this certificate from someone else, you could import it as a trusted certificate into a keystore in a file named Security09B.cer under the alias joe using the following command. I manually inserted line breaks into this command to make it fit in the allocated space.

keytool -import -alias joe -file Security09A.cer 
-keystore Security09B.cer

While importing my certificate, the command displays the following information on the screen. Note that this is a self-signed certificate because the owner is the same as the issuer.

Owner: CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, 
C=US
Issuer: CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, 
C=US
Serial number: 3724d7d7
Valid from: Mon Apr 26 16:17:11 CDT 1999 until: 
Sun Jul 25 16:17:11 CDT 1999
Certificate fingerprints:
MD5:  B7:80:2C:FC:CB:F4:C1:60:2E:03:49:B5:E8:76:F4:42
SHA1: E9:C5:B3:C1:6F:9C:1E:87:1D:33:EB:4F:4F:26:66:09:49:
D5:9C:37

The program prompts you to provide a password for the keystore and asks if you want to trust the certificate. If you answer "y", the program responds

"Certificate was added to keystore."

If you answer "n", the program responds

"Certificate was not added to keystore."

A recap

Now I will recap some of the above to prepare you for the discussions that follow.

The genkey command can be used to generate a pair of public/private keys, wrap the public key in a self-signed certificate, and store the private key along with the certificate as a key entry in a keystore. This information is associated with an alias, provided by you, that must be unique to the keystore database.

You must be able to provide the password for the keystore and another password for the key in order to execute this command. You must also provide other information about the entity that will be the owner of the key and the certificate.

The list command can be used to display certificate information in the keystore associated with a particular alias. You must be able to provide the keystore password to execute this command.

The export command can be used to export a certificate associated with a particular alias into a file that is suitable for sending to another entity. You must be able to provide the keystore password to execute this command.

The printcert command can be used to display the contents of a certificate that has been exported. No password is required to execute this command.

The import command can be used to import a (previously exported) certificate as a trusted certificate into a keystore database and to associate it with a unique alias. . You must be able to provide the keystore password to execute this command.

Standard tools

As of JDK 1.2, there are three standard tools delivered with the JDK that make use of a keystore:

keytool is discussed in this lesson. jarsigner and policytool are discussed is other lessons having to do with managing security policies and managing signed JAR files.

Implementation of the keystore database

A built-in implementation by Sun implements the keystore database as a file, utilizing a proprietary keystore format named "JKS." This format protects each private key with its individual password, and also protects the entire keystore with a different password.

As with other aspects of Java security, it is also possible to install a keystore implementation from other providers. According to Sun:

"The term "provider" refers to a package or a set of packages that supply a concrete implementation of a subset of services that can be accessed by the Java Security API.

Applications can choose different types of keystore implementations from different providers, using the "getInstance" factory method supplied in the KeyStore class. A keystore type defines the storage and data format of the keystore information, and the algorithms used to protect private keys in the keystore and the integrity of the keystore itself. Keystore implementations of different types are not compatible."

If this is of interest to you, you will need to refer to the documentation to learn how to perform the installation.

Specifying the location of the keystore database

The manner in which the location of the keystore is determined differs among the keytool, jarsigner, and policytool tools. keytool considers the keystore to be contained in a file. (It treats the KeyStore location that is passed to it at the command line as a filename and converts it to a FileInputStream, from which it loads the keystore information.)

The jarsigner and policytool tools can read a keystore from any location that can be specified using a URL.

Keystore type

You can specify a keystore type at the command line, via the storetype option for keytool and jarsigner. You can specify a keystore type via the "Change Keystore" command in the Edit menu for policytool.

A separate lesson discusses the different security policy configuration files that are used to establish the security policy on a machine under JDK 1.2. One of those files is java.home\lib\security\java.security. According to the JDK 1.2 documentation:

"If you don't explicitly specify a keystore type, the tools choose a keystore implementation based simply on the value of the keystore.type property specified in the security properties file. The security properties file is called java.security, and it resides in the JDK security properties directory, java.home\lib\security, where java.home is the JDK installation directory.

Each tool gets the keystore.type value and then examines all the currently-installed providers until it finds one that implements keystores of that type. It then uses the keystore implementation from that provider."

A static method named getDefaultType() is defined in the Keystore class. This method is used to manage security under program control, and makes it possible for applications and applets to retrieve the value of the keystore.type property.

Changing the keystore type

As mentioned earlier, the default keystore type is "jks". This is the proprietary type implementation provided by Sun. This default value is specified by a line in the security properties file that reads: keystore.type=jks.

If you need for the tools to use a keystore implementation that is different from the default, you will need to change that line to specify a different keystore type. The specification is not case sensitive.

Specifying keypair and signature algorithms

The keyalg and sigalg options of keytool allow you to specify any key pair generation and signature algorithm supplied by any of the registered cryptographic service providers.

Quoting the Sun documentation for JDK 1.2

The default key pair generation algorithm is "DSA". The signature algorithm is derived from the algorithm of the underlying private key: If the underlying private key is of type "DSA", the default signature algorithm is "SHA1withDSA", and if the underlying private key is of type "RSA", the default signature algorithm is "MD5withRSA".

When generating a DSA key pair, the key size must be in the range from 512 to 1024 bits, and must be a multiple of 64. The default key size for any algorithm is 1024 bits.

Alternative export formats

Certificates are often stored using an encoding format defined by the Internet RFC 1421 standard, as an alternative to binary encoding. This "Base 64 encoding" produces a printable format. It also facilitates exporting certificates to other applications by email or through some other mechanism capable of handling seven-bit ASCII data.

Certificates read by the import and printcert commands can be in either the Base 64 format or the binary encoded format.

By default, the export command outputs a certificate in binary encoding. Optionally, it can be used to output a certificate in the Base 64 format by using the rfc option.

For example, the following command can be used to export the certificate for the alias dick created earlier in this lesson into a file using the Base 64 format. I manually inserted a line break to force this material to fit in the allocated space.

keytool -export -alias dick -file Security09C.cer 
-keystore Security09.cer -rfc

When viewed with a text editor, the output file appears as shown below. Note that I removed a substantial amount of material from the middle of the file for brevity. I also manually inserted line breaks to force the material to fit in the allocated space.

-----BEGIN CERTIFICATE-----

MIIC8TCCAq8CBDck19cwCwYHKoZIzjgEAwUAMF
4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJUWDEP

NOTE: Material was removed here for brevity

Na3fjJYu4A/XXRYwCwYHKoZIzjgEAwUAAy8AMC
wCFE9MOdL1cPKle4MUsADr38pWS9DuAhQ0DsNI
FbIOvyc+ptj3JF7k2iBV7g==

-----END CERTIFICATE-----

This file will be used in a later section to illustrate the manipulation of certificates under program control.

Alternative display formats for list

An earlier example made use of the v and rfc options of the list command of keytool to display a certificate in three different formats.

By default, the list command prints the MD5 fingerprint of a certificate.

If the v option is specified, the certificate is printed in human-readable format.

If the rfc option is specified, the certificate is output in the Base 64 encoding format.

In the Base 64 format, the encoded certificate data is bounded at the beginning and the end by the lines:

-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----

The characters between these two lines are a Base 64 representation of the certificate.

Certificate chaining

keytool can be used to create and manage "key" entries in a keystore. Each such entry contains a private key and an associated certificate "chain". The first certificate in the chain contains the public key corresponding to the private key.

When you first use the genkey command to create a key, the chain contains a single self-signed certificate. In this case, the issuer (signer) is the same as the subject (the entity whose public key is being authenticated by the certificate). The private key that is generated and the public key authenticated by the certificate form a pair of corresponding keys.

Engendering trust

A self-signed certificate should not engender trust on the part of someone who receives a copy of the certificate. Anyone who downloads and installs JDK 1.2 can create such a certificate, and can pretend to be anyone else.

In order to cause this certificate to engender trust, it needs to be used to form a certificate chain that can be traced back to a trusted Certification Authority and verified against a well-known public key owned by that CA.

The certificate signing request (CSR)

This is accomplished by using the certreq command to generate a Certificate Signing Request (CSR) and sending that CSR to a Certification Authority (possibly accompanied by some money or a credit card number).

Processing the response from the CA

When the response is received back from the CA, that response is imported using the import command. The self-signed certificate in the keystore is automatically replaced by a chain of certificates received from the CA.

The certificate at the bottom of the chain is the certificate issued by the CA authenticating the subject's public key.

The next certificate in the chain is one that authenticates the CA's public key. This will often be a self-signed certificate from the CA authenticating its own public key. In that case, it will be the last certificate in the chain.

Alternative forms of response from the CA

Sometimes the CA will return a chain of certificates as described above. In this case, the bottom certificate in the chain will be a certificate signed by the CA, authenticating the public key corresponding to the private key in the key entry.

The second certificate in the chain will be a certificate signed by a different CA, authenticating the public key of the CA you sent the CSR to.

The next certificate in the chain will be a certificate authenticating the second CA's key, and so on. When the top certificate in the chain is reached, it will be a self-signed "root" certificate.

Thus, each certificate in the chain (after the first) authenticates the public key of the signer of the previous certificate in the chain.

There are two prevalent reply formats. One format (defined by the PKCS#7 standard) includes the supporting certificate chain, in addition to the issued certificate.

However, some CAs only return the issued certificate, with no supporting chain. In this case, the certificate chain must be established from trusted certificate information already stored in the keystore. The keytool tool can handle both formats, provided the keystore already contains the necessary trusted certificate information.

The root Certification Authority

The top-level or root CA certificate is always self-signed. The simple fact that the certificate contains a public key should not engender any trust because anybody could generate a self-signed certificate with the distinguished name of a well-known CA. The trust must come from the fact that the public key in that certificate is a well-known public key for that CA that can be verified from other sources such as newspaper advertisements.

The only reason that the public key is stored in the root certificate is because this is the format that most certificate management tools expect. In this case, the certificate is used only for the purpose of transporting the CA's public key to you so that you can manually verify it against another source.

Two reasons for importing a certificate

There are two reasons for you to import a certificate using the import command:

Import precautions

Before importing the certificate into your keystore, you should verify the public key embodied in the root certificate using other sources. One way to do this is to use the printcert command to view the fingerprint for the certificate. Then compare the fingerprint that is displayed with the known fingerprint for that CA obtained from some other reliable source.

Only if the fingerprints match can you be confident that the certificate has not been replaced in transit with an attacker's certificate. If such an attack took place, and you did not check the certificate before you imported it, you would end up trusting anything the attacker has signed, such as a JAR file with malicious class files inside.

Importing the certificate

You can import a certificate from a file using the import command as in the following sample command:

keytool -import -alias tom -file tomsfile.cer 

This command imports the certificate(s) in the file tomsfile.cer and stores it in the keystore entry identified by the alias tom. An earlier paragraph identified two reasons for importing a certificate, which really corresponds to two different types of certificates.

The value of the alias option indicates which type of import is intended. If the alias exists in the database, and identifies an entry with a private key, it is assumed you want to import a certificate reply from a Certification Authority. In this case, keytool checks whether the public key in the certificate reply matches the public key stored with the alias. If they are different, keytool exits without completing the import operation.

When importing a new trusted certificate, alias must not yet exist in the keystore. If the alias does not exist, it will be created and associated with the newly-imported trusted certificate.

Exporting a certificate

As mentioned earlier, you can use the export command as follows to export a certificate into a file that is suitable for sending to another entity.

keytool -export -alias tom -file tomsfile.cer 

This command will export tom's certificate to the file named tomsfile.cer.

If tom is the alias for a key entry, the command exports the certificate at the bottom of the certificate chain in that keystore entry. This is the certificate that authenticates tom's public key.

If tom is the alias for a trusted certificate, that trusted certificate is exported.

Using the list command to display entire keystore database

You can use the list command to display the entire contents of a keystore database, or the contents associated with a particular alias.

If you specify an alias, only the information for that alias will be displayed. If you don't specify an alias, the entire contents of the keystore will be displayed.

Displaying an exported certificate

You can use the printcert command to display the contents of a certificate stored in a file that has been exported from a keystore. No password is required, and there is no required association with a keystore database. For example, the file may contain a certificate sent to you by another entity that you have not yet imported into your keystore.

Generating a certificate for an existing key pair

You can use the genkey command to create a public/private key pair and to wrap the public key in a self-signed certificate. In this case, you will need to provide a password for the keystore that is to contain the key entry as well as a password for the key. You will also be required to provide other information about the entity that will own the certificate.

It is also possible to create a new self-signed certificate using the key pair associated with a previously generated certificate. For example, if you change departments within your company, you may need a new certificate that properly reflects your new organizational unit. There are several steps involved in accomplishing this, which I won't attempt to discuss here. If you need to do this, see the JDK 1.2 documentation.

Certificate Programming

While JDK 1.2 does not provide the capability to create certificates under program control, it does provide the capability to import certificates and then to use them in a variety of ways. Some of those ways are illustrated in the sample program that follows.

Sample Program

Illustrates manipulation of certificates under program control

This program, named Security09, illustrates the manipulation of Digital Certificates under program control.

A self-signed certificate was previously created using the keytool program. This certificate was exported using keytool into two separate files named Security09A.cer and Security09C.cer.

The certificate exported into Security09A.cer was exported in the default binary format.

The certificate exported into Security09C.cer was exported into the RFC or Base 64 format.

Creates an X509Certificate object

This program reads each of those files and uses the contents of the file to create an X509Certificate object. Various methods of the object are invoked to display information contained in the certificate.

Verifies the certificate

The public key is extracted from the certificate and used to verify the certificate. Verification confirms that the certificate was signed using the private key that corresponds to the specified public key. The verify() method uses the signature verification engine supplied by the specified provider. In this case, the default provider (SUN) was used.

Since this was a self-signed certificate, it could be verified using the public key that it contains. If it were not a self-signed certificate, the public key of the issuer, instead of the public key contained in the certificate, would be required to verify it.

Program output

The program was tested using JDK 1.2 under Win95. The output from the program was as shown below. Since the two files, having different formats, were based on the same certificate, the output produced by processing the two files is identical.

Process RFC formatted certificate file
Subject:
CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, C=US
Issuer:
CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, C=US
Serial Number: 925161431
Valid from Mon Apr 26 16:17:11 CDT 1999
until Sun Jul 25 16:17:11 CDT 1999
Type: X.509
Certificate is verified

Process binary encoded certificate file
Subject:
CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, C=US
Issuer:
CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, C=US
Serial Number: 925161431
Valid from Mon Apr 26 16:17:11 CDT 1999
until Sun Jul 25 16:17:11 CDT 1999
Type: X.509
Certificate is verified

Interesting Code Fragments

Calling processCertFile()

With only one exception involving the use of a factory, this is a very simple program. The first fragment shows the entire main() method. This method makes two calls to the method named processCertFile() passing the names of the certificate files to be processed. All of the work is done in the method named processCertFile().

class Security09 {
  public static void main(String[] args) {
    try{
      System.out.println(
                 "Process RFC formatted certificate file");
      processCertFile("Security09C.cer");

      System.out.println(
              "\nProcess binary encoded certificate file");
      processCertFile("Security09A.cer");
    }catch(Exception e){System.out.println(e);}
  }//end main

Behavior of processCertFile()

The method named processCertFile()

However, the first two steps are not distinguishable in the code.

Get a FileInputStream

The first fragment gets a FileInputStream object linked to the file containing the certificate.

  static void processCertFile(String fileName)
                                         throws Exception{
    InputStream inStream = new FileInputStream(fileName);

Creating an X509Certificate object requires two steps

Two steps are involved in using the file to create a certificate object.

Creating a CertificateFactory object

The first step uses the getInstance() method of the CertificateFactory class to create an object of type CertificateFactory. The certificate type "X.509" is passed as a parameter resulting in a CertificateFactory object that complies with the X.509 standard. This step is shown in the next fragment.

The factory object will be used to actually create the certificate.

    CertificateFactory certFactory = 
                   CertificateFactory.getInstance("X.509");

Create the X509Certificate object

The next step invokes the generateCertificate() method on the factory object to create the actual certificate as an object of the X509Certificate class.

Note that the InputFileStream that was linked to the file containing the exported certificate in an earlier fragment is passed as a parameter to this method. Thus, this method

    X509Certificate certificate = 
                          (X509Certificate)certFactory.
                             generateCertificate(inStream);
    inStream.close();

The above fragment also closes the input stream.

Display information about the certificate

The next fragment invokes various methods on the certificate object to extract and display information about the certificate as shown earlier.

    System.out.println("Subject:\n" 
                   + certificate.getSubjectDN().getName());
    System.out.println("Issuer:\n" 
                    + certificate.getIssuerDN().getName());
    System.out.println("Serial Number: " 
               + certificate.getSerialNumber().toString());
    System.out.println("Valid from " 
             + certificate.getNotBefore()  
                 + "\nuntil " + certificate.getNotAfter());
    System.out.println("Type: " + certificate.getType());

Verify the certificate

The next fragment extracts the public key from the certificate and passes it to the verify() method in an attempt to verify the certificate. Verification confirms that the certificate was signed using the private key that corresponds to the specified public key. If the verification fails, one of several different exceptions will be thrown.

In this case, the verification is successful. A self-signed certificate should always verify against the public key stored in the certificate because that public key belongs to the person who issued the certificate. If it were not a self-signed certificate, the public key of the issuer, instead of the public key contained in the certificate, would be required to verify the certificate.

    PublicKey publicKey = certificate.getPublicKey();

    try{//to verify certificate against its own public key
      certificate.verify(publicKey);
      System.out.println("Certificate is verified");
    }catch(Exception ex){System.out.println(ex);}
  }//end processCertificateFile()
  
}//end class Security09

 

Program Listing

A complete listing of the program follows.

/*File Security09.java Copyright 1999, R.G.Baldwin
Rev 5/1/99

Illustrates the manipulation of Digital Certificates under
program control.

A self-signed certificate was previously created using the
keytool program.  This certificate was exported using
keytool into two separate files named Security09A.cer and
Security09C.cer.

The certificate exported into Security09A.cer was exported
in the default binary format.

The certificate exported into Security09C.cer was exported
into the RFC or Base 64 format.

This program reads each of those files and uses the 
contents of the file to create an X509Certificate object.
Various methods of the object are invoked to display
information contained in the certificate.

The public key is extracted from the certificate and used
to verify it.  Since this was a self-signed certificate,
it can be verified using the public key that it contains.
If it were not a self-signed certificate, the public key
of the issuer, rather than the public key contained in the
certificate, would be required to verify it.

Tested using JDK 1.2 under Win95.

Output from the program is:
  
Process RFC formatted certificate file
Subject:
CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, C=US
Issuer:
CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, C=US
Serial Number: 925161431
Valid from Mon Apr 26 16:17:11 CDT 1999
until Sun Jul 25 16:17:11 CDT 1999
Type: X.509
Certificate is verified

Process binary encoded certificate file
Subject:
CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, C=US
Issuer:
CN=Dick Baldwin, OU=CIS, O=ACC, L=Austin, ST=TX, C=US
Serial Number: 925161431
Valid from Mon Apr 26 16:17:11 CDT 1999
until Sun Jul 25 16:17:11 CDT 1999
Type: X.509
Certificate is verified

**********************************************************/

import java.io.*;
import java.security.*;
import java.security.cert.*;
import sun.misc.*;

class Security09 {

  public static void main(String[] args) {
    try{
      System.out.println(
                 "Process RFC formatted certificate file");
      processCertFile("Security09C.cer");

      System.out.println(
              "\nProcess binary encoded certificate file");
      processCertFile("Security09A.cer");
    }catch(Exception e){System.out.println(e);}
  }//end main
  //-----------------------------------------------------//

  //Reads exported certification file, creates certificate,
  // and displays information about the certificate.  
  static void processCertFile(String fileName)
                                         throws Exception{
    InputStream inStream = new FileInputStream(fileName);
    CertificateFactory certFactory = 
                   CertificateFactory.getInstance("X.509");
    X509Certificate certificate = 
                          (X509Certificate)certFactory.
                             generateCertificate(inStream);
    inStream.close();
    
    System.out.println("Subject:\n" 
                   + certificate.getSubjectDN().getName());
    System.out.println("Issuer:\n" 
                    + certificate.getIssuerDN().getName());
    System.out.println("Serial Number: " 
               + certificate.getSerialNumber().toString());
    System.out.println("Valid from " 
             + certificate.getNotBefore()  
                 + "\nuntil " + certificate.getNotAfter());
    System.out.println("Type: " + certificate.getType());
    
    PublicKey publicKey = certificate.getPublicKey();
    try{//to verify certificate against its own public key
      certificate.verify(publicKey);
      System.out.println("Certificate is verified");
    }catch(Exception ex){System.out.println(ex);}
  }//end processCertificateFile()
  
  //-----------------------------------------------------//

}//end class Security09

-end-