Will the cross root cover trust by the default list in the JDK/JRE?

Hi, this is the output of keytool -list

lets-encrypt-x2, 20/01/2016, trustedCertEntry, 
Huella Digital de Certificado (SHA1): 02:00:7A:05:CE:D3:68:99:AA:8A:03:A2:CF:30:7F:1C:04:49:FC:31
lets-encrypt-x1, 20/01/2016, trustedCertEntry, 
Huella Digital de Certificado (SHA1): 3E:AE:91:93:7E:C8:5D:74:48:3F:F4:B7:7B:07:B4:3E:2A:F3:6B:F4
isrgrootx1, 20/01/2016, trustedCertEntry, 
Huella Digital de Certificado (SHA1): CA:BD:2A:79:A1:07:6A:31:F2:1D:25:36:35:CB:03:9D:43:29:A5:E8
signfiles, 20/01/2016, PrivateKeyEntry, 
Huella Digital de Certificado (SHA1): 38:11:0A:E1:0C:00:31:6C:AF:84:9A:DA:98:B9:10:F1:DA:EA:9A:86
letsencryptauthorityx1, 20/01/2016, trustedCertEntry, 
Huella Digital de Certificado (SHA1): E0:45:A5:A9:59:F4:27:80:FA:5B:D7:62:35:12:AF:27:6C:F4:2F:20

My program is still returning:
```sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target````

What should I check?

What about getting cross signature from another authority that’s already in java keystore in older versions as well?
The problem is still present with jre 1.8.0_71.

FYI: problem is still here with jdk-8u74.
It seems that, at least under Linux debian/ubuntu/mint/…, OpenJDK installer symlinks $JAVA_HOME/jre/lib/secutity/cacerts to /etc/ssl/certs/java/cacerts in order to have all certifications centralized.
Oracle JDK/JRE rely on it’s own internal cacerts (as expected).
I “solved” the problem doing the same with my hand-installed Oracle JDK:

cd $JAVA_HOME/jre/lib/security/ && mv cacerts cacerts-orig && ln -s /etc/ssl/certs/java/cacerts .

To solve the problem it might be enough to provide a specialized installer for Oracle JDK.

I still get SunCertPathBuilderException even with your code. I’m using Unirest which uses Apache HttpComponents.

Could you give the following a try?
Just change the URL part to your ssl enabled site (which is signed by letsencrypt):

package com.sandbox;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

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.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class CheckSSL {

public static void main(String[] args) throws Exception {
    URL oracle = new URL("https://yoursslsitewhichissignedbytheca/");
    URLConnection yc = oracle.openConnection();
    BufferedReader in = new BufferedReader(new InputStreamReader(
    String inputLine;
    while ((inputLine = in.readLine()) != null)

public static void addRootCA() throws Exception {
	InputStream fis = new BufferedInputStream(new FileInputStream("target/classes/dst_root_ca_x3.pem"));
	Certificate ca = CertificateFactory.getInstance("X.509").generateCertificate(fis);

	KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
	ks.load(null, null);
	ks.setCertificateEntry(Integer.toString(1), ca);

	TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

	SSLContext ctx = SSLContext.getInstance("TLS");
	ctx.init(null, tmf.getTrustManagers(), null);		

public static void disableCertificateValidation() {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] { 
      new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() { 
          return new X509Certificate[0]; 
        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
        public void checkServerTrusted(X509Certificate[] certs, String authType) {}

    // Ignore differences between given hostname and certificate hostname
    HostnameVerifier hv = new HostnameVerifier() {
      public boolean verify(String hostname, SSLSession session) { return true; }

    // Install the all-trusting trust manager
    try {
      SSLContext sc = SSLContext.getInstance("SSL");
      sc.init(null, trustAllCerts, new SecureRandom());
    } catch (Exception e) {}


And if that doesn’t work, try using the disableCertificateValidation() instead of addRootCA() in the main method

Thanks for offering this fix. I just spent $15 and half an hour to make the problem go away for three years, so I’m not really in a position to test it now.

I see my own reply up above here, but suddenly I have the issue again:

Server access Error: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target url=https://repo.woodenstake.se/content/groups/All/se/hedefalk/lift-utils_2.5_2.11/0.1/lift-utils_2.5_2.11-0.1.pom

Even though I follow my own instructions above of importing isrgrootx1 and letsencryptauthorityx1, the problem persists. The only thing I can think of is that I have gone to using SAN extensions for all my subdomains in one cert. Or that the root cert has changed?

Oh, it’s the later:

The X1 and X2 intermediates were our first generation of intermediates. We’ve replaced them with new intermediates that are more compatible with Windows XP.


So, I guess I’m gonna have to do this again a few times so made a small script, might be useful for someone else:

You shouldn’t need to store (and probably shouldn’t store) the intermediate certs in the root trust store. Rather, add both the ISRG root and the DST root. All the certs made right now with the letsencrypt client use an intermediate chained back to the DST root because it has wider trust acceptance.


Since @pfg mention this topic as relevant for oracle jdk root inclusion.
It would be nice to get an update if there is any progress or timeline.

Getting LE-verified site e.g. https://gethttpsforfree.com/ fails for current latest Oracle java (1.8.0_91).

Oracle needs to add IdenTrust’s DST Root X3 to Java in order for things to work by default. I’ve been notified by Oracle that they have accepted the root into their program and that it will ship in a software update. I don’t know when that software update will ship, unfortunately.


Very good news!
Do you know at least if it will be in a major update (i.e. JRE 9) or in a minor update?


1 Like

The ticket at https://bugs.openjdk.java.net/browse/JDK-8154757 and shows a backport for JDK 8u101. The next Oracle Critical Patch Update is July 2016 per http://www.oracle.com/technetwork/topics/security/alerts-086861.html

1 Like

Just wanted to let you know that importing chain.pem into cacerts (/etc/ssl/java/cacerts) from /etc/letsencrypt/live// worked with an Oracle JDK 1.8.0_91 in Debian 64. In my case I used the certificates for a Jira Tomcat container which had its own JDK by the way. So check carefully which JDK is really used.

Even though the certificate should’ve been added to Java per https://bugs.openjdk.java.net/browse/JDK-8154757, the latest JDK 8u112 Build b02 from Early Access Releases (https://jdk8.java.net/download.html) still doesn’t have it. Java trust store file (lib/security/cacerts) hasn’t changed since JDK 8u92.

I’ve just tried the latest Java 9 build and its cacerts also still doesn’t include IdenTrust and DST certificates. Any idea why?

:smile: Letsencrypt certificates are confirmed working with Oracle JDK >= 8u101 (release)

List of browsers and operating systems where LE is trusted ( Which browsers and operating systems support Let's Encrypt) updated.