How to ignore PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException?

JavaSslCertificateSsl Certificate

Java Problem Overview


I got the following exception when try to post a request to a http server:

Here is the code I used

URL url = new URL(
		"https://www.abc.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setDoOutput(true);

DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
// wr.writeBytes(params);
wr.flush();
wr.close();

BufferedReader br = new BufferedReader(new InputStreamReader(
		conn.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
	System.out.println(line);
}

Here is the exception:

Exception in thread "main" 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
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1731)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
	at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
	at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
	at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1014)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
	at com.amazon.mzang.tools.httpchecker.CategoryYank.getPV(CategoryYank.java:32)
	at com.amazon.mzang.tools.httpchecker.CategoryYank.main(CategoryYank.java:18)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
	at sun.security.validator.Validator.validate(Validator.java:218)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185)
	... 13 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)
	... 19 more

The server is not owned by me. Is there a way to ignore this exception?

Java Solutions


Solution 1 - Java

If you want to ignore the certificate all together then take a look at the answer here: https://stackoverflow.com/questions/6047996/ignore-self-signed-ssl-cert-using-jersey-client

Although this will make your app vulnerable to man-in-the-middle attacks.

Or, try adding the cert to your java store as a trusted cert. This site may be helpful. http://blog.icodejava.com/tag/get-public-key-of-ssl-certificate-in-java/

Here's another thread showing how to add a cert to your store. https://stackoverflow.com/questions/6755180/java-ssl-connect-add-server-cert-to-keystore-programatically

The key is:

KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(someCert);
ks.setEntry("someAlias", newEntry, null);

Solution 2 - Java

I have used the below code to override the SSL checking in my project and it worked for me.

package com.beingjavaguys.testftp;

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

/**
 * Fix for Exception in thread "main" 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
 */
public class ConnectToHttpsUrl {
	public static void main(String[] args) throws Exception {
		/* Start of Fix */
		TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
			public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
			public void checkClientTrusted(X509Certificate[] certs, String authType) { }
			public void checkServerTrusted(X509Certificate[] certs, String authType) { }

		} };

		SSLContext sc = SSLContext.getInstance("SSL");
		sc.init(null, trustAllCerts, new java.security.SecureRandom());
		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

		// Create all-trusting host name verifier
		HostnameVerifier allHostsValid = new HostnameVerifier() {
			public boolean verify(String hostname, SSLSession session) { return true; }
		};
		// Install the all-trusting host verifier
		HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
		/* End of the fix*/

		URL url = new URL("https://nameofthesecuredurl.com");
		URLConnection con = url.openConnection();
		Reader reader = new InputStreamReader(con.getInputStream());
		while (true) {
			int ch = reader.read();
			if (ch == -1) 
				break;
			System.out.print((char) ch);
		}
	}
}

Solution 3 - Java

Set validateTLSCertificates property to false for your JSoup command.

Jsoup.connect("https://google.com/").validateTLSCertificates(false).get();

Solution 4 - Java

FWIW, on Ubuntu 10.04.2 LTS installing the ca-certificates-java and the ca-certificates packages fixed this problem for me.

Solution 5 - Java

I got the same error while executing the below spring-boot + RestAssured simple test.

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static com.jayway.restassured.RestAssured.when;
import static org.apache.http.HttpStatus.SC_OK;

@RunWith(SpringJUnit4ClassRunner.class)
public class GeneratorTest {

@Test
public void generatorEndPoint() {
    when().get("https://bal-bla-bla-bla.com/generators")
            .then().statusCode(SC_OK);
    }
}

The simple fix in my case is to add 'useRelaxedHTTPSValidations()'

RestAssured.useRelaxedHTTPSValidation();

Then the test looks like

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static com.jayway.restassured.RestAssured.when;
import static org.apache.http.HttpStatus.SC_OK;

@RunWith(SpringJUnit4ClassRunner.class)
public class GeneratorTest {

@Before
public void setUp() {
   RestAssured.useRelaxedHTTPSValidation();
}


@Test
public void generatorEndPoint() {
    when().get("https://bal-bla-bla-bla.com/generators")
            .then().statusCode(SC_OK);
    }
}

Solution 6 - Java

If the issue is a missing intermediate certificate, you can enable Oracle JRE to automatically download the missing intermediate certificate as explained in this answer.

Just set the Java system property -Dcom.sun.security.enableAIAcaIssuers=true

For this to work the server's certificate must provide the URI to the intermediate certificate (the certificate's issuer). As far as I can tell, this is what browsers do as well and should be just as secure - I'm not a security expert though.

Edit: If I recall correctly, this seems to work at least with Java 8 and is documented here for Java 9.

Solution 7 - Java

If you're using CloudFoundry then you'd have to explicitly push the jar along with the keystore having the certificate.

Solution 8 - Java

I also came across the same issue. I was trying to build the project with a clean install goal. I simply changed it to clean package -o in the run configuration. Then I re-built the project and it worked for me.

Solution 9 - Java

I also faced this issue. I was having JDK 1.8.0_121. I upgraded JDK to 1.8.0_181 and it worked like a charm.

Solution 10 - Java

I also have the same problem on Apache Tomcat/7.0.67 and Java JVM Version: 1.8.0_66-b18. Just upgrading to JRE 1.8.0_241 it seems the issue was solved.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDeepNightTwoView Question on Stackoverflow
Solution 1 - Javakm1View Answer on Stackoverflow
Solution 2 - JavaKishore KumarView Answer on Stackoverflow
Solution 3 - JavaZahid HasanView Answer on Stackoverflow
Solution 4 - JavaslimView Answer on Stackoverflow
Solution 5 - JavaPraveenView Answer on Stackoverflow
Solution 6 - JavaBen RombergView Answer on Stackoverflow
Solution 7 - JavaSmart CoderView Answer on Stackoverflow
Solution 8 - JavaChetan PatilView Answer on Stackoverflow
Solution 9 - JavaOsanda DeshanView Answer on Stackoverflow
Solution 10 - JavaespajavaView Answer on Stackoverflow