Why I need to import server certificates in java - 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.

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.

How to add SSL certificate in core 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.

Debian SSL certificates ERROR: cannot verify xxx certificate / javax.net.ssl.SSLHandshakeException

I have a strange problem (it's 100% server configuration problem,) for example I want to download something from Dropbox:
Resolving dl.dropboxusercontent.com... 23.23.160.146, 50.17.227.107,
54.221.248.69, ... Connecting to dl.dropboxusercontent.com|23.23.160.146|:443... connected. ERROR:
cannot verify dl.dropboxusercontent.com’s certificate, issued by
“/C=US/ST=CA/O=SonicWALL Inc./CN=SonicWALL Firewall DPI-SSL”:
Self-signed certificate encountered. To connect to
dl.dropboxusercontent.com insecurely, use ‘--no-check-certificate’.
Yes, I know that I can use --non-check-certificate but when I want to use SSL connection in Java app I have something like this:
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
This app works great in other servers or in local machines, any ideas what is wrong here?
/C=US/ST=CA/O=SonicWALL Inc./CN=SonicWALL Firewall DPI-SSL
Your traffic is visibly intercepted by a deep packet inspection firewall that acts as a MITM proxy to monitor your traffic.
This can generally be thought of as "legitimate" MITM attacker. (However legitimate this may be depends on a number of legal and ethical aspects.) Your local network administrator should be able to tell you a little bit about this. If this is part of a company network, this company is monitoring your traffic, including the contents of your HTTPS connection (so it's no longer secure from end-to-end). It the firewall does its job properly, it should still secure the connection from the firewall to the server (It's probably hard to know whether it check certificates properly.)
In general, such a firewall or proxy acts as its own Certification Authority, effectively forging each certificate as requested.
Most clients on the corporate network would trust certificates it issues (like the one you're facing) because system administrators would also install the CA certificate as a trusted certificate into each machine within that network. You probably have it the OS trusted root certificates.
However, it is likely that network administrators did not install this CA certificate into your JRE installation (which uses its own set of trust anchors by default).
Try to export that CA certificate (see the name above) from a reference machine and import it into the truststore you're using (either your JRE's default truststore: cacerts or a new truststore you build and pass to your application via the javax.net.trustStore properties).
Typically, you can use something like this (assuming you've exported the Firewall's CA as "firewallca.pem"):
keytool -import -file firewallca.pem -alias firewallca -keystore truststore.jks
If the truststore.jks file doesn't exist, it will be created. Otherwise, you can take a copy of the cacerts file in the lib/security directory of your JRE. You can also do this directly on the cacerts file (using -keystore /path/to/truststore.jks, provided you have write access to it).
If you choose not to do it on the default truststore (that cacerts file) but use a local truststore like truststore.jks, you'll can use it by using this system property when running your application: -Djavax.net.trustStore=/path/to/truststore.jks
For other ways of configuring your truststore, check this answer.
Another way to fix this is to tell Java to use your OS's truststore. I'll assume you're using Windows here. Using these system properties should work:
-Djavax.net.trustStore=NONE -Djavax.net.trustStoreType=WINDOWS-ROOT
(Try with WINDOWS-MY instead of WINDOWS-ROOT if this doesn't work.)
The WINDOWS-MY/WINDOWS-ROOT is a bit buggy in that it will miss some of the certificates in the Windows store: it uses the certificate "friendly name" (non unique) as the keystore alias (unique), so a certificate with a given friendly name will hide the others with the same name. (This effectively reduces the number of CA certificates that are trusted unfortunately.)
Since you're in an environment where presumably all the traffic goes through your DPI firewall, you'll probably only ever have to use one CA certificate at most. As long is it doesn't share its "friendly name" in the Windows list with any other cert, you should be fine.
You need to add the server's SSL certificate in your client's Java keystore. Take a look at this SO post:
Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?
TIP: This is because your client's JVM does not 'trust' the server's SSL cert. So you need to add the cert in your keystore.

Getting ssl exception inspite of both certificates are issued by verified CA's?

I have two webapplication at prrduction say app1 and app2. Both are on different webservers. app1 is verified secure trust corporation and
app2 is verified by TrustWave Holdings,Inc . So both are verified CA's.App2 tries to make HttpsURLConnection to app1 and gets some SSLException. My question
is if both certificates are verfied ones, still do we need to make any certificate entry in jre\lib\security folder? As per my understanding
we do not need this if certificates are verified one. Any pointers will be great help.
EDIT:-
i am on jdk1.6. I am not sure whether these certificates i.e(secure trust corporation and TrustWave Holdings,Inc) are already there
in cacerts file under jre\lib\security. i could find on the web that these are included in mozzila and other browser but not
sure about jdk 1.6?
It takes some effort from a provider to have its root CA cert included in all browsers and iphones and tablets and whatnots. More often than not they don't bother getting their cert shipped with oracle or openjdk. That's the exact reason why we moved away from Godaddy to Comodo... If the server cert isn't bundled you can create a keystore with the issuer certs and yours and tell java to use it via commandline:
-Djavax.net.ssl.trustStore=yourkeystorefile.jks -Djavax.net.ssl.keyStore=yourkeystorefile.jks
technically you would put the servers cert+key in the keystore and cert chain from the issuer to the truststore, but it's fine for java if the two are mixed in one keystore file
You will likely need to add these to /security/cacerts. By default Java does trust some certificate authorities. I'm not sure TrustWave is one of them.
View the keystore using the following command and see if TrustWave is in there.
keytool -list -keystore /usr/java/jdk1.6.0_14/jre/lib/security/cacerts

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.

Categories