I have enabled logs in my application using -Djavax.net.debug=all option. Code that have written is supposed to use SSLv3 protocol, but in logs when I am checking it is displaying as ::
*** ClientHello, TLSv1
*** ServerHello, TLSv1
As far as I understand from reading is, Client and Server using TLSv1 for handshake, but as I have used SSLv3 in my code while initiating socket, ideally it should print SSLv3 instead TLSv1.
Below is the code snippet I have used :
SSLContextBuilder builder = new SSLContextBuilder();
builder.useProtocol("SSLv3");
SSLContext sslContext = builder.build();
Can someone please clarify the reason for the same, or is there something else I have missed out. Just to add on I am on Java 7.
Most probably SSLv3 is just not supported by server (which is recommended configuration nowadays because of security), so the lib uses least supported TLS version.
UPD: seems that hello format says nothing about what protocol will be used in fact. There's something from Java docs:
Currently, the SSLv3, TLSv1, and TLSv1.1 protocols allow you to send SSLv3, TLSv1, and TLSv1.1 hellos encapsulated in an SSLv2 format hello. For more details on the reasons for allowing this compatibility in these protocols, see Appendix E in the appropriate RFCs (previously listed).
Note that some SSL/TLS servers do not support the v2 hello format and require that client hellos conform to the SSLv3 or TLSv1 client hello formats.
The SSLv2Hello option controls the SSLv2 encapsulation. If SSLv2Hello is disabled on the client, then all outgoing messages will conform to the SSLv3/TLSv1 client hello format. If SSLv2Hello is disabled on the server, then all incoming messages must conform to the SSLv3/TLSv1 client hello format.
Related
I am running embedded Jetty server with https/TLS enabled on it. It works perfectly with all modern browsers (TLSv1.2).
We have a legacy browser (.exe whose code cannot be changed/checked) which we are trying to connect to Jetty server over https, which is failing.
I debugged SSL on jetty side and came to know that this browser is connecting using TLSv1, so I did the following:
sslContextFactory.setIncludeProtocols( "TLSv1");
After this, I started getting error "no cipher suits in common" on server side. To pass this (I know this is dangeropus, but still for now), I did:
sslContextFactory.setExcludeCipherSuites();
After doing this, I don't see any error on server side, but still legacy browser is unable to connect. (It can connect to other https site though as facebook, google).
Server side logs after above change:
WRITE: TLSv1 Handshake, length = 48
called closeOutbound()
closeOutboundInternal()
SEND TLSv1 ALERT:
warning,
close_notify
WRITE: TLSv1 Alert, length = 32
Any idea what can be wrong here? I tried to do a lot of googling on it but cannot work it through. I also tried enabling SNI on server, but with no luck.
Any help would be very appreciated.
Thanks
edit1:
If I compare Jetty SSL logs with working request, I see below difference. Working request is sending application data also as below:
WRITE: TLSv1 Application Data, length = 1285
In non-working request, I see below additional line (TLS_RSA_WITH_AES_128_CBC_SHA is cipher suite name):
Cached server session: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
There is an issue with Jetty 9.4.*
https://github.com/eclipse/jetty.project/issues/3773
https://github.com/eclipse/jetty.project/issues/2807
which blindly excludes TLS1.0 and TLS1.1.
The fix
is (a) to call setExcludeCipherSuites() after SslContextFactory is contructed as mentioned above,
or (b) just override SslContextFactory.setExcludeCipherSuites(final String... cipherSuites) to do nothing, as below:
final SslContextFactory sslContextFactory = new SslContextFactory()
{
#Override
public void setExcludeCipherSuites(final String... cipherSuites)
{
// do nothing intentionally.
}
};
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.
Just letting folks know about an issue I had that many seemed to have had after upgrading to Java 1.8. Not all of the solutions are the same hence posting how I resolved this.
But first... This is not a solution worthy of production systems since security is being effectively downgraded. However, if you are blocked testing etc. it is probably quite suitable.
My issue was that no matter what I did... enabled SSLv3 etc. I always received
"javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure".
Here are the steps I took to 'solve' this.
First, I discovered which cipher the server was using. I did this via openssl.
openssl s_client -host yourproblemhost.com -port 443
This yields (at the end...)
SSL-Session:
Protocol : TLSv1.2
Cipher : RC4-MD5
Now.. what do we use 'Java-wise' to enable that cipher?
Oracle link
In that link, it has the names and their Java counterpart. So for RC4-MD5, we have SSL_RSA_WITH_RC4_128_MD5.
ok good. Now I added a System property.
-Dhttps.cipherSuites=SSL_RSA_WITH_RC4_128_MD5
And in my code...
Security.setProperty("jdk.tls.disabledAlgorithms", "" /*disabledAlgorithms */ );
Again.. this is an absolute last resort 'fix'... But if you're hitting your head aganst a wall to get it running (for testing), I hope it comes in useful.
With JDK 1.8.0_51 release RC4 is no longer supported from Java as client (also as server) to negotiate SSL handshake, RC4 is considered weak (and compromised ) cipher and that is the reason for removal
http://bugs.java.com/view_bug.do?bug_id=8076221
You can still however enable it by removing RC4 from jdk.tls.disabledAlgorithms from your Java security config or progamatically enabling them using setEnabledCipherSuites() method
However better solution would be to update the server configuration (if it is under your control) to upgrade to stronger Ciphers
RC4 is now considered as a compromised cipher. RC4 cipher suites have been removed from both client and server default enabled cipher suite list in Oracle JSSE implementation. These cipher suites can still be enabled by SSLEngine.setEnabledCipherSuites() and SSLSocket.setEnabledCipherSuites() methods.
As to your approach on setting it by using Security.setProperty(), it is not reliable way because the fields which hold disabled algorithms are static and final, So if that class gets loaded first you don't have controll over it, you could alternatively try by creating a properties file
like this
## override it to remove RC4, in disabledcipher.properties
jdk.tls.disabledAlgorithms=DHE
and in your JVM, you could refer it as system property like this
java -Djava.security.properties=disabledcipher.properties blah...
RC4 was effectively cracked - 14 years ago.
The Fluhrer, Mantin and Shamir (FMS) attack, published in their 2001
paper "Weaknesses in the Key Scheduling Algorithm of RC4", takes
advantage of a weakness in the RC4 key scheduling algorithm to
reconstruct the key from encrypted messages.
The problem isn't in Java 8.
The problem is your server is using RC4.
Thanks alton for sharing such a life saver information.
Only one thing I'd like to change
since
openssl s_client -host yourproblemhost.com -port 443
returned ->
Protocol : TLSv1.2
Cipher : 0000
openssl s_client -connect X.X.X.X:993 -prexit -tls1
returned -> the expected response as
Protocol : TLSv1
Cipher : RC4-MD5
I have TLS client writen in JAVA. When i set
sslContext = TLS1.2
and enabled protocols to SSLv3 TLSv1 TLSv1.1 TLS1.2
it works fine with almost all servers. Client start handshake with TLSv1.2. If server can only TLSv1, connection downgrades to TLSv1 during handshake.
But! We use about 15 such TLSv1 services and 4 of them fails to downgrade. Servers are all different:
Microsoft-IIS/7.5, nginx, IBM_HTTP_SERVER, SQLAnywhere.
Errors like this:
SEND TLSv1 ALERT: fatal, description = unexpected_message X2
handling exception: javax.net.ssl.SSLException: Invalid Padding length: 139
javaException : Received fatal alert: unexpected_message
If i set enabled protocols to TLSv1, that servers works fine. But i want set sslContext and enabled protocols to be compatible with all services and preferably work with TLSv1.2
Any suggestions will be appreciated!
But i want set sslContext and enabled protocols to be compatible with all services and preferably work with TLSv1.2
First, there are enough servers out there which don't do TLS 1.2 but the best they can do is TLS 1.0 (and some even only SSL 3.0). A proper implementation of the TLS stack would in this case simply send a TLS 1.0 reply and thus enforcing the connection to be TLS 1.0 which is supported in your client. Forcing these servers to TLS 1.2 will not work because they don't implement it. All you could do is replace the servers with newer implementations.
And then there are several implementations out there which incorrectly implement the protocol. Some of these simply close the connection if you send a TLS 1.2 ClientHello or use some TLS extensions they never heard of. If you can not replace these servers you have to communicate with them in a way they will understand, like speaking only TLS 1.0 etc. Browsers already deal with this rotten servers by slowly downgrading the connection, i.e. if TLS 1.2 causes a handshake failure they will try again with TLS 1.0 etc. Often browsers even have hard coded a list of servers which are too rotten to even play nice after trying simple downgrads and which need to have special ciphers or something like this.
I am working on configuring a Java client which its job is to make TLS connections to servers. I want to configure my client with these 3 ciphers:
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_MD5
In Java supported cipher suites, I found the same ciphers but with SSL at the beginning NOT TLS. The question, if I configured my client with:
SSL_RSA_WITH_RC4_128_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_RC4_128_MD5
Are the two lists exactly the same and will be interpreted by the server same? I am worried if I configured the client with SSL_* ciphers this mean something different than TLS_* and may be some servers do not support SSL_*. How can I be sure?
Yes, they are the same. See Java Cryptography Architecture
Standard Algorithm Name Documentation:
Some JSSE cipher suite names were defined before TLSv1.0 was finalized, and were therefore given the SSL_ prefix. The names mentioned in the TLS RFCs prefixed with TLS_ are functionally equivalent to the JSSE cipher suites prefixed with SSL_.