Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
This lesson explains why digital signatures, certificates, and keystores are needed. The lesson also compares use of the tools versus the JDK Security API with respect to generating signatures. Such tool usage is demonstrated in the next two lessons, Signing Code and Granting It Permissions and Exchanging Files. API usage is demonstrated in the Generating and Verifying Signatures lesson.
This lesson contains the following sections
If you electronically send someone an important document (or documents), or an applet or application to run, the recipient needs a way to verify that the document or code came from you and was not modified in transit (for example, by a malicious user intercepting it). Digital signatures, certificates, and keystores all help ensure the security of the files you send.
The basic idea in the use of digital signatures is as follows.
keytool
or security API methods. That is, you generate a digital signature for the document or code, using the jarsigner
tool or Security API methods.A recipient needs to ensure that your public key itself is authentic before he/she can use it to verify that your signature is authentic. Therefore, you will usually supply a certificate that contains your public key together with the key of a Certificate Authority who can vouch for your key's authenticity. See the next section for details.
For more information about the terminology and concepts of signing and verification, and further explanation of the benefits, see the Signing JAR Files section of the "The Packaging Programs in JAR Files" lesson.
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 can itself be stored within another certificate whose signature can also be verified by using the public key of that next 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 a trust chain, then he/she can calculate the the certificate fingerprint(s), using the keytool
-import
or -printcert
command. A fingerprint is a relatively short number that uniquely and reliably identifies the certificate. (Technically, the fingerprint is a hash value of the certificate information, using a message digest function.) The recipient can then phone the certificate owner and compare the fingerprint values of the received certificate with 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.
Self-signing a certificate is useful for developing and testing an application. However, before deploying to users, 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, perhaps by checking your driver's license or other information. The CA then vouches for your 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 accomplished by:
jarsigner
tool (if the document/code and signature appear in a JAR file),If you are sending signed code or documents to others, you need to supply them with 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 who receives the certificate can import it into the keystore as a trusted certificate, using, for example, 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. The tool then stores them, along with the signature, in the JAR file.
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 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 key. An alias may also identify the purpose of the key. For example, the alias signPersonalEmail
might be used to identify a keystore entry whose private key is used for signing personal e-mail, and the 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 to modify a keystore.
Note the following regarding use of the tools and the API related to digital signatures.
jar
tool. A JAR file is a good way of encapsulating multiple files in one spot. When a file is "signed", the resulting digital signature bytes need to be stored somewhere. When a JAR file is signed, the signature can go in the JAR file itself. This is what happens when you use the jarsigner
tool to sign a JAR file.jarsigner
tool to verify the authenticity of a JAR file signature, the person/organization that received the JAR file first needs to import into their keystore a certificate authenticating the public key corresponding to the private key used to sign the code.The Generating and Verifying Signatures shows you how to use the JDK Security API to sign documents. The lesson 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
This lesson also shows you alternative ways to import and supply keys, including certificates.
The Signing Code and Granting It Permissions lesson shows how to use Java Security tools to place your code into a JAR file, sign it, and export your public key. Then it shows how your recipient can use these same Java tools to import your public key certificate and then add an entry to a policy file that will grant your code the permission it needs to access system resources controlled by your recipient.
The
Exchanging Files lesson you how to use Java security tools to sign a document and then export the public key certificate for the public key using keytool
. corresponding to the private key used to sign that document using keytool
. Then it shows how your recipient can verify your signature by installing your public key certificate and then using the jarsigner
tool to verify your signature.
These two lessons have much in common. In both cases, the first two steps for the code or document sender are to:
jar
tool.keytool
-genkey
command.The next two steps are optional:
keytool
-certreq
command; then send the resulting certificate signing request to a certification authority (CA) such as VeriSign.keytool
-import
command to import the CA's response.The next two steps are required:
jarsigner
tool and the private key generated earlier.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 import the certificate as a trusted certificate, using the keytool
-import
command. The keytool
will attempt to construct a trust chain from the certificate to be imported to an already trusted certificate in the keystore. If that fails, the keytool
will display the certificate fingerprint and prompt you to verify it.
If what was sent was code, the receiver also needs to modify a policy file to permit the required resource accesses to code signed by the private key corresponding to the public key in the imported certificate. The Policy Tool can be used to do this.
If what was sent was one or more documents, the receiver needs to verify the authenticity of the JAR file signature, using the jarsigner
tool.
This lesson discusses the two optional steps. The other steps are covered in the next two lessons, Signing Code and Granting It Permissions and Exchanging Files .
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 is adequate when developing and testing an application.
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 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 authenticates you, the requestor ("subject"), and then signs and returns a certificate authenticating your public key. By signing the certificate, the CA vouches that you are the owner of the public key.
In some cases, the CA will return a chain of certificates, each one authenticating the public key of the signer of the previous certificate in the chain.
After submitting 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, the CA's signature on the certificate, or on the final certificate in the chain the CA sends to you in response to your CSR, can be verified.
Before you import the certificate reply from a CA, you need one or more "trusted certificates" in your keystore or in the cacerts
file.
The cacerts
file represents a system-wide keystore with CA certificates. This file resides in the JRE security properties directory, java.home/lib/security
, where java.home is the JRE installation directory.
IMPORTANT: Verify Your cacerts
File
Since you trust the CAs in the cacerts
file as entities for signing and issuing certificates to other entities, you must manage the cacerts
file carefully. The cacerts
file should contain only certificates of the CAs you trust. It is your responsibility to verify the trusted root CA certificates bundled in the cacerts
file and make your own trust decisions. To remove an untrusted CA certificate from the cacerts
file, use the delete option of the keytool
command. You can find the cacerts
file in the JRE installation directory. Contact your system administrator if you do not have permission to edit this file.
The cacerts
file contains a number of trusted CA certificates. If you sent your CSR to one of these trusted vendors (such as VeriSign), you won't need to import the vendor's root 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 that company ABC, Inc., is a CA and that you obtain a file named ABCCA.cer
, purportedly a self-signed certificate from ABC, authenticating that CA's public key.
Be very careful to ensure that 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, you can add it to your keystore via a command such as the following:
keytool -import -alias alias -file ABCCA.cer -keystore storefile
This command 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.
Once you've imported the required trusted certificate(s), as described in the previous section, or they are already 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) by using the certificate reply and trusted certificates that are already available in the keystore or in the cacerts
keystore file.
As an example, suppose that you sent your certificate signing request to VeriSign. You can then import the reply via the following, which assumes that 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 by using trusted certificates from the keystore and optionally by 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 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 whether 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 be replaced only if a valid keypass, the password used to protect the private key of the entry, is supplied. If no password is provided and if 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: