50 votes

Exceptions aléatoires "peer not authenticated" avec Java SSLContextImpl$TLS10Context

J'obtiens des échecs de connexion qui apparaissent de manière aléatoire lorsque je me connecte à un serveur HAProxy en utilisant SSL. J'ai confirmé que ces échecs se produisent avec les versions 1.7.0_21 et 1.7.0_25 du JDK, mais pas avec la version 1.7.0_04 ni avec la version 1.6.0_38.

L'exception est

 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)

Ces échecs se produisent uniquement lors de l'utilisation du contexte SSL TLS et non avec le contexte par défaut. Le code suivant est exécuté dans une boucle un millier de fois et les échecs se produisent avant la fin de la boucle (environ 2% des connexions échouent) :

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();

Cependant, si je crée le contexte SSL de cette manière, je n'ai aucun échec de connexion sur aucune des versions de Java que j'ai mentionnées :

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

La première façon utilise SSLContextImpl$TLS10Context et le dernier utilise SSLContextImpl$DefaultSSLContext . En regardant le code, je ne vois pas de différences qui pourraient provoquer l'exception.

Pourquoi j'obtiendrais les échecs et quels sont les avantages/inconvénients de l'utilisation de la getDefault() appeler ?

Note : Les exceptions ont été vues pour la première fois en utilisant le HttpClient d'Apache (version 4). Ce code est le plus petit sous-ensemble qui reproduit le problème observé avec HttpClient.

Voici l'erreur que je vois lorsque j'ajoute -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

Autre information : les erreurs ne se produisent pas si je désactive la fonction Diffie-Hellman sur le serveur proxy.

1voto

JvR Points 225

A en juger par les symptômes, je suis deviner cela est lié aux navigateurs qui utilisent Faux départ TLS qui est une astuce côté client introduite par Google pour réduire le va-et-vient dans TLS :

Le faux départ est largement contrôlé par le navigateur et fonctionne en réduisant les deux allers-retours de données décrits dans les spécifications SSL officielles à un seul aller-retour. Pour ce faire, il demande au client d'envoyer le message Finished et le premier message ApplicationData en une seule fois, plutôt que de les placer dans deux paquets distincts et de n'envoyer le second qu'après avoir obtenu la confirmation du serveur.

Google a proposé la norme False Start comme norme officielle afin de rendre le SSL plus acceptable pour les sites web qui le trouvent actuellement trop cher à offrir. En abrégeant la poignée de main qui négocie la clé de chiffrement et d'autres variables nécessaires à la protection des données transitant entre l'utilisateur final et le site web, le faux départ devait permettre de réduire la pénalité de performance qui, selon de nombreuses personnes, résulte de l'utilisation du protocole.

De la question pertinente soulevée dans Mozilla Firefox : (c'est moi qui souligne)

Jusqu'à présent, une liste incomplète de produits connus pour avoir des problèmes de compatibilité actuels ou antérieurs avec False Start inclut (AFAICT) : F5, A10, Microsoft TMG, Cisco ASA, ServerIron ADX, ESET, NetNanny, certaines configurations de l'implémentation du serveur SSL de Java .

-3voto

user3595081 Points 26

Javax.net.ssl.SSLPeerUnverifiedException survient uniquement à cause de la sécurité http, vous devez configurer votre connexion en https sinon suivez ce 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());

Utilisez ceci. J'espère que cela vous aidera

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X