Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sun.security.validator.ValidatorException: SunCertPathBuilderException -while importing certificate

I am getting below Exception

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I have set the SSL certificate in the location

C:\Program Files\AdoptOpenJDK\jdk-11.0.9.11-hotspot\lib\security

keytool -import -keystore cacerts -file C:\Users\test\Desktop\Certificate\oCertificate.cer

But i am getting the above exception while i am hitting the server.

Results i saw I have added the certificate to the Jdk cacerts file but then it worked for two days than again i was getting the same error. I am unable to get it was working i am able to succesfully ping the server than again it is showing the exception.

like image 654
dhS Avatar asked Oct 25 '25 07:10

dhS


2 Answers

Is the problem you describe that running keytool to import the certificat gives you this error? Please provide the option -trustcacerts and see the documentation about this:

Import a New Trusted Certificate

Before you add the certificate to the keystore, the keytool command verifies it by attempting to construct a chain of trust from that certificate to a self-signed certificate (belonging to a root CA), using trusted certificates that are already available in the keystore.

If the -trustcacerts option was specified, then additional certificates are considered for the chain of trust, namely the certificates in a file named cacerts.

If the keytool command fails to establish a trust path from the certificate to be imported up to a self-signed certificate (either from the keystore or the cacerts file), then the certificate information is printed, and the user is prompted to verify it by comparing the displayed certificate fingerprints with the fingerprints obtained from some other (trusted) source of information, which might be the certificate owner. Be very careful to ensure the certificate is valid before importing it as a trusted certificate. The user then has the option of stopping the import operation. If the -noprompt option is specified, then there is no interaction with the user.

Source: https://docs.oracle.com/en/java/javase/11/tools/keytool.html

Alternatively you may find that keytool is not very user-friendly and you may enjoy other software like: https://keystore-explorer.org/downloads.html more.

Or if the problem is that your (TLS-client, or even TLS-server) software has some certificate issue it might be as jccampanero already suggested that the server might have switched to a different certificate, or for all I know the server may actually be several different servers behind a load-balancer which may not all have the same certificates. (Or maybe you installed some Java update that replaced the default cacerts file?)

In case of problems I highly recommend reading the JSSE-documentation and enabling debug logging with java option -Djavax.net.debug=all or maybe a little less than all like handshake see the Java 11 docs at:

https://docs.oracle.com/en/java/javase/11/security/java-secure-socket-extension-jsse-reference-guide.html#GUID-31B7E142-B874-46E9-8DD0-4E18EC0EB2CF

This shows the exact TrustStore your application uses, the certificate(s) that the server offers during the handshake and a lot of other negotiation stuff that is part of the TLS handshake.

If you prefer full control of who you trust to issue certificates you can configure your own truststore instead of the default that can live outside your Java installation with options like:

java -Djavax.net.ssl.trustStore=samplecacerts \
     -Djavax.net.ssl.trustStorePassword=changeit \
     Application

I trust that studying this debug logging should make it straightforward to resolve the issue, if it doesn't please provide us with some of the relevant logging.

like image 111
JohannesB Avatar answered Oct 26 '25 21:10

JohannesB


The error you reported indicates that your application is unable to establish a trusted SSL connection with the remote peer, because it is unable to find a valid certification path.

Which seems very strange to me is why it worked a few days ago and now it is not: perhaps the server changes the certificate, or maybe your setup change in some way.

The SSL configuration will be highly dependent on the software you are using to connect with the remote server: it can be different if you are using standard Java classes like URLConnection or HttpURLConnection, or libraries like Apache HttpClient or OkHttp, among others. The difference mainly has to do with if that piece of software uses or not Java Secure Socket Extension (JSSE) under the hood.

Assuming that you are using JSSE, in order to successfully configure your trust relationship, you need to properly configure a TrustManager, and more specifically, an X509TrustManager. From the docs:

The primary responsibility of the TrustManager is to determine whether the presented authentication credentials should be trusted.

Basically you can configure this X509TrustManager in two ways.

On on hand, you can create your own implementation. For example:

// This KeyStore contains the different certificates for your server
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(
  new FileInputStream("/path/to/serverpublic.keystore"),
  "yourserverpublickeystorepassword".toCharArray()
);

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // SunX509
tmf.init(keyStore);
TrustManager[] trustManagers = tmf.getTrustManagers();

SSLContext sslContext = SSLContext.getInstance("TLS");
// You can configure your client for mutual authentication 
// and/or provide a SecureRandom also if you wish
sslContext.init(null, trustManagers, null); 

Please, consider read this SO question for a complete example.

Or, on the other hand, as you are doing, you can configure the standard TrustManagerFactory properly.

As indicated in the above-mentioned documentation, the standard TrustManagerFactory uses the following process to try to find trust material, in the specified order:

  1. First, you can use the javax.net.ssl.trustStore system property to point to the keystone that contains your trusted server certificates when running the application. If the javax.net.ssl.trustStorePassword system property is also defined, then its value is used to check the integrity of the data in the truststore before opening it.
  2. If the javax.net.ssl.trustStore system property was not specified, then:
  • if the file java-home/lib/security/jssecacerts exists, that file is used;
  • if the file java-home/lib/security/cacerts exists, that file is used;
  • if neither of these files exists, then the SSL cipher suite is anonymous, does not perform any authentication, and thus does not need a truststore.

No matter the chosen mechanism used, you must be sure that the keystore contains all the necessary certificates to trust the remote server, not only the SSL certificate, but all the certificates in the certificate chain.

openssl provides an useful command that allows you to obtain all the certificates used in the SSL connection:

openssl s_client -showcerts -connect google.com:443

Of course, modify the domain as appropriate.

It will output different certificates; be sure to save each of them, including —–BEGIN CERTIFICATE—– and —–END CERTIFICATE—–, and include them in your keystore.

This handy utility can probably be of help for this purpose as well: as indicated in the project README, it basically will try to connect to the remote peer and save the necessary certificate information. This related article provides more information about the tool.

like image 23
jccampanero Avatar answered Oct 26 '25 21:10

jccampanero



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!