How to add SSL certificate in core java? - java

My requirement is simple. I have SSL certificate for website. I want to connect to that website through https but i want to do this through simple java class (without Keystore as do not want to do any change in installed java). Is this possible?

All JREs ship with an default truststore (cacerts) that contains most Certificate Authorities (CAs) that you'd typically use on a website.
If your website uses a valid SSL certificate issued by a CA that is trusted by your version of Java, then you can connect without having to configure your truststore.

Related

Java client not picking root/intermediate certificates from Windows Trust Store

I have a Jetty server running with SSL certificate which has root->intermediate->host certificate chain.
I have a Java client on Windows which connects to this server. I am using below system properties to set trust store but it does not work unless I import "host" certificate in Windows "Trusted Root Certificate Authorities" store. I have intermediary and root certificates in "Intermediate Certificate Authorities" store of Windows, but Java does not pick them and throws SSL error. However, Chrome works perfectly without issueing any warning.
System.setProperty("javax.net.ssl.trustStore", "NUL");
System.setProperty("javax.net.ssl.trustStoreType", "Windows-ROOT");
As per my understanding, even if root or intermediary certificate is there on client machine, Java should be able to pick it.
Is it required to put intermediates and root under "Trusted Root authorities" store? Would putting under "Intermediate Certificate Authorities" not work? From which store category, Java picks the certificates?
Please help.
This happens when the server only returns the leaf certificate and not the intermediate certificates. Does a TLS client needs to have intermediate CA in the trust store? explains it is actually a server issue and not a client issue. Following that advice it solved my issue.

Why I need to import server certificates in java

