I have created the SSL cert for the domain example.com and intsalled it. It's working fine. I have configured Java on another host. When I'm trying to connect to the domain example.com from the remote host using java, I'm getting below error.
I have downloaded the Root CA of LetsEncrypt from wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.der and added it to the Java trusted certs. And the domain backend servers using tomact as web server.
So far, I have executed below commands.
1)wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.der
2)sudo keytool -trustcacerts -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -noprompt -importcert -alias lets-encrypt-x3-cross-signed -file lets-encrypt-x3-cross-signed.der
3)keytool -list -v -keystore $JAVA_HOME/jre/lib/security/cacerts and the results shows the letsEncrypt cert added to the java cacerts.
4)sudo /var/juno/bin/rc stop tomcat-memdesk
5)sudo /var/juno/bin/rc start tomcat-memdesk
When we made transaction from the remote host to the domain which have letsencrypt configured, then it throwing below error.
If s_client is able to successfully establish a TLS connection (both locally and remotely), then it would help narrow things down a bit - or reveal an error.
Well, Java 8 doesnât need anything additional to be able to talk to hosts with Letâs Encrypt certificates. Importing the intermediate into the trust store is not needed.
Can you run this program, adding your Tomcat hosts to HOSTS_TO_TRY? It would verify your systemâs ability to establish a TLS session with the remote Tomcat.
if it works fine, then the Java API is being misused somehow - or the changes you made to the trust store have broken something.
public class LetsEncryptConnectTest {
static final String[] HOSTS_TO_TRY = { "untrusted-root.badssl.com", "letsencrypt.org" };
public static void main(String args[]) {
for (String host : HOSTS_TO_TRY) {
System.err.printf("--- Trying %s\n", host);
try (final java.net.Socket s = javax.net.ssl.SSLSocketFactory.getDefault().createSocket(host, 443)) {
final javax.net.ssl.SSLSession session = ((javax.net.ssl.SSLSocket) s).getSession();
final java.security.cert.Certificate[] cchain = session.getPeerCertificates();
System.err.println("The Certificates used by peer");
for (int i = 0; i < cchain.length; i++) {
System.err.println(((java.security.cert.X509Certificate) cchain[i]).getSubjectDN());
}
System.err.println("Cipher is " + session.getCipherSuite());
System.err.println("Protocol is " + session.getProtocol());
} catch(Exception e) {
System.err.printf("Host %s experienced an error: %s\n", host, e.toString());
e.printStackTrace();
}
System.err.println();
}
}
}
$ javac LetsEncryptConnectTest.java && java LetsEncryptConnectTest
--- Trying untrusted-root.badssl.com
Host untrusted-root.badssl.com experienced an error: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:440)
at LetsEncryptConnectTest.main(LetsEncryptConnectTest.java:11)
--- Trying letsencrypt.org
The Certificates used by peer
CN=www.letsencrypt.org
CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US
Cipher is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Protocol is TLSv1.2
Are you sure youâre using Java 8 on the client side as well? You shouldnât need to manually install the root certificate with Java 8, as it was included with update 101.
If youâre using Java 7 or Java 6 client-side, they have known issues with DHE key exchange youâll need to work around in your server.
Thanks much. The program you provided helped me to a lot.
At last, Identified the root cause. We didnât enable the D-H key verification on the load balancer for that domain example.com that have configured with letsEncrypt cert. (my bad)
Because of that, Java was not able to do the key verification.
Still, the browser showing the domain as https enabled but in the back end, because of key verification disabled the data canât flow in an encrypted way (in a secure way). Am I right?
You have a load balancer? Maybe you are right and you have selected a ciphersuite/public key combination on the load balancer that Java does not support. Whether Diffie-Hellman is used or not is, and what type of DH handshake takes place, comes from the ciphersuite.
If you can share how the load balancer is configured (i.e. what ciphersuite it is configured for, what type of key the certificate uses), that would help.
Yeah, we have load balancer. We install the certificate for the particular VIP on LB so that if anyone tries to hit that domain. The request will comes to LB and verifies the SSL configuration. Based on that, the connection will establish.
and generally When you request a HTTPS connection to a webpage, the website will initially send its SSL certificate to your browser. This certificate contains the public key needed to begin the secure session. Based on this initial exchange, your browser and the website then initiate the âSSL handshakeâ. The SSL handshake involves the generation of shared secrets to establish a uniquely secure connection between yourself and the website. After handshake completed, the data flows b/w browser and the web server is in encrypted.