Exemple Java de SSL bidirectionnel

Quel est un exemple de SSL Java bidirectionnel ?

Secure Sockets Layer (SSL) est une technologie de sécurité standard permettant d‘établir une liaison cryptée entre un serveur et un client. Elle est largement utilisée lors de transactions impliquant des informations sensibles ou personnelles telles que les numéros de carte de crédit, les identifiants de connexion et les numéros de sécurité sociale. Le cryptage peut être appliqué dans un sens ou dans les deux sens - unidirectionnel ou bidirectionnel. Dans le cas du SSL unidirectionnel, le client confirme l‘identité du serveur tandis que l‘identité du client reste anonyme. Dans le cas du SSL bidirectionnel, également appelé SSL mutuel, le client confirme l‘identité du serveur et le serveur confirme l‘identité du client.

Le protocole SSL bidirectionnel commence par un "bonjour" du client au serveur. Le serveur répond par un "hello" accompagné de son certificat public. Le client vérifie le certificat reçu à l‘aide des certificats stockés dans son TrustStore. Si la validation du certificat du serveur est réussie, le client présentera des réserves de certificats dans ses KeyStores. Le serveur valide le certificat reçu à l‘aide des TrustStores du serveur. Le serveur déchiffre les clés de session à l‘aide de la clé privée du serveur afin d‘établir une connexion sécurisée.

Java utilise Java Keystore (JKS), une base de données protégée par un mot de passe pour les certificats et les clés. Chaque entrée doit être identifiée par un alias unique. Keystore fournit des informations d‘identification.

Java utilise également le Truststore qui se trouve dans $JAVA_HOME/lb/security/cacerts. Il stocke les entrées des autorités de certification (CA) de confiance et les certificats auto-signés des tiers de confiance. Le Truststore vérifie l‘identité des serveurs.

Java fournit également keytool, un outil de ligne de commande permettant de gérer la base de données de clés et la base de données de confiance.

Vous pouvez exécuter TrustStore à l‘aide du code suivant. Remplacez $CERT_ALIAS et $CERT_PASSWORD par votre alias et votre mot de passe, respectivement.

1) Si nous ne disposons pas du certificat du serveur, nous utilisons openssl pour le récupérer.

echo -n | openssl s_client -connect SERVERDOMAIN:PORT -servername SERVERDOMAIN

-key myclient.key -cert myclient.cert.pem

| sed -ne ‘/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p‘

| tee "server.crt"

2) Créer le Truststore à partir du certificat du serveur

keytool -import -alias $CERT_ALIAS -file server.crt -keystore truststore.jks -deststorepass $CERT_PASSWORD

Ensuite, générez l‘IdentityStore. Remplacez $CERT_ALIAS et $CERT_PASSWORD par votre alias et votre mot de passe, respectivement.

1) Concaténer tous les certificats dans un fichier PEM

cat intermediate.cert.pem myclient.cert.pem myclient.key > full-chain.keycert.pem

2) Générer le keystore PKCS12 avec l‘alias de l‘url du serveur

openssl pkcs12 -export -in full-chain.keycert.pem

-out full-chain.keycert.p12

-mot de passe env:$CERT_MOT DE PASSE

-nom $CERT_ALIAS

-noiter -nomaciter  

3) Convertir .p12 en .jks

keytool -importkeystore -srckeystore full-chain.keycert.p12

-srcstoretype pkcs12 -srcstorecalias $CERT_ALIAS -srcstorepass $CERT_MOT DE PASSE

-destkeystore identity.jks -deststoretype jks

-deststorepass $CERT_PASSWORD -destalias $CERT_ALIAS

Ce code Java charge Keystore et Truststore dans un contexte SSL personnalisé, crée une SSLConnectionSocketFactory, puis la lie à un HttpClient.

public class SSLMutualAuthTest {

  publicSSLMutualAuthTest() {

    // TODO Auto-generated constructor stub

  }

  public static void main (String[] args) {

    System.out.println("MagicDude4Eva 2-way / mutual SSL-authentication test") ;

    org.apache.log4j.BasicConfigurator.configure() ;

    Logger.getRootLogger().setLevel(Level.INFO) ;

    try {

      Chaîne CERT_ALIAS = "monalias", CERT_PASSWORD = "monmotdepasse" ;

      KeyStore identityKeyStore = KeyStore.getInstance("jks") ;

      FileInputStream identityKeyStoreFile = new FileInputStream(new File("identity.jks")) ;

      identityKeyStore.load(identityKeyStoreFile, CERT_PASSWORD.toCharArray()) ;

      KeyStore trustKeyStore = KeyStore.getInstance("jks") ;

      FileInputStream trustKeyStoreFile = new FileInputStream(new File("truststore.jks")) ;

      trustKeyStore.load(trustKeyStoreFile, CERT_PASSWORD.toCharArray()) ;

      SSLContext sslContext = SSLContexts.custom()

          // load identity keystore

          .loadKeyMaterial(identityKeyStore, CERT_PASSWORD.toCharArray(), new PrivateKeyStrategy() {

@Override

              public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) {

                  return CERT_ALIAS ;

              }

          })

          // load trust keystore

          .loadTrustMaterial(trustKeyStore, null)

          .build() ;

      SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,

          new String[]{"TLSv1.2", "TLSv1.1"},

          nul,

          SSLConnectionSocketFactory.getDefaultHostnameVerifier()) ;

      CloseableHttpClient client = HttpClients.custom()

          .setSSLSocketFactory(sslConnectionSocketFactory)

          .build() ;

      // Call a SSL-endpoint

      callEndPoint (client, "https://secure.server.com/endpoint", 

          nouveau JSONObject()

          .put("param1", "value1")

          .put("param2", "value2")

          ) ;

    } catch (Exception ex) {

      System.out.println("Boom, we failed : " + ex) ;

      ex.printStackTrace() ;

    }

  }

  private static void callEndPoint (CloseableHttpClient aHTTPClient, String aEndPointURL, JSONObject aPostParams) {

    try {

      System.out.println("Calling URL : " + aEndPointURL) ;

      HttpPost post = new HttpPost(aEndPointURL) ;

      post.setHeader("Accept", "application/json") ;

      post.setHeader("Content-type", "application/json") ;

      StringEntity entity = new StringEntity(aPostParams.toString()) ;

      post.setEntity(entity) ;

      System.out.println("**POST** request Url : " + post.getURI()) ;

      System.out.println("Paramètres : " + aPostParams) ;

      HttpResponse response = aHTTPClient.execute(post) ;

      int responseCode = response.getStatusLine().getStatusCode() ;

      System.out.println("Code de réponse : " + responseCode) ;

      System.out.println("Contenu:-n") ;

      BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent())) ;

      String line = "" ;

      while ((line = rd.readLine()) != null) {

          System.out.println(ligne) ;

      }

    } catch (Exception ex) {

      System.out.println("Boom, we failed : " + ex) ;

      ex.printStackTrace() ;

    }

  }  

}

Bien sûr, il existe une solution beaucoup plus simple pour mettre en place une authentification SSL bidirectionnelle. SnapLogic dispose de plusieurs snaps qui prennent en charge la validation et l‘authentification des certificats SSL, y compris SOAP, Splunk et REST.

Connectez vos applications en quelques minutes et non en quelques jours. Réservez une démonstration avec SnapLogic

Autres contenus susceptibles de vous intéresser