Previous | Next | Trail Map | Security in JDK 1.2  | Contents

API and Tools Use for Secure Code and File Exchanges


Note: This section contains overview information that may be helpful in understanding why digital signatures, certificates, and keystores are needed. It also compares use of the tools vs. the JDK Security API with respect to generating signatures. Such tool usage is demonstrated in the Signing Code and Granting It Permissions(in the Java Security 1.2 trail) and Exchanging Files(in the Java Security 1.2 trail) lessons, while API usage is demonstrated in the Generating and Verifying Signatures(in the Java Security 1.2 trail) lesson.

Introduction

If you electronically send an important document (or documents) to someone, or you supply them an applet or application to run, they need a way of verifying that the document or code came from you and was not modified in transit (for example, by a malicious user intercepting it).

Here's where digital signatures come in.

Digital Signatures

The basic idea in the use of digital signatures is the following:
  1. You "sign" the document or code using one of your private keys (which you can generate using keytool or security API methods). That is, you generate a digital signature for the document or code, using the jarsigner tool or API methods.

  2. You send the other person (the "receiver") the document or code and the signature.

  3. You also supply the receiver the public key corresponding to the private key used to generate the signature, if they don't already have it.

  4. Using the public key, the receiver can verify the authenticity of the signature and the integrity of the document/code.

Actually, a receiver needs to ensure the public key itself is authentic before they can reliably use it to check the signature's authenticity. It is more typical to supply a certificate containing the public key rather than just the public key itself, as discussed in the next section.

For more information about the terminology and concepts of signing and verification, and further explanation of the benefits, see the Understanding Signing and Verification(in the Learning the Java Language trail) section of the "The Java Archive (JAR) File Format" trail.

Certificates

A certificate contains One way for a recipient to check whether a certificate is valid is by verifying its digital signature using its issuer's (signer's) public key. That key may itself be stored in another certificate whose signature can be verified using the public key of that other certificate's issuer, and that key may also be stored in yet another certificate, and so on; you can stop checking when you reach a public key that you already trust and use it to verify the signature on the corresponding certificate.

