In a Java desktop application I need to connect to a SSL URL. When I try it, I get the exception:
SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
To solve it, I go to the address with my browser, download the certificate in .cert file and import in my java cacerts keystore using keytool command. After this, the application works fine.
My question is: why java don't recognize the certificate if this is signed with VeriSign? VeriSign certificate is not installed in cacerts keystore by default?
Maybe I don't understand how SSL works. What's the difference between browser and java desktop behavior? I can connect to this URL with my browser without installing nothing.
Thanks
When we access a secure site which uses SSL for providing identity and encryption, it provides a certificates which was verified by a trusted third party sites like verisign, godaddy or thwate.
By using certificates browser or java clients knows that they talking to the correct site (who it claims to be) and not on redirected proxy site. this step is pretty transparent if you access websites using browser because if certificate is not on browser's trusted store it will ask you to add that certificate and it will be subsequently added.
But when you access a secure site using Java program, this step of certificate hand shaking is not transparent to user and certificates are verified form JRE's trustStore.
Read more: http://javarevisited.blogspot.com/2012/03/add-list-certficates-java-keystore.html#ixzz32v1wL3Gl
You did not say which certificate you imported into the keystore. Usually there are several certificates involved in the verification:
the trusted root certificate, which is stored in the keystore or browser (Java does not share the keystore with the browser)
the leaf certificate which identifies the site
and most times also intermediate certificates, which provide a signed way from the leaf certificate to the trusted root and thus establish a trusted path
If any of the intermediate certificates is missing, the verification fails.
So the server has to send not only the leaf certificate, but all intermediate certificates too. And this is where lots of sites fail, e.g. they don't provide the full certificate chain.
But why does this work in the browser?
Because enough sites fail to provide the intermediate certificates and because the browser wants to provide the best experience, they will cache the intermediate certificates. Thus, if you go to one site signed by verisign which provides the trusted chain, and then go to another site signed with the same certificate, but which does not provide the chain, then it will still work, because the chain certificates are cached from the other side.
But, if you use a fresh system (or simply a new browser profile with firefox) and visit the misconfigured site first, it will complain there too, as much as the Java application did. And if you just import the relevant intermediate certificate into the keystore and thus trust it it will work too, because it does not need the rest of the chain to get a path to a trusted certificate.
Related
I have a Java program that connects to an https remote webservice which exposes a TLS certificate of this structure:
Webservice certificate
Signed with some certificate
Signed with some corporate certificate
Now, when my Java app makes a https request to that webservice it fails due to invalid certificate. This is normal, so I added the webservice direct certificate to the Java/lib/security/cacerts file.
But this didn't work, I still had the certificate exception.
After a long debugging session and hours wasted, I tried to add all three individual certificates, and this time it worked. But why ?
Why does Java checks the full certificate path even though the direct certificate is made trusted ?
Is this behavior as per SSL/TLS RFCs ? Will this behavior occur with other tools/languages like curl ?
Thanks.
... so I added the webservice direct certificate to the Java/lib/security/cacerts file
The webservice certificate is not a CA certificate, so it does not belong in cacerts in the first place (as the name indicates). A CA certificate is a certificate which is used to sign other certificates, a webservice certificate is a leaf certificate which cannot be used to sign other certificates.
Will this behavior occur with other tools/languages like curl ?
This is a common behavior. With OpenSSL based tools one usually needs to provide the root CA (and of course the chain to it), only with X509_V_FLAG_PARTIAL_CHAIN it will accept when parts of the chain a specified as trusted.
I am very new to webservice and configuring certificates. I have roughly gone through PKI concepts. Below are come basic questions I have
1) I have certain certificates which i use in my code to Sign the XML elements,
What is the need to add these certificates to in the cacerts file under lib/Security of JRE
2) what is the use of this cacerts file.
I use weblogic server with jockrit jre
Do let me know , if there are some sites to learn the above concepts
2) what is the use of this cacerts file.
cacerts is the default trust store of your JRE. It contains the root certificate of Certification Service Providers that JRE manufacturer considers to be trusted. Cacerts is checked by default TrustManager to verify if a certificate has been issued by some of this CSP's, for example when you invokes a third party service using SSL/TLS, the server certificate is validated
1) I have certain certificates which i use in my code to Sign the XML elements
You do not need to add anything to cacerts. But if you use a self-signed certificate you should provide the public part of your certificate to the receivers in order they can verify the signature.
Here I need to verify the SSL certificates for https websites with the root certificate. I have tried extremely lot but it could not be done yet. If anyone have any Idea to write such a code in java that could verify the Certs with the root cert. Mean that I have to check the certificate hierarchy signature validation for particular certs.
Thanks....
You need all root and sub root certs for validation. There is two different technologies; CLR and OCSP. OCSP is new one but some certificates support it.
You need some basic check for validate certifcate (also there are more rules):
Date is valid,
Certificate has ssl encription support, domain, etc,
Certificate issuer is correct,
Certifate rewoked or cancalled (with CRL or OCSP)
Java has own library for this, example: How to get server certificate chain then verify it's valid and trusted in Java
My application is running in intranet in tomcat server. I am able to run my application with https but with warning(The security certificate presented by this website was not issued by a trusted certificate authority) also https symbol is crossed in red.
How we can have trusted SSL with self sign certificate in tomcat server without pain of importing certificate in browser?
How we can have trusted SSL with self sign certificate in tomcat server without pain of importing certificate in browser?
You can't. Self-signed is not trusted by default (where should the trust come from?) and thus you cannot expect the browser to trust it without telling the browser that it can trust it (by importing). Trust is a relationship and can not simply emerge from nowhere.
The warning States that the certificate is valid but browser don't trust the authority issuing the certificate. The only way is to Configure Browser to Ignore the untrusted CA issues, or Trust The organization in this case you .
Alternatively the recommended way is to get a certificate issues from one the of the CA Authority ( Verisign , Godaddy etc).
Any browser confirms below list items before marking a website/url secure:
Match the base DNS with that of the certificate CN (Note that the port number doesn't come into picture in this case). For example, if you are accessing https://example.com:8445/something, the certificate CN should be "example.com"
The self-signed certificate has to be imported into the respective trust store (Root Certification Authorities) of the system.
The certificate must have a SAN (Subject Alternative Name), that matches the DNS. With respect to previous example, the certificate must have at least one SAN equivalent to "example.com". This is a must, and most of the folks miss out on this point, and could not understand why the browser doesn't trust the certificate.
The Free way to establish trust in browser for internal applications
Now, all the above 3 criteria cannot be met unless the certificate is signed by a CA. However, there is an easy way. Go to https://freesslcert.org/ to receive a completely free 1 year certificate with all the above criteria incorporated. Follow the steps mentioned in https://freesslcert.org/trust-freesslcert-in-browser and you are all set.
Paid Solution for external websites
You can spend some dollars to get a certificate from one of the CA as mentioned here : https://freesslcert.org/get-cert
I've generated a self-signed certificate for my Java app using keytool. However, when I go to the site in a browser it always pops up with a warning - saying this site does not own the certificate - is there a way to self-sign/doctor a certificate so I won't get these warnings in a browser? Both server and browser are located on the same host and I navigate to the site using "http://localhost/". I do not want to add an exception to the browser because I have tests which run on a big build farm so it is excessive to add an exception to all browsers on all build machines.
No, you can't. You might as well ask "How can I make a fake certificate for hsbc.com?"
There are two ways to get a browser to accept a certificate:
Buy a certificate for a domain from a trusted authority (which means proving to that authority that you own that domain) and then use that domain as the name of your test servers
Install your signing certificate into the browsers, so that you effectively become a trusted authority for that browser.
Without touching the browsers, there's no other way to do it - how could there be, if the internet is to remain secure?
You could also setup a self-signed Certificate Authority (CA) using OpenSSL or possibly your Java tool. You can then use that CA to sign a number of server certs.
You are still going to need to manually trust your self-signed CA on all clients that access your test servers, but at least you only have to trust one root CA, rather than a bunch of individual self-signed server certs.
Another option is to check out CAcert.
Is the certificate you created for localhost or for test.textbox.com? If you create a certificate for the FQDN test.textbox.com, that's how you need to be reaching the server to not get those errors, as long as the certificate is properly signed. You can't generate a certificate for the FQDN and then use an IP or an alias (localhost) to access it without being warned that things aren't matching up properly. Or am I misunderstanding your problem?
Make the certificate for "localhost" instead. It needs to match the hostname you have in the URL.
You will still be bothered as the certificate is not trusted, but that is another issue.