We have developed an console application which will bring data from ESB (https://esb.mkcl.org/) which is on HTTPS. When I hit to this web site I get javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated exception. I changed URL to https://netbanking.hdfcbank.com/netbanking/ which is also on HTTPS and after giving hit I have NOT received any exception.
After some searching I come to know that I have to import public certificate in java's keystore i.e cacerts (C:\Program Files\Java\jre6\lib\security). So I exported certificate of https://esb.mkcl.org/ from browser and imported in java using keytool and then executed console application and it works!! no exception is occurred.
So the question is why I need to import certificate for that particulate URL (where as other HTTPS URLs are working without importing any certificate in java)?
The root certificate used by that server's certificate (COMODO RSA Certification Authority) was added to Java in Java 8 Update 51, so that means the java version you're using (java6 from your jre path) is too old to already include it.
To have that certificate trusted by default, update to a never java version.
And by the way, the ssl configuration for that server is pretty insecure.
A client-side SSL implementation relies on a set of known "trusted root certificates". These are certificates for SSL Certification Authorities that are known to be trusted / trustworthy.
The "problem" is that the set of trusted certs in the keystore that is distributed in your Java JDK / JRE is (typically) smaller than the set in a typical web browser.
There are reasons for this. For example:
A "server" Java installation probably needs to be more conservative on who to trust by default ... for security reasons.
You may be running an older (i.e. out of maintenance) version of Java. Obviously, Oracle will not be refreshing the keystore with new trusted certs.
Some JREs can make use of either the host OSes default keystore, or a browser keystore.
Access to the Mac OS X keystore was introduced in Java 7u4.
Browser plugins can use the browser keystore.

How can a Java app accepts a server certificate seamlessly?

Most Web browsers that support SSL have a list of CAs whose certificates they will automatically accept. If a browser encounters a certificate whose authorizing CA is in the list, the browser will automatically accept the certificate, and establish a SSL connection to the site.
There is a Java 1.6 client, running on JBoss 7, which is required to make SSL connection to LDAP server. Since the client is on production, if the LDAP server updates its certificate without notifying me to update the certificate accordingly on JBoss, the client will fail. My question is: how can I securely connect(ssl) to LDAP in a similar way the browser “accepts” the certificate seamlessly?
I don’t know if this is feasible in Java. But, any thoughts and feedbacks are all welcome.
Java has a default truststore that contains all the trusted certificates. This is under %JRE_HOME%\lib\security\cacert and has all the trusted CA certificates (Verisign etc).
So if your client https application tries to connect to a server that deploys a certificate signed by these issuers you would have no issue (same as happens with your browser).
Now to your problem. You don't mention enough information about your LDAP server.
I can think of the following:
The LDAP server deploys a certificate signed by some CA (not one of
the known ones).
The LDAP server deploys a self-signed certificate
For case (1) all you need to do is add the certificate of the signer to your truststore (i.e. the certificate of the issure that signed the certificate of your LDAP server). If the LDAP server changes certificate, you would be unaffected provided that it gets the certificate from the same CA which you would have set now as trusted. This trusted certificate could be added in cacerts but the recommended solution is to use your own separate truststore, import it and set it in JVM to override the default cacerts. Plenty of example in Google.
For case (2) this is a really bad setup and are in trouble as you would need to actually update the truststore manually each time the LDAP server changes certificate.
But in any case I can only assume that the certificate changes due to expiration? I can't think of another reason (except compromise of private key but this is not the problem here from your description)

Do we need to add the verified CA in VM TrustStore when making connection from java?

I am making a call from one application sayApp1 to another application(say App2) authorized by verfied CA like Verisign or Thawte like
String urlStr="https://myApp2/welcome"
HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();
conn1.getInputStream()
Do i need to import that certificate issued by App2 somewhere in
VM truststore of app1? This is the case when they are on different tomcat server(so different vm).
What about the same scenario if they are on same tomcat server(i mean same vm)?
i know in case of browser it is not required to import the certificate signed by CA's like verisign,thawte etc but what about when making the connection from java?
Edit:-
As you said This will be the same regardless of the server they are installed
It means ever webserver checks the cacerts file that shipped with Java 1.6.0_30 . so if client jvm has those certicates, we dont have to do anything.
This cacerts file check is done only when we are making the url connection from java code. In case of browser it will just check browser truststore.RIGHT?
To move my site to https i followed below step
C:\Program Files\Java\jdk1.6.0_23>keytool -genkey -alias tomcat -keyalg RSA which generated .keystore file
Finally i made changes in server.xml and it worked keystoreFile="c:/.keystore" keystorePass="changeit"
After going thru too many material on net i am bit confused about which approach i just followed(did i create my own CA or i just created self signed certificate which needs
to be present at client side) ?
It depends. The cacerts file that shipped with Java 1.6.0_30 has 76 entries. If the certificate used by the other application was verified by one of the those vendors using one of those certificates, no importing will be necessary. This will be the same regardless of the server they are installed on if the protocol used is HTTPS. Sometimes vendors have new certificates that will require updates to cacerts. This is typically fixed by JVM upgrades. If the public key of the certificate used to verify the other application is not in cacerts then it will need to be imported to establish trust.
Your question is really confusing (this is the least I can say).
You start saying that you need communication with an application that deploys a certificate signed by a trusted CA like Verisign and end up asking what kind of certificate does keytool generated that you used in your Tomcat!
Anyway:
Do i need to import that certificate issued by App2 somewhere in VM
truststore of app1? This is the case when they are on different tomcat
server(so different vm). What about the same scenario if they are on
same tomcat server(i mean same vm)?
This does not matter.If you don't define for your client app a specific truststore then java's default will be used.
If the app2 sends a certificate signed by a trusted issuer like Verisign then you don't have to do anything (as #laz also points out). Since Verisign's certificate should already be present in your java installation cacerts
After going thru too many material on net i am bit confused about
which approach i just followed(did i create my own CA or i just
created self signed certificate which needs to be present at client
side) ?
You created a self-signed certificate (and a private key of course). You will need to import this in your client's truststore and of course use that keystore as your server's keystore.

Can't consume a SSL protected webservice with Java/Glassfish

I'm trying to consume a Webservice hosted under https security.
I'm using Java and glassfish and I'm getting the following error:
INFO: HTTP transport error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching testdomain.com found
The thing is that this specific server is used for testing and it's using the production certificate (the one with CN=domain.com)
I already added the domain.com certificate to my glassfish domain's cacerts keystore using keytool -importcert and it didn't work.
I also tried creating a self signed certificate with the CN=testdomain.com and adding it to the cacerts keystore and it didn't work either...
So how do I configure Java/Glassfish to consume this Web Service?
The CN of the server certificate should match the domain in URL to which the client connects. If still doesn't work, I would check if the IP maps to this hostname too (reverse DNS). It is the client, who verifies it. If you want to bypass this hostname verification, see the example code in my article: http://jakubneubauer.wordpress.com/2011/09/06/java-webservice-over-ssl/
The priciple is that you provide your own HostnameVerifier to the service client proxy.
THe self-signed certificate needs to be installed in the keystore of the Web service, along with its private key, and imported into the truststore of Glassfish.
the self signed certificate needs to be installed in key store of your java client. and testdomain.com should be resolved using dns.

Categories