Java use SSLContext for HttpsURLConnection - java

Looking for an example to open HttpsURLConnection with SSLContext and restricted to TLSv1.2. The context is built using trust store and trust key and after I added the custom() call - the TLS setting seem to be changed to just "TLS" vs. "TLSv1.2"
my code is:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext = SSLContexts.custom()
.loadTrustMaterial(getKeyStore(trustStoreURL, trustStorePassword), new TrustSelfSignedStrategy())
.loadKeyMaterial(getKeyStore(keyStoreUrl, keyStorePassword), keyStorePassword.toCharArray()).build();
So after the custom() I see "TLS" in sslContext properties.

Why do you want to use only a single version, is there any restriction on your server host ? Most modern servers use TLSv1.2 which is backward compatible to one or two versions.
When you use TLSv1.2 while creating socket factory like below,
SSLSocketFactory.getInstance("TLSv1.2")
the default allowed protocols would be SSL, TLS, TLSv1.1, TLSv1.2.
With that being said, to answer your question,
You can set your SSLSocket to enable just a few protocols using the setEnabledProtocols method. Please check this doc for more on this.
Once done, your SSL connection will allow only the specified protocol.

Related

How to enforce a particular TLS version in Java 16+ without setting global properties

I know that a particular TLS version can be enforced with a global property, like so:
with code: System.setProperty("jdk.tls.client.protocols", "TLSv1.2");
or from the command line: java -Djdk.tls.client.protocols=TLSv1.2 ...
Is there a way to do that in a more refined, on SSL per-context/engine bases? For example, what if I want to prevent usage of TLSv1.3 in a particular context, and only allow protocols up to TLSv1.2?
I thought this was the way:
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
...
var sslContext = SSLContext.getInstance("TLSv1.2");
var sslEngine = sslContext.createSSLEngine();
...
but my tests still show TLSv1.3 creeping in the SSL handshake phase. Indeed,
the Java 16+ java doc explains that the "protocol" parameter guarantees provider with support for the requested TLS version, but does not necessarily restrict the provider from going higher:
SSLContext.getProtocol(String protocol);
javadoc:
protocol – the standard name of the requested protocol. See the SSLContext section in the Java Security Standard Algorithm Names Specification for information about standard protocol names.
P.S: I found something closer to what I need answered here:
Will SSLContext.getInstance("TLS") supports TLS v1.1 and TLS v1.2 also?
To use TLSv1.2 try to use below code:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
Assuming the answer is correct(I think it is not), however I do want to initialize my context from specific trust store and key store managers, passing NULLs is not acceptable to me.

How make rest service to use only TLS V1.2 using java or spring libraries?

The service provider who is hosting a rest service is asking to communicate using TLS version 1.2 only.
So now I need to make my application to communicate with that service using TLS v 1.2.
I know, in java8 we have an option of disabling the legacy version of TLS and SSL using the property jdk.tls.disabledAlgorithms=SSLv3, RC4 in java.security file.
But in a server there will be other process using the same java settings, so I'm worried like if I change for that property in java.security file, then it will be applicable to other services which are using the same settings.
Question:
I would like to know if there is any other way to make my rest calls use only particular TLS version, through application code using java/spring libraries ?
Create a SSLContext to use the required protocol:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
If the client code or library uses HttpsURLConnection then you can set the default SSLSocketFactory for all the HTTS Connections:
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
Or at a per connection level:
HttpsURLConnection urlConnection = ....;
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
urlConnection.connect();
Different libraries may have different systems to provide the SSLSocketFactory or SSLContext.
For example, if you are using JAX-RS, you can create a REST client that uses the SSLContext with:
Client client = ClientBuilder.newBuilder().sslContext(sslContext).build();

Enabling TLSv1.2 as default in JDK 7

I want to enable TLSv1.2 as default protocol for clients in jdk7. I can see java 7 supports TLS v1.1, 1.2 but the default enabled is TLSv1.0.
I have gone through some post like this one here which says the client application has to specify in startup scripts which security protocol they want to use or the other way to do this is by java programming.
So is there any way out by which I can chnage the default enabled protocol to TLSv1.2 So that no chnage is required in all the running client application.
This is the code which we are using to initiate SSL connection.
//create the SSLContext with your key manager and trust
//manager, and get your socket factory from the context:
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(km, tm, null);
SSLSocketFactory factory = ctx.getSocketFactory();
Change it to this at the entry point of your Main
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
SSLContext.setDefault(sslContext);

how to build a web service client through ssl

I'm new to SSL and security and I want to build a java client for a web service that uses SSL. the server is properly configured to use two way ssl configuration, but how to build the client..
also if spring has anything for this it will be good..
thanks in advance
You dont have to do nothing special with the client, just use HTTPS on your request instead HTTP.
to get things work you have to create a client keystore and truststore, then define SSLContext with these stores, then instantiate SSLSocketFactory to produce SSLSockets like this:
SSLContext sslcontext = SSLContexts.createDefault();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext, SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
you should read this http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html to understand how it works.
also this question how to write java client and server applications that uses mutual ssl authentication between them? may be useful.

Java Client to connect to Server with Openssl and Client Auth

I have to write a Java Client to connect to an SSL server. The server uses openssl certificate, and is configured to do Client Auth.
I can't seem to locate any useful resources online that can help me (who doesn't know anything about openssl and much about SSL) to understand who to go about implementing my Client Side.
Help!
The twist here is that you are using client authentication, so you need a private key and a certificate to identify yourself. You provide this to JSSE by specifying KeyManagers when you initialize an SSLContext.
Customizable Setup
Following are the basic steps. The JSSE API was significantly improved in Java 6, but I'll stick with Java 5, in case you're stuck on that version.
KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
tks.load(...); /* Load the trust key store with root CAs. */
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(tks);
KeyStore iks = KeyStore.getInstance(KeyStore.getDefaultType());
iks.load(...); /* Load the identity key store with your key/cert. */
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(iks, password);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SocketFactory factory = ctx.getSocketFactory();
Socket socket = factory.createSocket(host, port);
System Configuration
An alternative "zero-config" scenario can be used when using the SunJSSE provider. I believe many other providers (like IBM) have followed the same pattern and will work as well. The mechanism uses system properties, and is described in detail by the JSSE Reference Guide.
For client authentication, the important properties are javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword. The values should be the path to the user's key store and the password for that key store's "key entries", respectively.
When using these properties, you can create a new SSLSocket that supports client authentication like this:
SocketFactory factory = SSLSocketFactory.getDefault();
Socket socket = factory.createSocket(host, port);
Since you are using the "default" SSLSocketFactory, which depends on the system-wide properties, all sockets created in the JVM will authenticate with the same certificate. If you need more control than that, you have to use the "Customizable Setup" above.
Java includes SSL support in the standard API. Have a look at these classes in the 1.5.0 javadoc:
SSLSocket if you're doing the comms logic yourself.
HttpsURLConnection if the server side speaks HTTP
You could use httpclient. Have a look at this SSL guide.

Categories