Home Knowledge base Knowledge Base - Languages Knowledge Base - Languages - Java SSL Handshake Failure, lors de l'appel d'un Web Service en HTTPS
SSL Handshake Failure, lors de l'appel d'un Web Service en HTTPS PDF Print E-mail
Written by LECLERE   
Thursday, 04 April 2013 16:53

Contexte :

Lorsque l'on tente de faire un appel à un Web Service en HTTPS depuis une JVM Java, on rencontre souvent le message suivant :

Received fatal alert: handshake_failure at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert( SSLSocketImpl.java:1657)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord( SSLSocketImpl.java:932)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake( SSLSocketImpl.java:1096)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake( SSLSocketImpl.java:1123)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake( SSLSocketImpl.java:1107)
at posslu.Main.main(Main.java:22)
Java Result: 1

La première cause est un problème de configuration de la chaîne de validation du Certificat SSL. Je vais vous expliquer cela dans la suite ...

Rappel : Différence entre HTTP et HTTPS

HTTP signifie « Hypertext Transport Protocol », ce qui traduit juste la façon dont deux systèmes communiquent sur le Web (Un navigateur - Internet Explorer, Firefox, Chrome, ... - qui est utilisé pour parcourir les pages exposées par un serveur Web - Internet Information Server, Tomcat, WebSphere, ...).

L’important, c'est la lettre « S » qui fait toute la différence entre HTTP et HTTPS. Le « S » (grande surprise) est synonyme de « Secure (i.e. sécurité) » (par exemple : https://intranet.softcomputing.com).

En conséquence :


  • Si le protocole est non sécurisé (HTTP), cela signifie que les données sont échangées en clair entre le serveur et le client. Donc, si vous remplissez un formulaire Web et que vous le soumettez, toutes les informations sont envoyées telles quelles vers le serveur. Et donc, si quelqu'un espionne le réseau entre le client et le serveur (plusieurs outils existent tel tcpdump), il peut voir en clair toutes les informations saisies dans le formulaire. 
  • Si, par contre, le protocole est sécurisé (HTTPS), le client et le serveur conviennent au préalable d'une clé commune pour chiffrer toutes les informations qui vont être échangées entre le client et le serveur. Ainsi, le même espion que précédemment verra toujours passer les paquets réseau, mais cette fois-ci, les informations échangées ne seront plus directement lisibles. Et plus la clé de chiffrement est forte, plus il sera difficile de déchiffrer les paquets. 

Comment activer le protocole HTTPS Sécurisé ?

La mise en oeuvre du protocole HTTPS se fait sur le serveur Web :

  • En activant dans la configuration du serveur les connecteurs adéquats
    Par exemple, pour le serveur d'application Tomcat, dans le fichier server.xml, on ajoutera la section suivante : 
    • <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
      maxThreads="150" scheme="https" secure="true"  
      clientAuth="false" sslProtocol="TLS" >
  • En Ajoutant un certificat SSL Web sur le serveur Web
    Par exemple, pour le serveur Apache, dans le fichier httpd.conf, on ajoutera les éléments suivants : 
    • SSLEngine on 
    • SSLCertificateFile /path/to/www.exemple.com.cert 
    • SSLCertificateKeyFile /path/to/www.exemple.com.key 

Comment opère la chaîne de certification SSL ?

