0

I have been spending hours on this and can't figure out why. I am even using parts of the code example used on the bls.gov website. I shouldn't have any issues because it's a public API... Please help!

public static void main(String[] args) throws ClientProtocolException, IOException {

     HttpHost proxy = new HttpHost("myproxy.com", 3128, "http");

    CloseableHttpClient httpClient = HttpClientBuilder.create().setProxy(proxy).build(); // Use
                                                                            // this
                                                                            // instead

    HttpPost request = new HttpPost("https://api.bls.gov/publicAPI/v1/timeseries/data/");
    StringEntity params = new StringEntity("{\"seriesid\":[\"LAUCN040010000000005\", \"LAUCN040010000000006\"]}");

    request.setEntity(params);

    request.setHeader("Accept", "application/json");
    request.setHeader("Content-type", "application/json");

    CloseableHttpResponse response = httpClient.execute(request);
    System.out.println("HERE");
    System.out.println(response.getStatusLine());
    response.close();

Keep getting this error:

  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
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
at sun.security.ssl.Handshaker.processLoop(Unknown Source)
at sun.security.ssl.Handshaker.process_record(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
gd000
  • 195
  • 2
  • 12

2 Answers2

0

Java is very picky with the Certificate chain. Is the server also delivering the intermediate certificate?

https://en.m.wikipedia.org/wiki/Intermediate_certificate_authority

It's not you. The order of the certificates is not delivered correctly: https://www.ssllabs.com/ssltest/analyze.html?d=api.bls.gov

  • Can I ask you what this means? Does this mean there are issues with their certificate which will prevent anyone from getting data? Is there a way around it? – gd000 Dec 21 '16 at 20:17
  • More or less, yes. Since java is very picky here, default configured Java Programms will have problems with that. Main issue is the wrong order in the certificate chain. Also the ssl test indicates big issues with the SSL configuration, insecure ciphers etc. if you are able to contact the admins, you could ask them to fix this. – Maximilian Braun Dec 21 '16 at 20:21
  • @gd000 maybe as a workaround: http://stackoverflow.com/questions/21257455/whats-an-easy-way-to-totally-ignore-ssl-with-java-url-connections – Maximilian Braun Dec 21 '16 at 20:28
  • appreciate your replies. unfortunately, that didn't work – gd000 Dec 21 '16 at 20:36
  • @gd000 :-/ you could give http://stackoverflow.com/a/2893932 Option 2 a try. Hope this helps for you. But please see the authors comment on vulnerability. – Maximilian Braun Dec 21 '16 at 20:41
  • @gd000 you are using an Apache http client, right? If yes, please see http://stackoverflow.com/a/2703233 – Maximilian Braun Dec 21 '16 at 20:51
0

You have to have a certificate from https://api.bls.gov in your Java Trust store.

Certificate it-self you can import from any browser when connect to that URL.

You have to add a certificate into Trust store which will be used for your program. You can do it by using either keytool or OpenSSL.

There are number of different ways to define which Trust store will be used:

  1. Certificate can be added to Java default Trust store on JRE level. Trust store is cacerts in JRE lib/security folder. - not recommended

  2. Certificate can be added to Trust store provided on JVM level at startup in -Djavax.net.ssl.trustStore parameter - not recommended (Trust store password must be provided as open text in -Djavax.net.ssl.trustStorePassword)

  3. Create SSLSocketFactory from needed Trust store file (and HostnameVerifier as well) and then use them for your https connection.

There are a lot of examples everywhere on the Internet. just try to google it.

Vadim
  • 4,027
  • 2
  • 10
  • 26