title: Sending HTTP request with SSL authontication using Apache HttpClient
body: <p>I am a newbie to the subject of SSL authontication and Httpclient requests in Java. And I need to perform a secured connection to service provider to be able to fetch some data from service provider api.</p>
  
  <h2>Where I am now:</h2>
  
  <p>I have made a .jks keystore containing private key and csr request which I have sent to remote service provider. I have got a signed .cer certificate. So far I have tested it in my Postman by exporting private key to a pem file and setting up a client certificate via CRT+KEY+Keypassword in Postman settings. The requests are running just fine. Now, I have to implement this issue using Java and I have already used Apache fluent-hc to send unauthenticated POST requests before.
  What actions should I take to implement a client certificate secured HTTP request?</p>
  
  <h2>Upd. So far I have googled next steps:</h2>
  
  <p>I imported my .CER signed cert into existing jks keystore with PrivateKey:</p>
  
  <p><code>keytool -importcert -file ./signed.cer -keystore trusted.jks -alias mykey</code></p>
  
  <p>When listing keystore, I get two entries: PrivateKeyEntry and trustedCertEntry</p>
  
  <p>Then I load my keystore from resource:</p>
  
  <pre><code>    public KeyStore loadKeyStore() throws Exception {
      KeyStore keystore = KeyStore.getInstance("JKS");
      try (InputStream is =  new ClassPathResource(authProperties.getKeyStore()
      + ".jks").getInputStream()) {
      keystore.load(is, authProperties.getKeyPass().toCharArray());
      }
  
      return keystore;
      }
  </code></pre>
  
  <p>Loading seems to be fine, I test it and get both private key and certificate. But not the certificate chain, not sure if I need it here.</p>
  
  <p>Then I create a SSLContext and load both TrustMaterial and KeyMaterial from the same keystore:</p>
  
  <pre><code>    public SSLContext loadSSLContext() throws Exception {
      return new SSLContextBuilder()
      .loadTrustMaterial(loadKeyStore(), (x509Certificates, s) -&gt; true)
      .loadKeyMaterial(loadKeyStore(), authProperties.getKeyPass().toCharArray())
      .build();
      }
  </code></pre>
  
  <p>Then, I create a SSLConnectionSocketFactory:</p>
  
  <pre><code>    SSLContext context = loadSSLContext();
      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(context,
      new NoopHostnameVerifier());
  </code></pre>
  
  <p>I create a CloseableHttpClient using SSLConnectionSocketFactory:</p>
  
  <pre><code>    CloseableHttpClient httpclient = HttpClients.custom()
      .setSSLSocketFactory(sslsf)
      .build();
  </code></pre>
  
  <p>And perform a GET request:</p>
  
  <pre><code>    HttpGet request = new HttpGet("/private/openapi");
      HttpResponse httpresponse = httpclient.execute(request);
  </code></pre>
  
  <p>When running this, I got </p>
  
  <blockquote>
    <p>javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure</p>
  </blockquote>
  
  <p>What could possibly be a cause? I have googled this issue, but it seems that it is mainly corresponds to protocol and cipher suite mismatch. I am not sure, if it is my case or not. 
  Please help, any ideas or links would be highly appriciated!
  Here is the stacktrace and debug output(please, ignore strange ip adresses):</p>
  
  <hr>
  
  <blockquote>
    <p>16:46:08.727 [main] DEBUG org.apache.http.headers - http-outgoing-0 >>
    CONNECT api.serviceprovider.com:443 HTTP/1.1 16:46:08.727 [main] DEBUG
    org.apache.http.headers - http-outgoing-0 >> Host:
    api.serviceprovider.com:443 16:46:08.727 [main] DEBUG
    org.apache.http.headers - http-outgoing-0 >> User-Agent:
    Apache-HttpClient/4.5.3 (Java/1.8.0_232) 16:46:08.727 [main] DEBUG
    org.apache.http.wire - http-outgoing-0 >> "CONNECT
    api.serviceprovider.com:443 HTTP/1.1[\r][\n]" 16:46:08.727 [main]
    DEBUG org.apache.http.wire - http-outgoing-0 >> "Host:
    api.serviceprovider.com:443[\r][\n]" 16:46:08.727 [main] DEBUG
    org.apache.http.wire - http-outgoing-0 >> "User-Agent:
    Apache-HttpClient/4.5.3 (Java/1.8.0_232)[\r][\n]" 16:46:08.727 [main]
    DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
    16:46:08.878 [main] DEBUG org.apache.http.wire - http-outgoing-0 &lt;&lt;
    "HTTP/1.1 200 Connection established[\r][\n]" 16:46:08.879 [main]
    DEBUG org.apache.http.wire - http-outgoing-0 &lt;&lt; "[\r][\n]"
    16:46:08.880 [main] DEBUG org.apache.http.headers - http-outgoing-0 &lt;&lt;
    HTTP/1.1 200 Connection established 16:46:08.881 [main] DEBUG
    org.apache.http.impl.execchain.MainClientExec - Tunnel to target
    created. 16:46:08.906 [main] DEBUG
    org.apache.http.conn.ssl.SSLConnectionSocketFactory - Enabled
    protocols: [TLSv1, TLSv1.1, TLSv1.2] 16:46:08.906 [main] DEBUG
    org.apache.http.conn.ssl.SSLConnectionSocketFactory - Enabled cipher
    suites:[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
    TLS_RSA_WITH_AES_256_CBC_SHA256,
    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
    TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA,
    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
    TLS_RSA_WITH_AES_128_CBC_SHA256,
    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
    TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA,
    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
    TLS_RSA_WITH_AES_256_GCM_SHA384,
    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
    TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
    TLS_RSA_WITH_AES_128_GCM_SHA256,
    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
    TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
    TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 16:46:08.906 [main] DEBUG
    org.apache.http.conn.ssl.SSLConnectionSocketFactory - Starting
    handshake 16:46:08.997 [main] DEBUG
    org.apache.http.conn.ssl.SSLConnectionSocketFactory - Secure session
    established 16:46:08.997 [main] DEBUG
    org.apache.http.conn.ssl.SSLConnectionSocketFactory -  negotiated
    protocol: TLSv1.2 16:46:08.997 [main] DEBUG
    org.apache.http.conn.ssl.SSLConnectionSocketFactory -  negotiated
    cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 16:46:08.998
    [main] DEBUG org.apache.http.conn.ssl.SSLConnectionSocketFactory - 
    peer principal: CN=api.serviceprovider.com, OU=IT Department,
    O=ServiceProv, L=Moscow, C=RU 16:46:08.998 [main] DEBUG
    org.apache.http.conn.ssl.SSLConnectionSocketFactory -  peer
    alternative names: [api.serviceprovider.com,
    developer.serviceprovider.com] 16:46:08.999 [main] DEBUG
    org.apache.http.conn.ssl.SSLConnectionSocketFactory -  issuer
    principal: CN=Thawte TLS RSA CA G1, OU=www.digicert.com, O=DigiCert
    Inc, C=US 16:46:08.999 [main] DEBUG
    org.apache.http.impl.execchain.MainClientExec - Executing request GET
    /private/openapi HTTP/1.1 16:46:08.999 [main] DEBUG
    org.apache.http.impl.execchain.MainClientExec - Target auth state:
    UNCHALLENGED 16:46:08.999 [main] DEBUG org.apache.http.headers -
    http-outgoing-0 >> GET /private/openapi HTTP/1.1 16:46:08.999 [main]
    DEBUG org.apache.http.headers - http-outgoing-0 >> Host:
    api.serviceprovider.com:443 16:46:08.999 [main] DEBUG
    org.apache.http.headers - http-outgoing-0 >> Connection: Keep-Alive
    16:46:08.999 [main] DEBUG org.apache.http.headers - http-outgoing-0 >>
    User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_232) 16:46:08.999
    [main] DEBUG org.apache.http.headers - http-outgoing-0 >>
    Accept-Encoding: gzip,deflate 16:46:08.999 [main] DEBUG
    org.apache.http.wire - http-outgoing-0 >> "GET /private/openapi
    HTTP/1.1[\r][\n]" 16:46:08.999 [main] DEBUG org.apache.http.wire -
    http-outgoing-0 >> "Host: api.serviceprovider.com:443[\r][\n]"
    16:46:08.999 [main] DEBUG org.apache.http.wire - http-outgoing-0 >>
    "Connection: Keep-Alive[\r][\n]" 16:46:08.999 [main] DEBUG
    org.apache.http.wire - http-outgoing-0 >> "User-Agent:
    Apache-HttpClient/4.5.3 (Java/1.8.0_232)[\r][\n]" 16:46:08.999 [main]
    DEBUG org.apache.http.wire - http-outgoing-0 >> "Accept-Encoding:
    gzip,deflate[\r][\n]" 16:46:08.999 [main] DEBUG org.apache.http.wire -
    http-outgoing-0 >> "[\r][\n]" 16:46:09.037 [main] DEBUG
    org.apache.http.wire - http-outgoing-0 &lt;&lt; "[read] I/O error: Received
    fatal alert: handshake_failure" 16:46:09.037 [main] DEBUG
    org.apache.http.impl.conn.DefaultManagedHttpClientConnection -
    http-outgoing-0: Close connection 16:46:09.037 [main] DEBUG
    org.apache.http.impl.conn.DefaultManagedHttpClientConnection -
    http-outgoing-0: Shutdown connection 16:46:09.037 [main] DEBUG
    org.apache.http.impl.execchain.MainClientExec - Connection discarded
    16:46:09.038 [main] DEBUG
    org.apache.http.impl.conn.PoolingHttpClientConnectionManager -
    Connection released: [id: 0][route:
    {tls}-><a href="http://x.x.x.120:8080-" rel="nofollow noreferrer">http://x.x.x.120:8080-</a>><a href="https://api.serviceprovider.com:443][total" rel="nofollow noreferrer">https://api.serviceprovider.com:443][total</a>
    kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
    javax.net.ssl.SSLHandshakeException: Received fatal alert:
    handshake_failure     at
    sun.security.ssl.Alerts.getSSLException(Alerts.java:192)  at
    sun.security.ssl.Alerts.getSSLException(Alerts.java:154)  at
    sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2020)     at
    sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1127)    at
    sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:933)
      at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)    at
    org.apache.http.impl.conn.LoggingInputStream.read(LoggingInputStream.java:84)
      at
    org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
      at
    org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
      at
    org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:282)
      at
    org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:138)
      at
    org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
      at
    org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
      at
    org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
      at
    org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:165)
      at
    org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
      at
    org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
      at
    org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
      at
    org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
      at
    org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
      at
    org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
      at
    org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
      at
    org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:118)
      at
    ru.bcs.creditmarkt.delivery.adapter.ServProvAuthTest.testConn(ServProvAuthTest.java:99)</p>
  </blockquote>