Random "peer not authenticated" exceptions with Java SSLContextImpl$TLS10Context

JavaSslHaproxySslsocketfactory

Java Problem Overview


I get connection failures that appear randomly when connecting to an HAProxy server using SSL. I have confirmed that these failures happen on JDK versions 1.7.0_21 and 1.7.0_25 but not with 1.7.0_04 or with 1.6.0_38.

The exception is

 Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
	at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)
	at SSLTest2.main(SSLTest2.java:52)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

These failures only happen when using the TLS SSL context and not with the default context. The following code is run in a loop a thousand times and failures happen before the loop completes (about 2% of the connections fail):

SSLContext sslcontext = SSLContext.getInstance("TLS");   
sslcontext.init(null, null, null);
SSLSocketFactory factory = sslcontext.getSocketFactory(); 
SSLSocket socket = (SSLSocket)factory.createSocket("myserver", 443);

//socket.startHandshake();
SSLSession session = socket.getSession();
session.getPeerCertificates();
socket.close();

If, however, I create the SSL context this way I have no connections failures on any of the Java versions I mentioned:

SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();

The first way uses SSLContextImpl$TLS10Context and the later uses SSLContextImpl$DefaultSSLContext. Looking at the code, I don't see any differences that would cause the exception to occur.

Why would I be getting the failures and what are the advantages/disadvantages of using the getDefault() call?

Note: The exceptions were first seen using the Apache HttpClient (version 4). This code is the smallest subset that reproduces the problem seen with HttpClient.

Here's the error I see when adding -Djavax.net.debug=ssl:

main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, bad_record_mac
%% Invalidated:  [Session-101, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLException: Received fatal alert:   bad_record_mac
main, IOException in getSession():  javax.net.ssl.SSLException: Received fatal alert: bad_record_mac

Another piece of information is that the errors do not occur if I turn off Diffie-Hellman on the proxy server.

Java Solutions


Solution 1 - Java

Judging by the symptoms, I'm guessing this is related to browsers using [TLS false start](https://datatracker.ietf.org/doc/html/draft-bmoeller-tls-falsestart-00 "IETF draft"), which is a client-side trick Google introduced to [reduce the back-and-forth in TLS](http://arstechnica.com/business/2012/04/google-abandons-noble-experiment-to-make-ssl-less-painful/ "Ars Technica"):

> False Start is largely controlled by the browser and works by reducing the two round-trip passes of data described in official SSL specifications to a single round-trip pass. It did this by instructing the client to send Finished and first ApplicationData messages in a single dispatch rather than putting them in two distinct packages and sending the second only after getting confirmation from the server. > > Google proposed False Start as an official standard to make SSL more palatable to websites that currently find it too expensive to offer. By abbreviating the handshake that negotiates the encryption key and other variables needed to protect data passing between the end user and website, False Start was intended to lower the performance penalty that many say comes from using the protocol.

From the relevant issue raised in Mozilla Firefox: (emphasis mine)

> So far, an incomplete list of products that are known to have current or previous compatibility problems with False Start include (AFAICT): F5, A10, Microsoft TMG, Cisco ASA, ServerIron ADX, ESET, NetNanny, some configurations of Java's SSL server implementation.

Solution 2 - Java

javax.net.ssl.SSLPeerUnverifiedException arise only because of http security you have to configure your connection as https else follow this code..

            SSLContext ctx = SSLContext.getInstance("TLS");
	ctx.init(null, new TrustManager[]{tm}, null);
	SSLSocketFactory ssf = new SSLSocketFactory(ctx);
	ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
	ClientConnectionManager ccm = client.getConnectionManager();
	SchemeRegistry sr = ccm.getSchemeRegistry();
	sr.register(new Scheme("https", ssf, 443));
	return new DefaultHttpClient(ccm, client.getParams());

use this. i hope it will help you

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2687486View Question on Stackoverflow
Solution 1 - JavaJvRView Answer on Stackoverflow
Solution 2 - Javauser3595081View Answer on Stackoverflow