We have a java application which runs on Java Version: 1.7.0_80 and we are trying to enable TLSv1.2 with the jvm argument -Dhttps.protocols=TLSv1.1,TLSv1.2
-Djdk.tls.client.protocols=TLSv1.1,TLSv1.2-Ddeployment.security.TLSv1=false
-Ddeployment.security.TLSv1.1=true
-Ddeployment.security.TLSv1.2=true to consume a web service which supports only TLSv1.2. Though we have the jvm argument java client still using TLSv1 for communicating with web services,
can someone please help me is there any jvm configurations I need to make to use TLSv1.2 without any code change?
Without any code change, as I wrote in the comment, you need at least 7u95.
jdk.tls.client.protocols system property. To enable specific SunJSSE
protocols on the client, specify them in a comma-separated list within
quotation marks; all other supported protocols are then disabled on
the client. For example, if the value of this property is
"TLSv1,TLSv1.1", then the default protocol settings on the client for
TLSv1 and TLSv1.1 are enabled on the client, while SSLv3, TLSv1.2, and
SSLv2Hello are disabled on the client. This propery has been available
since Java SE 7u95.
The same property is also available since Java 6u121, with Java 6 supporting and implementing TLS 1.2.
Related
We initialise our SSL context with the following code and are running on Java 8.
SSLContext context = SSLContext.getInstance("SSL");
Since Java 8 uses TLSv1.2 by default? Does it mean the above code will start sending TLSv1.2 requests if my server supports it.
Want to understand if "SSL" protocol name is just an alias but java runtime starts sending the requests with default TLS version.
UPDATE
I ran my code against "https://www.google.co.in/" and found this in fiddler
A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
Version: 3.3 (TLS/1.2
And also if i change my protocol to TLSv1 which only supports 1.0. Then Fiddler tells me
A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
Version: 3.1 (TLS/1.0)
So, I guess the above code with "SSL" protocol name should work well with TLS 1.2 servers.
Yes. In Java 7, server side default TLS version was 1.2. In Java 8 both server and client have default TLS version 1.2.
As TLS version is backward compatible on both side unless server is configured strictly to specific version should not be an issue.
I use IBM JDK J9 on AIX OS.
I want to know what I need to change in the java.security file to enable the SSLv3 Secure Socket Layer protocol. Or is there another file that needs to be changed to enable this protocol?
Delete or comment out the following line "jdk.tls.disabledAlgorithms=SSLv3"
I am trying to record a https site through jmeter (version 2.13, java version - 1.8u31) and I am getting SSLHandshakeException while connecting to a https site. The error message is
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:2011)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1113)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:436)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.jmeter.protocol.http.sampler.MeasuringConnectionManager$MeasuredConnection.open(MeasuringConnectionManager.java:107)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:643)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.executeRequest(HTTPHC4Impl.java:517)
at org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sample(HTTPHC4Impl.java:331)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(HTTPSamplerProxy.java:74)
at org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase.sample(HTTPSamplerBase.java:1146)
at org.apache.jmeter.protocol.http.proxy.Proxy.run(Proxy.java:240)
I have turned on debug logging for SSL but I wasn't able to understand the root cause. It seems that the java client sends the ClientHello but does not receive the ServerHello message (where the server chooses the highest version of SSL and the best cipher suite that both the client and server support and sends this information to the client). I see differences between the protocol versions being sent, read and received by the client (TLSv1.1 vs TLSv1.2)
Is this the root cause ? If so, how can I fix it?
The logs are pasted here - Java SSLHandshakeException Logs - Pastebin.com
Update
As #Anand Bhatt suggested, I analyzed the site with ssllabs and understood the following
The server does not support TLSv1.2 which is supported by java 8
The server supports only one cipher suite - TLS_RSA_WITH_AES_256_CBC_SHA
Java 8u31 doesn't support the cipher suite that the server supports and that's most probably the issue.
Does that sound right? If so, how do we make the java 8 client support the cipher suite that the server supports?
SSLlabs is apparently testing "out of the box" support. Java crypto has a crock dating back to the 1990s when the US government severely restricted export of crypto software,
and as a result the JRE (or JDK) as distributed by then-Sun now-Oracle does not permit use of 256-bit symmetric encryption, which your server is demanding. You must download and install
the "JCE Unlimited Strength Jurisdiction Policy Files" for your Java (major) version; 8 is at http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html .
The README in the file gives longwinded details, but basically you replace two tiny jar files in JRE/lib/security.
TLSv1.2 is not a real issue now. TLS protocol automatically negotiates the highest version supported (and enabled) by both ends.
Java 8 implements SSLv3, TLSv1.0, TLSv1.1 and TLSv1.2, but recent updates (8u31 or 7u75 and up) disable SSLv3 by default because of POODLE;
you can re-enable it if you choose, but you should be reluctant to. (Java 7 implements the same protocol versions, but client by default disables 1.1 and 1.2 because of compatibility concerns at its release several years ago.)
However, because of POODLE and BEAST some security authorities no longer accept SSLv3 and TLSv1.0
as adequately secure; an important example is credit and debit cards, as detailed in https://security.stackexchange.com/a/87077/39571 .
TLSv1.2 includes some technical improvements over 1.1, making it preferred today, and there might be future discoveries that make those
improvements crucial; if your server can't support 1.2 (and maybe higher) at that point you would be in trouble. Similarly the fact that the server's only
supported suite uses plain-RSA key-exchange, i.e. NOT forward secrecy, is considered suboptimal now, and over time may become unacceptable.
keytool (at least with the normally used keystore and truststore files) has nothing to do with symmetric cryptography.
It could likely be relevant if the server uses a CA root (or more exactly and slightly more general, trust anchor)
that your JRE and/or application does not trust, and/or if the server wants client authentication at SSL/TLS level,
which is fairly rare. (Most websites authenticate at the web-application level, or at least HTTP level, if at all.)
SSLLabs checking of the server cert chain (and several other things also) is generally stricter than Java's, and they
didn't complain in that area, so it's unlikely you have a problem there.
I'm looking at the JSSE reference guide, I need to obtain an instance of SSLContext in order to create a SSLEngine, so I can use it with Netty to enable security.
To obtain an instance of SSLContext, I use SSLContext.getInstance(). I see that the method is overridden multiple times, so I can chose the protocol and security provider to use.
Here, I can see the list of algorithms that can be used. Which algorithm should I use to enable secure communication?
Also, since it is possible to specify the security provider to use, which provider should I use?
Thanks
As you can see in the standard names documentation, all entries (SSLv3, TLSv1.0, TLSv1.1, ...) say that they may support other versions.
In practice, in the Oracle JDK (and OpenJDK), they all do. If you look at the source code, the TLS10Context class is what's used for TLS, SSL, SSLv3 and TLS10, TLS11Context is used for TLSv1.1 and TLS12Context for TLSv1.2. All support all versions of SSL/TLS, it's what's enabled by default that varies.
This may be different with another provider or JRE vendor. You should of course pick one that's at least going to support the protocol version you want to use.
Note that the protocol used is determined later on using SSLSocket.setEnabledProtocols(...) or its SSLEngine equivalent.
As a general rule, use the highest version number you can (SSLv3 < TLSv1.0 < TLSv1.1 ...), which may depend on what the parties with which you want to communicate support.
Which protocols are enabled by default varies depending on the exact version of the Oracle JRE.
When looking at the source code for sun.security.ssl.SunJSSE in OpenJDK 7u40-b43, TLS is simply an alias for TLSv1 (and so are SSL and SSLv3), in terms of SSLContext protocols. Looking at the various implementations of SSLContextImpl (which are inner classes of SSLContextImpl itself):
All support all protocols.
All protocols are enabled on the server side by default.
the client-side protocols enabled by default vary:
TLS10Context (used for protocol SSL, SSLv3, TLS, TLSv1) enables SSLv3 to TLSv1.0 by default on the client side.
TLS11Context (used for protocol TLSv1.1) also enables TLSv1.1 by default.
TLS12Context (used for protocol TLSv1.2) also enables TLSv1.2 by default.
If FIPS is enabled, SSL is not supported (so not enabled by default).
This changes in Java 8, in conjunction with the new jdk.tls.client.protocols system property.
Again, when looking at the source code for sun.security.ssl.SunJSSE in OpenJDK 8u40-b25, SSLContext protocols TLSv1, TLSv1.1, and TLSv1.2 also make use of TLS10Context, TLS11Context and TLS12Context, which follow the same logic as in Java 7.
However, protocol TLS is no longer aliased to any of them. Rather, it uses TLSContext which relies on the values in the jdk.tls.client.protocols system properties. From the JSSE Reference guide:
To enable specific SunJSSE protocols on the client, specify them in a comma-separated list within quotation marks; all other supported protocols are then disabled on the client. For example, if the value of this property is "TLSv1,TLSv1.1", then the default protocol settings on the client for TLSv1 and TLSv1.1 are enabled on the client, while SSLv3, TLSv1.2, and SSLv2Hello are disabled on the client.
If this property is empty, all protocols are enabled by default on both client and server side.
Of course, in recent versions of Oracle JRE 8, SSL is also completely disabled by default (so removed from those lists).
Note that in both cases (JRE 7 and 8), the SSLContext you get by default via SSLContext.getDefault() out of the box is more or less equivalent to an SSLContext obtained with protocol TLS and initialised with the default truststore parameters and so on.
There is no default for the protocol, so I would use the latest one supported by your JDK, which is either TLSv1, TLSv1.1 or TLSv1.2: see which works, or have a look at getSupportedProtocols(). The default security provider is used by avoiding all the APIs where you specify it, or else e.g. KeyStore.getDefaultType().
And when you come to get your SSLEngines, make sure you use the method that takes a hostname and port. Otherwise you will get no SSL session sharing.
(Disclaimer: I am by no stretch of the imagination a security expert nor a windows expert for that matter)
Setup:
server on our end: java 1.6 (already added bouncycastle to the security file) on windows 2003 server
third party client: windows 2008 server with biztalk
all renegotiation system properties introduced due to the renegotiation attack are "enabled" on the server side (not safe I know)
Ideally we want to fix this at our end but it is possible to propose a fix to the client if necessary.
The client server has to connect to our server over a HTTPS connection but it always fails, wireshark shows the following conversation:
> TLSv1: Client Hello
< TLSv1: Alert (21): Unexpected Message
As per the RFC (http://www.ietf.org/rfc/rfc2246.txt) the alert(21) refers to a failed decryption and from what I can see in wireshark, none of the ciphers proposed by the client are actually supported by JRE 1.6 (as per http://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html#SupportedCipherSuites)
In an effort to reproduce the error to be able to examine it closer, I tested with some other software:
wfetch on windows xp with "https" selected will perform the initial client handshake in SSLv2, the server will switch to TLSv1 to answer, this works
wfetch on windows xp with configured to use "TLSv1" for the initial handshake will fail in the same way as the biztalk server
wfetch on windows 2008 with configured "https" will use "TLSv1" for the initial handshake and fail in the same way as the biztalk server
IE (on windows xp) will initially try a TLSv1 handshake with the same failed result but immediately tries again using SSLv3 which works
(at this point I figure all microsoft software uses a central configuration available at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel)
firefox uses SSLv3 for the entire conversation, so no problem there
OpenSSL performs an initial handshake in SSLv2, and the server switches to TLSv1 when it answers, no problem there
OpenSSL can be forced to do the initial handshake in TLSv1 as well, it offers a list of 27 ciphers (as opposed to the 11 ciphers proposed by windows-based software) and can connect without a problem
To my untrained eye this reinforces the idea that an incompatible cipher proposition is the root cause where windows only supports cipher suites that are not supported by JVM (for TLSv1).
I have installed bouncy castle as an additional provider in the java.security file to no avail.
I have searched high and low and only found a reference that maybe websphere supports the windows ciphers for TLSv1 but no way of downloading a standalone provider to test it.
JRE 1.7 is not supported by the software we run on our JVM, so upgrading is not an option (perhaps the security provider can be downgraded safely? I haven't found a download for it yet though)
I have found no way to add a cipher to windows short of writing c++ code (I've played around with the above mentioned registry settings without effect).
So in conclusion I wonder if one of the following things would fix it and how they should be accomplished:
add a provider to the jvm that can work with the ciphers for TLSv1 that are proposed by windows
somehow force the client to do the initial handshake in SSLv3 (preferably not SSLv2) or at least retry if the TLSv1 handshake fails
somehow add a JVM-supported cipher for TLSv1 to the client windows
Any other solutions are of course also appreciated.
EDIT
The Java version is Java version (64 bit): 1.6.0_19-b04.
The list of proposed ciphers is:
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_DES_CBC_SHA
TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA
TLS_RSA_EXPORT_WITH_RC4_40_MD5
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_DHE_DSS_WITH_DES_CBC_SHA
TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA
The unlimited strength cryptography policy files are installed. I have tried to set javax.net.debug=all and started the server from the console, no additional output appeared. I have set sun.security.ssl.allowUnsafeRenegotiation=true to no avail.
EDIT 2
It turns out the software we are using uses a custom stack for HTTPs instead of the default. A fix was issued which seems to solve the problem though I don't know exactly which part of the TLS request triggered the error (seeing as most TLSv1 handshakes did succeed).
Thanks for the feedback, it has been an interesting if futile search. Live and learn.
It turns out the software we are using uses a custom stack for HTTPs instead of the default. A fix was issued which seems to solve the problem though I don't know exactly which part of the TLS request triggered the error (seeing as most TLSv1 handshakes did succeed).
Thanks for the feedback, it has been an interesting if futile search. Live and learn.
You could read my article on detecting cipher strength (just to make sure you installed the jce ciphers correctly) . In your question you say you installed unlimited ciphers but then you reference 128 and 40-bit keys. So, I am confused by what you have. Also, could you check the cipher strength on the SSL cert you are trying to connect to and let us know what it is and what the algorithm is? Also, make sure your policy file for JDK has the proper rights to allow unlimited strength.
Finally, can you connect to a "known good" SSL site to verify your client handshakes correctly? (Gmail web for example)