Which certificate store does Java use? Does it use the system one? Really don’t see any issue here on Linux with Java. Which domain did you test?
It works on OpenJDK on Ubuntu. But Oracle Java does not accept it; not even on Ubuntu.
Since there is no OpenJDK für Microsoft Windows, I assume that is broken for all java based Feed readers on Windows.
Did you try the oracle java with the openJDK’s keystore? It could simply be that the openJDK one’s been updated to include the relevant root certs
OpenJDK on ubuntu definitely uses a different keystore. You can look at the contents with:
keytool -keystore /etc/ssl/certs/java/cacerts -storepass changeit -list
Similar command for the Oracle JRE/JDK keystore
This is the root that allows it to trust LE:
debian:dst_root_ca_x3.pem, Nov 9, 2015, trustedCertEntry,
Certificate fingerprint (SHA1): DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13
Sorry, if this has been posted or answered already, but it may help some people until an official support is made available. Though JAVA may not support the CA out-of-the-box, the CA can be added during runtime of a java program by this simple code.
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());
tmf.init(ks);
SSLContext ctx = SSLContext.getInstance(“TLS”);
ctx.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
}
So, calling this function inside URLConnectionReader.java from Firefishy should do the job. I prefer this rather than disabling certificate path checking completely in java by creating a dummy trust manager.
It’s pretty trivial to add the CA to the trust list for any standard JDK with the keytool command. Point is - if you have to add the CA it’s not much different than you adding your own local CA — it’s not something you can expect an end-user to do.
If you use services with certificates issued by LE, just load the CA dynamically. The end user doesn’t have anything to do with it then and you’re fine.
Can someone give me instructions for adding to the JRE:s truststore that a retard like me understands?
~/dev/projects/kostbevakningen $ java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
sudo keytool -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -file ~/Downloads/isrgrootx1.pem
Still get errors:
[error] 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…
I’m struggling. I have exactly the same use case (nexus and sbt/ivy) but JDK build 1.8.0_65-b17 (the latest for OS X it seems).
I’ve run:
sudo keytool -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -file ~/Downloads/isrgrootx1.pem
but it doesn’t help. I guess I need the full chain. Individually adding the three pem:s from here doesn’t work: https://letsencrypt.org/certificates/. I get errors:
keytool error: java.lang.Exception: Certificate not imported, alias <mykey> already exists
on the two later and on second runnings of the first.
You need to use a different alias for each imported cert.
i.e. if It’s a chain of “root”, “intermediate1”, “intermediate2” - specify “-alias leroot”, “-alias leint1”, “-alias leint2” for example when doing the imports.
You should also validate that your server is returning the intermediates/chain.
Found out the pem-file didn’t work for me here: https://letsencrypt.org/certs/letsencryptauthorityx1.pem.
`keytool error: java.lang.Exception: Input not an X.509 certificate``
But the .der file worked fine. So for me:
wget https://letsencrypt.org/certs/isrgrootx1.pem
wget https://letsencrypt.org/certs/letsencryptauthorityx1.der
sudo keytool -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -alias isrgrootx1 -file ~/Downloads/isrgrootx1.pem
sudo keytool -trustcacerts -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -alias letsencryptauthorityx1 -file ~/Downloads/letsencryptauthorityx1.der
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 {
addRootCA();
URL oracle = new URL("https://yoursslsitewhichissignedbytheca/");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
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());
tmf.init(ks);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
}
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());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hv);
} 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.