Un Certificat Electronique est un ensemble de données contenues dans un fichier et précisant :

  • Au moins une clé publique
  • Des information d'identification du détenteur du certificat (exemple : nom, localisation, adresse email) ; 
  • Des informations de validité (date d'expiration, ...) ; 
  • Au moins une signature de l'autorité qui certifie l'exactitude des informations contenues dans le certificat. 

Sur ce principe, quand une communication est initiée entre le client Web et le serveur Web, le serveur Web présente au client Web le Certificat Electronique qui lui est attaché. Le client Web commence par vérifier auprès de l'autorité de certification déclarée dans le certificat lui même que celui-ci est bien valide (délivré par cette autorité , pas expiré ni révoqué), et si tel est le cas, en extrait la clé publique pour pouvoir chiffrer le canal de communication.

Là ou ça commence à se compliquer, c'est qu'il n'y à pas qu'une seule autorité de certification. On peut acheter des certificats SSL chez plusieurs fournisseurs (Verisign, RapidSSL, ...). C'est la raison pour laquelle, chaque fournisseur de certificat SSL, qui fait office d'autorité locale de certification pour ses propres certificats SSL doit être déclaré auprès d'une autorité de certification supérieure qui va garantir que le fournisseur en question est autorisé à délivrer des certificats SSL.

Donc au moment de la validation, le client Web remonte toute la chaîne : de l'autorité de certification locale (celle du fournisseur du certificat) jusqu'à l'autorité de certification racine.

En conséquence :

  • Le client Web doit donc connaitre toute la chaîne pour pouvoir réaliser cette opération. 
  • S'il s'agit du Navigateur Web (Internet Explorer, ...) ces éléments sont enregistrés dans la magasin des certificats. 


Et qu'en est-il de JVM Java ?

Pour la JVM Java, le principe est le même que pour le navigateur, à savoir, les éléments de configurations des certificats (Certificat Web, Autorité de Certification locale ou racine) sont stockés dans le contexte de la JVM dans un KeyStore.

Par défaut, lors de l'installation de la JVM Java, un ensemble de KeyStore sont installés :

  • Par exemple : 
    • Si la JVM Java est installée dans le dossier JAVA_HOME 
    • Les éléments de la KeyStore sont disponibles dans le dossier %JAVA_HOME%\jre\lib\security 
  • On peut alors consulter le détail des autorités de certification installées en natif dans la JVM Java avec la commande :
    • %JAVA_HOME%\bin\keytool -list -keystore %JAVA_HOME%\jre\lib\cacerts 
  • Qui produit une sortie du type : 
    • Type de fichier de clés :
      JKS Fournisseur de fichier de clés : SUN Votre fichier de clés d'accès contient 79 entrées
       digicertassuredidrootca, 16 avr. 2008, trustedCertEntry, Empreinte du certificat (SHA1) : 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43
      trustcenterclass2caii, 29 avr. 2008, trustedCertEntry, Empreinte du certificat (SHA1) : AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E 


Pour ajouter une autorité dans le KeyStore de la JVM Java ?

Il arrive parfois qu'une autorité de certification ne soit pas connue de la JVM Java (nouveau fournisseur de certificat SSL, ancienne version de la JVM Java), il faudra alors ajouter manuellement les éléments de l'autorité de certification du fournisseur dans la KeyStore de la JVM Java.

  • Cette opération se fait avec l'utilitaire keytool, et la commande suivante :
    • %JAVA_HOME%\bin\keytool -import -alias <alias_authority> -keystore %JAVA_HOME%\jre\lib\security\cacerts -storepass <password> -file <path_to_authority_certificate_file>
  • En précisant les éléments suivants :
    • <alias_authority> : le nom sous lequel l'autorité de certification sera identifiée dans le KeyStore ;
    • <password> : Le mot de passe pour ouvrir le KeryStore ;
    • <path_to_authority_certificate_file> : Le chemin vers le fichier Certificat SSL de l'autorité de certification récupéré auprès du fournisseur.


    Cas des Certificats auto-signés ?

    Pour les besoins du développement ou du test, il arrive que l'on doivent créer un certificat SSL sans pouvoir passer par un fournisseur agrée. On utilise à lors un Certificat SSL auto-signé, c'est à dire qu'il fait office de certificat SSL mais aussi d'autorité de certification.

    Ce type de certificat SSL n'est pas utilisable sur des environnements de production car rien ne permet de valider l'origine du certificat et les différents clients du service émettent un Warning lors de l'utilisation d'un tel certificat (Internet Explorer, Chrome, ...).

    Bien entendu, la JVM Java déclenche elle aussi une erreur si l'on tente d'utiliser ce type de certificat, car la chaîne de confiance entre le client et le serveur n'est pas assurée.

    Pour palier ce problème, il faut appliquer la même méthode que précédemment, mais cette fois on ne peut pas se baser sur le certificat de l'autorité de certification (puisqu'elle n'existe pas), et on va utiliser le certificat SSL auto-signé lui-même,

    • et la commande sera : 
      •  %JAVA_HOME%\bin\keytool -import -v -trustcacerts -alias <alias_authority> -keystore %JAVA_HOME%\jre\lib\security\cacerts -storepass <password> -file <path_to_authority_certificate_file>
    • En précisant les éléments suivants :
      •  <alias_authority> : le nom sous lequel l'autorité de certification sera identifiée dans le KeyStore ;
      • <password> : Le mot de passe pour ouvrir le KeryStore ;
      • <path_to_authority_certificate_file> : Le chemin vers le fichier Certificat SSL de l'autorité de certification récupéré auprès du fournisseur.

    Pour aller plus loin :


    Last Updated on Thursday, 04 April 2013 17:40
     
    Copyright © 2024 Tech'IT. All Rights Reserved.
    Joomla! is Free Software released under the GNU/GPL License.