I'm working on a Java 6 project using Apache HttpClient 3.5 and Spring Web Services 2.1.0.
My Spring WebServicesTemplate is sending WebServices requests using an apache HttpClient. However, the service that I am contacting has phased out TLS 1.0 in favor of TLS 1.2. Java 6 does not support TLS 1.2. I was led to bouncycastle, which should give me TLS 1.2 support.
How can I integrate bouncycastle with Spring or my HttpClient, so that I can send requests that support TLS 1.2? I have found a solution which provides an extended SSLSocketFactory. However, HttpClient only accepts SSLConnectionSocketFactory.
Upgrading to Java 8 is not feasible in the short term, but I can make it a long-term priority if someone can confirm that it would fix my issue.
The main problem you will face with Bouncy Castle is that its TLS implementation does not implement the JSSE API. Practically, this means you won't get any support for
SSLSocket
,SSLSocketFactory
(orHttpsURLConnection
, but that doesn't matter when you're using Apache HTTP Client).In addition, TLS isn't the best documented feature of Bouncy Castle, which is going to make your work more difficult. There are examples in the answers to this other question.
You might somehow be able to write you custom
Socket
implementation that wraps the necessary calls to Bouncy Castle's TLS API. You could then return such sockets from your customorg.apache.http.conn.ssl.SSLConnectionSocketFactory
implementation (you could probably use dummy values in the constructors if your subclass does something completely different for its method that return aSocket
anyway).This might be feasible, but it will probably require a considerable amount of effort. An upgrade to Java 8 (which supports TLS 1.2 with the traditional JSSE classes) would generally be easier (depending on your constraints).
I have come up with a solution that does not require upgrading to Java 8. As a disclaimer, I know very little about https security, and I'm sure there are some issues that a more knowledgeable person may notice. This method requires using the built-in HttpsURLConnection, which is very primitive if you're used to using things like Unirest, or even apache HttpClient.
First you need to add BouncyCastle to you pom.
Then you will create an extension of SSLSocketFactory. Warning! This socket factory will accept all certificates, so use at your own risk.
Next, you need to use your new socket factory. If you are using Spring to handle your Web Services calls, you can extend the existing HttpUrlConnectionMessageSender in order to send your calls for you. Just make sure to update your message sender bean in your spring config to use this class.
Alternatively, if you are not using Spring, or using Rest, you can manually create an HttpsURLConnection as is done in the class above, and send your messages using the outputstream.
Beware that if the service you are communication with uses cookies, you will need to set a system-wide cookie manager. However, the Java 6 cookie manager is bug-ridden. You may need to copy the source-code from the Java 8 CookieManager in order for your cookies to work.