6

I'm trying to use the SSL certificate obtained with StartSSL.com on an Apache server. The connection with browser is fine, but when I try to use a Java application, I got this exeption:

Exception in thread "main" 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

I don't understand what could be the problem, because with the browser, I got the SSL with green label.

I love coding
  • 1,183
  • 3
  • 18
  • 47
  • you probably didn't import your certificate into the JVM see details [here](http://stackoverflow.com/questions/9619030/resolving-javax-net-ssl-sslhandshakeexception-sun-security-validator-validatore) –  May 12 '15 at 19:33
  • in my own HTTPS library, I have a convenience method [`trustAll()`](http://bayou.io/release/0.9/docs/http/Client_SSL_Configuration.html#Root_CAs) so that all server certificates, including self-signed ones, are accepted. this is probably OK for some client applications (but certainly not for a major browser!) The security threat is that some man-in-the-middle may be able to eavesdrop or even modify the traffic; but that is quite improbable. It requires resources like NSA has; but I'm pretty sure NSA can hack into SSL anyway :) – ZhongYu May 12 '15 at 19:36
  • @bayou.io Actually, it can happen in many other places, e.g. public wifis. – Bruno May 12 '15 at 20:56
  • @Bruno - the problem is certificate-tempering is immediately noticeable to browser users. so if our client is a small fish under the radar, we might get away with not being strict. :) – ZhongYu May 12 '15 at 21:00
  • @bayou.io That's just non-sense. That's why there's plenty of mobile apps that are insecure, for example. – Bruno May 12 '15 at 21:01
  • @Bruno any actual man-in-the-middle attack on SSL in the wild? hackers have much better attack vectors to work on than MITM SSL. – ZhongYu May 12 '15 at 21:03

5 Answers5

10

The problem is your Java is not trusting the certificate. You have to import it to your java's truststore.

# Copy the certificate into the directory Java_home\Jre\Lib\Security
# Change your directory to Java_home\Jre\Lib\Security>
# Import the certificate to a trust store.
# Here's the import command:

keytool -import -alias ca -file somecert.cer -keystore cacerts -storepass changeit [Return]

Trust this certificate: [Yes]

changeit is default truststore password.

For every certificate that you imported into your truststore you have to provide a new alias.

The import method is a quote from Here

Community
  • 1
  • 1
Sercan Ozdemir
  • 4,641
  • 3
  • 34
  • 64
  • Thank you ! So if I have to share the java application on the web, will I have to insert the key in that file ? By the way, this is what StartSSL, told me: You must make this site the default web site of your server or use a dedicated IP address for it. What do you think about ? – I love coding May 12 '15 at 19:35
  • If you want to share java applicaton on the web, you have to also provide ssl file to people, but it can be obtained by browser easily.. Well a ssl certificate can be easily created by many ways, even if you use a dedicated ip address, if your certificate isn't imported by the client's OS (Windows etc.) user will see a warning on browser when entering your website.. – Sercan Ozdemir May 12 '15 at 19:38
  • The other thing, is that with another SSL certificate by Comodo, the Java application works without any additional modification. So the problem is just about Java, isn't it ? Is there any way to modify Apache to solve the problem ? – I love coding May 12 '15 at 19:46
  • You can bypass ssl in your java code by googling how to do it but its not recommended – Sercan Ozdemir May 12 '15 at 20:15
1

This message is due to:

  1. Either the JRE does not have the root CA as a trusted entry in its keystore.
  2. The server is not sending a proper chain.

But, 2 is not valid in your case since the browser is able to construct the chain and validate the certificate.

Consequently you need to get the root CA and put it in the JRE keystore as a trusted entry. There are lots of resources that document the "how". One of them is: https://access.redhat.com/documentation/en-US/Fuse_Message_Broker/5.3/html/Security_Guide/files/i379776.html

EDIT 1: Since you want to share the java app, it would we worth the effort to get a certificate from a CA whose root is already trusted in the trust store for the Java versions that your app supports.

Khanna111
  • 3,627
  • 1
  • 23
  • 25
  • Thank you ! I haven't completely understood your edit. What should I do to fix the problem, within Java ? – I love coding May 12 '15 at 19:48
  • Check the keystore for the already trusted ca roots and get the server cert that can build trust to that. Or you could ship with your own trusted store and specify a command line option to Java to trust it. Djavax.net.ssl.trustStore=path/to/trustStore.jks – Khanna111 May 12 '15 at 20:18
0

As far as I understand this is related to the Java Certificate Keystore. Your certificate is not accepted by java. Here is a link how to add your certificate to Java trusted Certificates keystore: https://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html

nullptrex
  • 34
  • 3
0

There are a few questions like this already on SO (like this one: PKIX path building failed: unable to find valid certification path to requested target).

The usual answer to this is that your java client doesn't have certificates needed to complete the certificate chain.

If you need proper certificate validation, then you'll have to figure out where the certificate chain breaks down. If you don't (because this is a proof of concept or a dev sandbox, or whatever), then you can easily work around this by adding the certificate to the trust store you use with your client.

Edit:

As for why your browser accepts this, it's likely that either your browser has the certificates in the chain that you need or you've absentmindedly told your browser to trust the certificate even though it also wasn't able to validate the certificate.

Community
  • 1
  • 1
Trevor Brown
  • 169
  • 3
0

I recomend use http-request built on apache http api.

import org.junit.Test;

import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.apache.http.entity.ContentType.APPLICATION_XML;
import static org.junit.Assert.assertEquals;

public class HttpRequestSSLTest {

private final HttpRequest<?> httpRequest = HttpRequestBuilder.createGet("https://mms.nw.ru/")
        .trustAllCertificates()
        .trustAllHosts()
        .addDefaultHeader(ACCEPT, APPLICATION_XML.getMimeType())
        .build();

@Test
public final void ignoreSSLAndHostsTest() throws Exception {

    assertEquals(SC_OK, httpRequest.execute().getStatusCode());
}

}

Beno
  • 945
  • 11
  • 22