2 votes

Java 11 donne le message Unsupported handshake : server_hello_done sur une connexion HTTPS avec certificat client

Nous avons une applet Java (fonctionnant sous tomcat) qui fait des appels à des tiers. L'un d'eux utilise un certificat client pour s'authentifier. Cela fonctionnait sous Java 8, mais nous avons récemment mis à niveau le système vers Java 11 et cela ne fonctionne plus. L'erreur est la suivante

Message de poignée de main non pris en charge : server_hello_done

(ce qui est étrange, puisque je pensais serveur_hello_done était une partie valide de la poignée de main)

Nous avons eu un problème avec le keystore java après la mise à jour. Le service a échoué en disant que ce n'était pas un flux PCKS12 valide. L'affichage du contenu avec keytool a fonctionné, mais avec un avertissement

Attention :

Le keystore JKS utilise un format propriétaire. Il est recommandé de migrer vers PKCS12 qui est un format standard de l'industrie en utilisant "keytool -importkeystore -srckeystore /path/to/keystore -destkeystore /path/to/keystore -deststoretype pkcs12".

Nous avons utilisé la commande suggérée et il ouvre maintenant le keystore OK, mais nous obtenons l'erreur de poignée de main.

La trace de la pile vers notre code est :

Unsupported handshake message: server_hello_done
javax.net.ssl.SSLProtocolException: Unsupported handshake message: server_hello_done
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:126)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:446)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)

Nous utilisons le client http d'Apache (org.apache.http.impl.client.CloseableHttpClient). La ligne suivante dans la trace de la pile est simplement un appel à client.execute() dans notre code.

Il comprend également

Caused by: java.lang.UnsupportedOperationException: Not supported yet.
        at java.base/sun.security.ssl.HandshakeHash$CloneableHash.archived(HandshakeHash.java:616)
        at java.base/sun.security.ssl.HandshakeHash$T12HandshakeHash.archived(HandshakeHash.java:546)
        at java.base/sun.security.ssl.HandshakeHash.archived(HandshakeHash.java:188)
        at java.base/sun.security.ssl.CertificateVerify$T12CertificateVerifyMessage.<init>(CertificateVerify.java:581)
        at java.base/sun.security.ssl.CertificateVerify$T12CertificateVerifyProducer.produce(CertificateVerify.java:740)
        at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
        at java.base/sun.security.ssl.ServerHelloDone$ServerHelloDoneConsumer.consume(ServerHelloDone.java:173)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)

La tierce partie confirme qu'elle ne voit "aucun chiffrement partagé" dans ses journaux, mais affirme qu'elle prend en charge un large éventail de chiffrement ( " SSL3, TLS 1.0, 1.1, ou 1.2. Les codes sont marqués comme HIGH:MEDIUM:!aNULL:!eNULL:@STRENGTH". ). Je pense que nous supportons la plupart de ces éléments, sauf SSL3. Pour autant que je sache, nous avons des paramètres par défaut dans java 11 pour cela. J'ai essayé d'activer SSLv3 temporairement, mais je n'ai pas pu me connecter (bien que depuis que j'ai essayé, je ne peux plus me connecter du tout à partir de cette machine (la connexion est interrompue) même après avoir fait marche arrière, donc cela ne veut pas dire grand-chose - j'ai essayé à partir d'une machine de test et non de production).

Des idées ? Suis-je sur la bonne voie pour continuer à chercher des chiffres ou y a-t-il quelque chose qui m'échappe ?

1voto

Adam Points 2623

Il s'est avéré que tout ce qui était nécessaire était un redémarrage de tomcat ! Mais, comme il s'agissait d'un serveur de production faisant beaucoup de choses, je ne voulais pas faire cela comme première étape. Mais cela a réglé le problème.

Ma meilleure idée de ce qui s'est passé était :

  • Le keystore n'avait pas le bon format pour la version de java mise à jour.
  • La tentative d'utiliser le keystore invalide a mis tomcat/java dans un état bizarre.
  • La mise à jour du keystore a permis à Java de l'utiliser, mais il était toujours dans un état bizarre.
  • Le redémarrage l'a réparé.

Ce qui est vraiment bizarre, c'est qu'il se comporte de la même manière même avec une IP différente (j'ai essayé avec le serveur de test du tiers) et avec un keystore différent (j'ai fait une copie du keystore mis à jour et j'ai fait une requête qui l'utilisait). L'erreur initiale était "Stream n'est pas un keystore PKCS12 valide" et la trace de la pile est revenue à la ligne qui a essayé d'ouvrir le keystore dans notre code. Après avoir corrigé le format du keystore, nous sommes allés plus loin dans notre code (la trace de la pile est maintenant retournée à la ligne suivante client.execute() ) mais il a échoué avec le message _Unsupported handshake message : server_hello_done_.

J'ai créé une copie de l'ensemble du dossier tomcat (y compris jre), avec initialement le keystore original (invalide), je l'ai modifié pour qu'il fonctionne sur un autre port et je l'ai démarré à côté de ce tomcat sur la même machine. Il s'est comporté de la même manière mais a fonctionné après un redémarrage. Ce matin, j'ai redémarré le service principal et maintenant il fonctionne.

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