This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0
My J2SE app uses HttpsUrlConnection to access a secure location. It used to work just fine until I updated my JRE to 1.7. Now I get the "Remote host closed connection during handshake" SSLException. After running the app using -Djavax.net.debug=ssl:handshake, both under JRE 1.6 and JRE 1.7, my impression is that under 1.7 the cached client session fails to resume.
UPDATE:
I have come to understand that under JRE 1.6 my client app uses SSLv2Hello encapsulation. However it does not do that under JRE 1.7, which is most probably what causes the exception. My question is now this: how do I enable SSLv2Hello encapsulation for clients running on JRE 1.7?
UPDATE #2:
SSLv2Hello accomplished on JRE 7 via System.setProperty("https.protocols", "TLSv1,SSLv2Hello"). However this didn't make the handshake exception go away. Turns out that the true reason for the exception is the cipher suite. On JRE 6 the server picks SSL_RSA_WITH_RC4_128_MD5 out of the client's options, while on JRE 7 it always goes with TLS_DHE_RSA_WITH_AES_128_CBC_SHA. For some reason the server can't resume cached sessions using TLS_DHE_RSA_WITH_AES_128_CBC_SHA. Problem patched using System.setProperty("https.cipherSuites", suggestedCipherSuites) where suggestedCipherSuites always starts with SSL_RSA_WITH_RC4_128_MD5. Any downsides with this approach?
UPDATE #3:
The SNI extension of the client is what bothers the server. See "Server Name Indication (SNI) for JSSE client" at http://docs.oracle.com/javase/7/docs/technotes/guides/security/enhancements7.html
In the end it turns out that the problem was related to the SNI extension in the JSSE client 1.7.
The solution is to disable sending SNI records, before any access to an https location:
System.setProperty ("jsse.enableSNIExtension", "false");
Many thanks to eckes for his solution (see SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0).
Related
I'm currently migrating some server software from Java 8 to Java 11. Everything works fine except for the fact that TLS connections are refused when my server runs on Java 11 (and only 11). I.e., everything works when running on up to and including Java 10. As soon as I switch to Java 11 (with absolutely no code changes inbetween, of course) I get a TLS decrypt error. My application works fine otherwise when I disable SSL/TLS or when I use IE/Edge to connect to my server (via TLS). When using Chrome 70 or Firefox 62 I get ERR_SSL_PROTOCOL_ERROR or SEC_ERROR_BAD_SIGNATURE, respectively.
I tried to analyze this using WireShark (see my dump). My conclusion is that Java 11 and Chrome/Firefox negotiate a bad cipher suite (rsa_pss_rsae_sha256), which somehow doesn't work with Java 11. Java 8 and IE/Edge seem to negotiate a different cipher suite (rsa_pkcs1_sha256), which works.
Does someone know how to fix this problem or at least work around it for the moment (other than disabling SSL/TLS or using IE/Edge, of course)? Thanks in advance.
This is likely to be a compatibility failure with the new PSS algorithms in TLS 1.3. You can read a good explanation for the reasoning behind the introduction of PSS here.
Until it's fixed you can prevent your server from negotiating TLS 1.3 by editing lib/security/java.security and adding TLSv1.3 to the jdk.tls.disabledAlgorithms property.
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.
My java version is 1.6 and connect to a server over ssl using axis 2 stub; all used to work fine. It seems like they did some upgrade (apache2.4) and the ssl handshake doesn't happen anymore. I receive javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake error. Just for testing purpose, I locally installed jdk 8 and tested it works fine. Is there any way to make this work using jdk1.6? It is not possible to upgrade jdk now.
It is hard to tell without more details but I guess that the server either requires a TLS version unsupported by JDK 6 (e.g. TLS 1.1 or TLS 1.2) or uses ciphers which are not supported by JDK 6 yet. Another option might be that the server needs SNI (server name indication) which is not supported by JDK 6. If the problem is any of these things you are unfortunately out of luck with JDK 6.
I suggest you check with SSLLabs to get more details about the problem. They show also compatibility information regarding various JDK versions.
You could try using a 3rd party JCE provider, Bouncy Castle comes into mind:
https://www.bouncycastle.org
I've tried using the params element:
<param name='java_arguments' value='-Djsse.enableSNIExtension=false'>
Tried from code also with
System.setProperty("jsse.enableSNIExtension", "false");
Seen these threads but none of the suggested solutions worked:
SSLException during handshake while resuming cached session
SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0
But what I really want is to generally disable SNI even before the Java machine starts downloading the applet code.
(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)