5

In a spring boot application using java8, I am setting the underlying SSLConext of an httpClient connection as follows:

 import javax.net.ssl.SSLContext;

  SSLContext sslContext =  SSLContext.getInstance("TLSv1.2");
  sslContext.init(null, null, null); 

  CloseableHttpClient httpClient = HttpClientBuilder
          .create()
          .setConnectionManager(myConnectionManager)
          .setDefaultRequestConfig(rqConfig)
          .setSSLContext(sslContext)
          .build();

I need to set the cipher suites for the underlying TLS1.2 secured connection to something stronger of my choice. I don't see a way to do this with the way I am creation the sslContext in my code.

Can someone help me set up the cipher suites with my sslContext ?

================UPDATE=================

 This is how I have now created my HttpClient

 CloseableHttpClient httpClient = HttpClientBuilder
          .create()
          .setConnectionManager(myConnectionManager)
          .setDefaultRequestConfig(rqConfig)
          .setSSLSocketFactory(new SSLConnectionSocketFactory(
                  SSLContexts.createSystemDefault(),
                  new String[]{"TLSv1.2"},
                  new String[] {"some-gibberish-cipher-suite"},
                  SSLConnectionSocketFactory.getDefaultHostnameVerifier()))
          .build();
Ray S
  • 569
  • 1
  • 8
  • 18

1 Answers1

4

Preferred TLS protocol versions and custom ciphers can be specified when creating a custom SSLConnectionSocketFactory instance

CloseableHttpClient client = HttpClients.custom()
    .setSSLSocketFactory(new SSLConnectionSocketFactory(
            SSLContexts.createSystemDefault(),
            new String[]{"TLSv1.2"},
            new String[] {"TLS_RSA_WITH_AES_256_CBC_SHA256"},
            SSLConnectionSocketFactory.getDefaultHostnameVerifier()))
    .build();
try (CloseableHttpResponse response = client.execute(new HttpGet("https://httpbin.org/"))) {
    System.out.println(response.getStatusLine());
    HttpEntity entity = response.getEntity();
    EntityUtils.consume(entity);
}

Alternatively, one can create a custom PoolingHttpClientConnectionManager instance with the desired SSL configuration.

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", new SSLConnectionSocketFactory(
                SSLContexts.createSystemDefault(),
                new String[]{"TLSv1.2"},
                new String[]{"TLS_RSA_WITH_AES_256_CBC_SHA256"},
                SSLConnectionSocketFactory.getDefaultHostnameVerifier()))
        .build());

CloseableHttpClient client = HttpClients.custom()
    .setConnectionManager(cm)
    .build();
try (CloseableHttpResponse response = client.execute(new HttpGet("https://httpbin.org/"))) {
    System.out.println(response.getStatusLine());
    HttpEntity entity = response.getEntity();
    EntityUtils.consume(entity);
}
ok2c
  • 26,450
  • 5
  • 63
  • 71
  • How come when I enter any gibbering for the cipher, it just works fine and I get a valid response from the server. Is there any kind of validation by the TLS framework on the the cipher suite used in the TLS call ? – Ray S Dec 28 '18 at 15:01
  • You are doing something wrong, like throwing away all your SSL customization by setting a connection manager with `#setConnectionManager`. See `HttpClientBuilder` javadoc. – ok2c Dec 28 '18 at 16:52
  • please check my update in this post to see the code that I have currently. – Ray S Dec 28 '18 at 18:06
  • It looks like the connectionManager in my code will override the sslconnectionSocketFactory. Is there way to use both or a way to set cipher suites using connectionManager separately ? – Ray S Dec 28 '18 at 18:21
  • _Please_ read javadoc of `HttpClientBuilder`! `#setSSLSocketFactory` has no effect due to `#setConnectionManager` setting a fully initialized connection manager – ok2c Dec 28 '18 at 18:22
  • The way you have created PoolingHttpClientConnectionManager, is it going to be ok to set MaxTotal and other properties using cm.setMaxTotal after the connectionmanager is built using .build() ? – Ray S Dec 28 '18 at 18:59
  • It is not very clear from javadocs as to which overloaded constructor would be able to achieve both i.e. setting the sslcontext and maxTota as well – Ray S Dec 28 '18 at 19:41
  • https://github.com/apache/httpcomponents-client/blob/4.5.x/httpclient/src/main/java/org/apache/http/impl/client/HttpClientBuilder.java#L1009 – ok2c Dec 28 '18 at 19:57
  • @RayS To your question on if you would be able to set maxTotal etc after invoking the constructor of PoolingHttpClientConnectionManager as suggested by oleg, yes you can do that. Those are just the state members of the class and that is what you would have done by using no arg constructor. If you check the PoolingHttpClientConnectionManager API, no arg constructor does exactly the same thing what the constructor that has suggested to you. You are just using your own custom sslsocketfactory instead of a default one. – Hary Dec 28 '18 at 20:36