4

I'm kind of newbie in SSL/TLS stuff, but recently I tried to send regular POST request to some third party server(to receive some data) from my Java client.
I started with the simple way with cURL request, and it was pretty easy.
The following request:

curl -v -X POST --header "Content-Type: application/json" 
--header "Accept: application/json" 
-H "X-Client-Id: xxxx" 
-H "X-Client-Secret: yyyy" 
--cert  ../my_certificate.crt:password 
--key ../my_private_key.pem 
-d "{
some data
}" "https://hostname/some_url"

Its worked perfect, I received proper response. After that, I follow dozen of guides and combined that with some similar solution which proposed here but without success. First, Im working with Java jdk8, my client is okhttp3, and I have caCertificate , signed certificate and private_key which I received from the remote server.
My current version of init client:

try (InputStream storeStream = this.getClass().getClassLoader().getResourceAsStream("client.p12")) {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(storeStream, "password".toCharArray());
        KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyFactory.init(keyStore, "password".toCharArray());
        KeyManager[] keyManagers = keyFactory.getKeyManagers();

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
           TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
           throw new IllegalStateException("Unexpected default trust managers:"
             + Arrays.toString(trustManagers));
        }
        X509TrustManager trustManager = (X509TrustManager) trustManagers[0];

        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(keyManagers, null, new SecureRandom());
        SSLContext.setDefault(sslContext);
        HostnameVerifier hostnameVerifier = createHostnameVerifier();
        client = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(),trustManager)
                .hostnameVerifier(hostnameVerifier)
                .build();
    } catch (Exception e) {
    }

the client.p12 file generated by the following command: openssl pkcs12 -export -in certificate.crt -inkey private_key.pem -out client.p12 -password pass:password -CAfile caCertificate.pem

and my request:

private String post(String url, String json) throws IOException {
    RequestBody body = RequestBody.create(JSON_MEDIA_TYPE, json);
    Builder builder = new Request.Builder();
    builder.addHeader("X-Client-Id", "xxxx");
    builder.addHeader("X-Client-Secret", "yyyy");
    }
    Request request = builder.url(url).post(body).build();
    Response response = client.newCall(request).execute();
    return response.body().string();
}

and I received the following exception:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:992)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:267)

Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
... 59 common frames omitted

Any idea what am I doing wrong here? Or any suggestion how to reflect the cURL request to Java client? Thanks a lot!

nisanarz
  • 895
  • 1
  • 12
  • 22
  • 1
    Run with sysprop `javax.net.debug=ssl` to see exactly what you are sending and when in the handshake the server closes (which is rude of it, it _should_ send an alert first). Your Java uses the p12 file for truststore as well as keystore, while your curl command uses its default; this may or may not be wrong, but it doesn't cause this specific error. One thing that might is if your curl uses openssl (check `curl -V`) and your client cert's issuer doesn't match the server's request (which the trace above will show); openssl doesn't check this but Java normally does. – dave_thompson_085 Apr 12 '18 at 23:15
  • I finally managed to fix that issue. I still belive its not the proper way to solve that, but I gave up. I followed this [link comment](https://stackoverflow.com/a/11762788/5658342) as a workaround. Still hope for real solution for that :) Thanks! – nisanarz Apr 15 '18 at 18:18
  • you should share the solution if you found one :) – jpganz18 Feb 18 '20 at 10:19
  • I stopped working with okhttp :) moved to different client. – nisanarz Feb 19 '20 at 12:45

0 Answers0