90

I have been getting:

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

Searching on how to resolve this exception I have come across the term Keystore which I do not understand. What is Keystore in simple terms? How it is related to SSL?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
saplingPro
  • 20,769
  • 53
  • 137
  • 195
  • 2
    simple terms: "In Java, a keystore is a repository of security certificates, either authorization certificates or public key certificates" – tutak Apr 21 '14 at 17:12
  • 2
    @BheshGurung I am aware of the docs. But I want it in a layman. What is it and its need ? What it has to do with SSL exception ? – saplingPro Apr 21 '14 at 17:12
  • @BheshGurung So for my `localhost` to communicate with a remote server via SSL, localhost should possess some kind of certificate ? – saplingPro Apr 21 '14 at 17:18
  • @BheshGurung You could elaborate and explain all this in an answer. That will be more beneficial – saplingPro Apr 21 '14 at 17:20
  • nobody answered.. strange....I also encountered the same question today... – Jayesh Nov 12 '14 at 07:07
  • @Jayesh Please see my answer below. – Zeemee Nov 12 '14 at 07:44

3 Answers3

183

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).

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
  • I just tried to connect to "https://google.com" and it gave me success without any keystore issue, so I was just wondering how it worked, why java didn't gave same error while connecting to "https://google.com"? – Jayesh Nov 13 '14 at 08:36
  • can you please help me with flow, like. 1. user tries to connect to some "https" site. 2. server refuses the connection or required connection to be established from known host. can you please explain me in that way or point any link where it is explained. – Jayesh Nov 13 '14 at 08:38
  • 5
    @Jayesh As I said, there is a default truststore. It contains a number of CA certificates that the JRE already trusts, including one that verifies google.com. Your second question (about a refused connection) has nothing to do with keystores: if the server refuses the connection, that's it, the connection is refused... Nothing happens. – Bruno Nov 13 '14 at 12:50
  • Thanks Bruno. so can i say like, when we try to access https website, server returns with its certificate, then java client checks that certificate is present in its keystore, if it is present then client to server communication starts getting encrypted using that key. if not present then using apache http client, we will not able to access https website until and unless we get the certificate from remote server and store it in our java keystore. am I correct? – Jayesh Nov 13 '14 at 15:31
  • 5
    @Jayesh Not quite. The server cert doesn't necessarily need to be in the truststore, but at least a CA cert that can validate the server cert. Saying that "*the communication starts getting encrypted using [the certificate's] key*" is certainly not correct: that's not how SSL/TLS works, but that's a whole different matter. In general, yes, if you truststore doesn't contain a CA cert that can be used to verify the server cert (or the CA cert itself), you won't be able to connect, unless you've also disabled certificate verification in your code (which you shouldn't). – Bruno Nov 13 '14 at 15:36
  • Thanks Bruno... much clear now. can you point any link where this information is given at low level explanation. – Jayesh Nov 14 '14 at 06:31
  • Thank you very much for this wonderful answer. Briefly explained to the point. – Patze Apr 30 '19 at 08:29
13

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zeemee
  • 10,486
  • 14
  • 51
  • 81
  • 5
    You're using a very specific subset of the notion of keystore. In particular, you're talking about the default truststore. – Bruno Nov 12 '14 at 13:43
0

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
Daria Pydorenko
  • 1,754
  • 2
  • 18
  • 45
saba
  • 332
  • 2
  • 14