Keystore 是什么?

我一直在想:

sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find
valid certification path to requested target
.
.
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.
ValidatorException: PKIX path building failed: sun.security.provider.
certpath.SunCertPathBuilderException: unable to find valid certification
path to requested target

在寻找如何解决这个异常,我遇到了术语 Keystore,我不明白。用简单的术语来说,Keystore 是什么?它与 SSL 有什么关系?

95175 次浏览

Simply speaking, to establish a connection to an SSL-endpoint, you have to trust its public certificate. To trust a certificate, either itself or the certificate of its issuer has to be in the keystore.

Think of the keystore as a set of folders or a database/repository which contains certificates. Physically, it is a file in the JRE (/lib/security/cacerts).

This repository can be modified with the keytool command that ships with the JRE. See this link for some common commands. Another way is to use the Certificate Dialog of the Java Control Panel (this is also installed with the JRE):

Certificate Dialog

Keystore in Java can refer to three things, depending on the context. (They're all closely related but subtly different.)

  • A keystore can be a repository where private keys, certificates and symmetric keys can be stored. This is typically a file, but the storage can also be handled in different ways (e.g. cryptographic token or using the OS's own mechanism.)

  • KeyStore is also a class which is part of the standard API. It is essentially a way to load, save and generally interact with one of the "physical" keystores as described above. A KeyStore can also be purely in memory, if you just need the API abstraction for your application.

    How to load and handle such a KeyStore instance depends on the format of the keystore file (or other storage system) that backs it. Multiple formats are available. Some of the most common are JKS and PKCS#12 (.p12).

  • "keystore" can also be used as the counterpart of "truststore". This is where it can get confusing, since both "keystore" and "truststore" are keystores, they're just used for different purposes. You can find more details in this answer. The keystore is used to initialise the key manager, whereas the truststore is used to initialise the trust manager. From the JSSE reference guide:

    • A TrustManager determines whether the remote authentication credentials (and thus the connection) should be trusted.

    • A KeyManager determines which authentication credentials to send to the remote host.

    Essentially, a keystore used as a truststore will contain a number of (CA) certificates that you're willing to trust: those are the trust anchors you are going to use to verify remote certificates you don't already know and trust. In contrast, a keystore used as a keystore will contain your own certificate and its private key: this is what you're going to use to authenticate yourself to a remote party (when required).

    There is a default truststore bundled with the JRE (/lib/security/cacerts). There isn't a default keystore, since it's usually a more explicit step for the user.

In the context of SSL/TLS, a keystore (keystore used as a keystore) will be where a server stores its certificate and private key (or, when client-certificate authentication is used, where the client stores its certifcate and private key). A truststore (keystore used as a truststore) will be where the client stores the CA certificates of the CAs it is willing to trust, so as to be able to verify the server certificate when making a connection to an SSL/TLS server (similarly, on the server side, this is also where the CA certificates used to verify the client certificates are stored).

Typically, the error you're getting ("ValidatorException: PKIX path building failed") happens when the certificate of the server you're connecting to cannot be verified using any certificate in the truststore you're using. You would generally need to have in your truststore either the server certificate directly in your truststore (which is only manageable on a small scale) or the CA certificate of the CA used to issue that server certificate (or one of the certificates in the chain it presents, when there is a chain).

I had this problem too because I was importing a certificate in a JDK that wasn't used by my java program so check the current JDK of you're program then run key tool command:

keytool -importcert –trustcacerts -alias [certificate name] -keystore "C:\Program Files\Java\jdk1.7.0_71\jre\lib\security\cacerts" -storepass changeit -file [certificate name].cer