If the recipient cannot establish such a trust chain (for example, because the required issuer certificates are not available), the certificate fingerprint(s) can be calculated (for example, as may be done by the keytool -import or -printcert command). Each fingerprint is a relatively short number that uniquely and reliably identifies the certificate. (Technically, it's a hash value of the certificate information, using a message digest function.) The recipient can call up the certificate owner and compare the fingerprints of the received certificate with those of the certificate that was sent. If the fingerprints are the same, the certificates are the same.

Thus, you can ensure that a certificate was not modified in transit. One other potential uncertainty when working with certificates is the identity of the sender.

Sometimes a certificate is self-signed, that is, signed using the private key corresponding to the public key in the certificate; the issuer is the same as the subject.

This is ok if the receiver already knows and trusts the sender.

Otherwise, the sender needs to obtain a certificate from a trusted third party, referred to as a Certification Authority (CA). To do so, you send a self-signed Certificate Signing Request (CSR) to the CA. The CA verifies the signature on the CSR and your identity (for example, by checking your driver's license or other information). The CA then vouches for you being the owner of the public key by issuing a certificate and signing it with its own (the CA's) private key. Anybody who trusts the issuing CA's public key can now verify the signature on the certificate. In many cases, the issuing CA itself may have a certificate from a CA higher up in the CA hierarchy, leading to certificate chains.

Certificates of entities you trust are typically imported into your keystore as "trusted certificates." The public key in each such certificate may then be used to verify signatures generated using the corresponding private key. Such verifications can be done by

If you are sending signed code or documents to others, you need to supply them the certificate containing the public key corresponding to the private key used to sign the code/document. The keytool -export command or API methods can export your certificate from your keystore to a file, which can then be sent to anyone needing it. A person that receives the certificate can import it into their keystore as a trusted certificate, for example, using API methods or the keytool -import command.

If you use the jarsigner tool to generate a signature for a JAR file, the tool retrieves your certificate and its supporting certificate chain from your keystore and stores them, along with the signature, in the JAR file.

Keystores

Private keys and their associated public-key certificates are stored in password-protected databases called keystores. A keystore can contain two types of entries: the trusted certificate entries discussed above, and key/certificate entries, each containing a private key and the corresponding public key certificate. Each entry in a keystore is identified by an alias.

A keystore owner can have multiple different keys in the keystore, accessed via different aliases. An alias is typically named after a particular role in which the keystore owner uses the associated private key. It may also identify the purpose of the key. For example, an alias "signPersonalEmail" might be used to identify a keystore entry whose private key is used for signing personal email, and an alias "signJarFiles" might be used to identify an entry whose private key is used for signing JAR files.

The keytool tool can be used to

API methods can also be used to access and modify a keystore.

Tool and API Notes:

Please note the following regarding use of the tools and the API related to digital signatures:

Use of the JDK Security API to Sign Documents

The Generating and Verifying Signatures(in the Java Security 1.2 trail) lesson demonstrates the use of the JDK Security API with respect to signing documents. It shows what one program, executed by the person who has the original document, would do to Then it shows an example of another program, executed by the receiver of the data, signature, and public key. It shows how the program could That lesson also discusses and demonstrates possible alternative approaches and methods of supplying and importing keys, including in certificates.

Use of the Tools to Sign Code or Documents

The Signing Code and Granting It Permissions(in the Java Security 1.2 trail) lesson shows use of the tools by a code developer to put the code in a JAR file, sign it, export the public key, and so on. Then it shows use of the tools by someone who will run the code (or a sysadmin) to import the signer's public key certificate and add an entry in a policy file granting the code permission for the resource accesses it needs.

The Exchanging Files(in the Java Security 1.2 trail) lesson shows use of the tools by one person to sign an important document, such as a contract, and export the public key certificate for the public key corresponding to the private key used to sign the contract. Then it shows how another person receiving the contract, the signature, and the public key certificate would use keytool to import the certificate and the jarsigner tool to verify the signature.

These two lessons have much in common. The steps they use are almost exactly the same, except with respect to the details as to the "distinguished name" information of the signer you will pretend to be, and whether you will store a data file or a class file in the JAR file to be signed. In both cases, the main steps for the code or document sender are:

  1. Create a JAR file containing the document or class file, using the jar tool.

  2. Generate keys (if they don't already exist), using the keytool -genkey command.

  3. (Optional) Generate a Certificate Signing Request (CSR) for the public key certificate, using the keytool -certreq command, and then send the CSR to a Certification Authority (CA) such as Verisign.

  4. (Optional) Import the response from the CA, using the keytool -import command.

  5. Sign the JAR file, using the jarsigner tool and the private key generated in Step 2.

  6. Export the public key certificate, using the keytool -export command. Then supply the signed JAR file and the certificate to the receiver.
In both cases, the receiver of the signed JAR file and the certificate should If what was sent was code, the receiver also needs to If what was sent was one or more documents, the receiver needs to

For further information regarding the tools, see Tools Summary.

The two optional steps are described further below.

Generating a Certificate Signing Request (CSR) for a Public Key Certificate

When keytool is used to generate public/private key pairs, it creates a keystore entry containing a private key and a self-signed certificate for the public key. (That is, the certificate is signed using the corresponding private key.)

This may be adequate if the people receiving your signed files already know and trust your identity.

However, a certificate is more likely to be trusted by others if it is signed by a Certification Authority (CA).

To get a certificate signed by a CA, you first generate a Certificate Signing Request (CSR), via a command such as the following:

keytool -certreq -alias alias -file csrFile 
Here, alias is the alias used to access the keystore entry containing the private key and the public key certificate, and csrFile specifies the name to be used for the CSR created by this command.

You then submit this file to a CA, such as VeriSign, Inc. The CA will authenticate you, the requestor ("subject"), usually off-line, and then will return a certificate, signed by them, authenticating your public key. That is, they vouch for you, the subject, being the owner of the public key by signing the certificate. (In some cases, they will actually return a chain of certificates, each one authenticating the public key of the signer of the previous certificate in the chain.)

Importing the Response from the CA

If you submitted a Certificate Signing Request (CSR) to a Certification Authority (CA), you need to replace the original self-signed certificate in your keystore with a certificate chain by importing the certificate (or chain of certificates) returned to you by the CA.

But first, you need a "trusted certificate" entry in your keystore (or in the cacerts keystore file, described below) that authenticates the CA's public key. With such an entry, the CA's signature can be verified. That is, their signature on the certificate, or on the final certificate in the chain they send to you in response to your CSR, can be verified.

Importing a Certificate from a CA as a "Trusted Certificate"

Before you import the certificate reply from a CA, you need one or more "trusted certificates" in your keystore or in the cacerts file:

  • If the certificate reply is a certificate chain, you just need the top certificate of the chain (i.e., the "root" CA certificate authenticating that CA's public key).

  • If the certificate reply is a single certificate, you need a certificate for the issuing CA (the one that signed it), and if that certificate is not self-signed, you need a certificate for its signer, and so on, up to a self-signed "root" CA certificate.

The cacerts file represents a system-wide keystore with CA certificates. It resides in the JDK security properties directory, java.home/lib/security, where java.home is the JDK installation directory.

The cacerts file currently ships with five VeriSign root CA certificates. If you sent your CSR to VeriSign, you won't need to import a VeriSign certificate as a trusted certificate in your keystore; you can go on to the next section to see how to import the certificate reply from the CA.

A certificate from a CA is usually either self-signed, or signed by another CA (in which case you also need a certificate authenticating that CA's public key). Suppose company ABC, Inc., is a CA, and you obtain a file named "ABCCA.cer" that is purportedly a self-signed certificate from ABC, authenticating that CA's public key.

Be very careful to ensure the certificate is valid prior to importing it as a "trusted" certificate! View it first (using the keytool -printcert command, or the keytool -import command without the -noprompt option), and make sure that the displayed certificate fingerprint(s) match the expected ones. You can call the person who sent the certificate, and compare the fingerprint(s) that you see with the ones that they show (or that a secure public key repository shows). Only if the fingerprints are equal is it guaranteed that the certificate has not been replaced in transit with somebody else's (for example, 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.

If you trust that the certificate is valid, then you can add it to your keystore via a command like the following:

keytool -import -alias alias -file ABCCA.cer -keystore storefile 
This creates a "trusted certificate" entry in the keystore whose name is that specified in storefile. The entry contains the data from the file ABCCA.cer, and it is assigned the specified alias.

Importing the Certificate Reply from the CA

Once you've imported a certificate authenticating the public key of the CA you submitted your certificate signing request to (or there's already such a certificate in your keystore or in the cacerts file), you can import the certificate reply and thereby replace your self-signed certificate with a certificate chain. This chain will be either the one returned by the CA in response to your request (if the CA reply is a chain), or one constructed (if the CA reply is a single certificate) using the certificate reply and trusted certificates that are already available in the keystore or in the cacerts keystore file.

As an example, suppose you sent your certificate signing request to VeriSign. You can then import the reply via the following, which assumes the returned certificate is in the file specified by certReplyFile:

keytool -import -trustcacerts -keystore storefile -alias alias  
   -file certReplyFile 

Type this command on one line.

The certificate reply is validated using trusted certificates from the keystore, and optionally using the certificates configured in the cacerts keystore file (if the -trustcacerts option is specified). Each certificate in the chain is verified using the certificate at the next level higher up in the chain. You need to trust only the top-level "root" CA certificate in the chain. If you do not already trust the top-level certificate, keytool will display the fingerprint of that certificate and ask you if you want to trust it.

The new certificate chain of the specified (by alias) entry replaces the old certificate (or chain) associated with this entry. The old chain can only be replaced if a valid keypass, the password used to protect the private key of the entry, is supplied. If no password is provided, and the private key password is different from the keystore password, the user is prompted for it.

For more detailed information about generating CSRs and importing certificate replies, see the keytool documentation on the public java.sun.com web site:


Previous | Next | Trail Map | Security in JDK 1.2  | Contents