Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Node.js] Application client/serveur TLS problème

Application avec communication sécurisée, problème clés de sécurité

Sujet résolu
    13 août 2016 à 15:12:34

    Bonjour à tous, je me tourne vers vous aujourd'hui car je fais face à un problème dont je ne parviens pas à trouver de solution.

    Je souhaite réaliser une application client/server avec node JS par l'élaboration d'un client serveur TCP. Souhaitant que tous les transfèrent de données se face de manière sécurisée, je vais donc utiliser TLS. Je me suis basé sur la doc officiel de Node.js concernant TLS mais en essayant de mettre en application l'exemple de client/seveur qu'il montre je ne parviens pas à le faire fonctionner.

    En effet je bloque sur la partie des clefs de sécurités, je ne parviens pas à créer des pairs de clés auto-signées qui fonctionnent, à chaque fois j'ai une erreur…

    Voici les codes dont je me suis servis :

    Server.js :

    const tls = require('tls');
    const fs = require('fs');
    
    const options = {
      key: fs.readFileSync('server-key.pem'),
      cert: fs.readFileSync('server-cert.pem'),
    
      // This is necessary only if using the client certificate authentication.
      requestCert: true,
    
      // This is necessary only if the client uses the self-signed certificate.
      ca: [ fs.readFileSync('client-cert.pem') ]
    };
    
    const server = tls.createServer(options, (socket) => {
      console.log('server connected',
                  socket.authorized ? 'authorized' : 'unauthorized');
      socket.write('welcome!\n');
      socket.setEncoding('utf8');
      socket.pipe(socket);
    });
    server.listen(8000, () => {
      console.log('server bound');
    });

    Client.js :

    const tls = require('tls');
    const fs = require('fs');
    
    const options = {
      // Necessary only if using the client certificate authentication
      key: fs.readFileSync('client-key.pem'),
      cert: fs.readFileSync('client-cert.pem'),
    
      // Necessary only if the server uses the self-signed certificate
      ca: [ fs.readFileSync('server-cert.pem') ]
    };
    
    const socket = tls.connect(8000, options, () => {
      console.log('client connected',
                  socket.authorized ? 'authorized' : 'unauthorized');
      process.stdin.pipe(socket);
      process.stdin.resume();
    });
    socket.setEncoding('utf8');
    socket.on('data', (data) => {
      console.log(data);
    });
    socket.on('end', () => {
      server.close();
    });

    Voici l'erreur qui m'est retourné lorsque le client ce connecte au serveur :
    events.js:141
          throw er; // Unhandled 'error' event
          ^
    
    Error: Hostname/IP doesn't match certificate's altnames: "Host: localhost. is not cert's CN: CA"
        at Object.checkServerIdentity (tls.js:186:15)
        at TLSSocket.<anonymous> (_tls_wrap.js:1023:29)
        at emitNone (events.js:67:13)
        at TLSSocket.emit (events.js:166:7)
        at TLSSocket._init.ssl.onclienthello.ssl.oncertcb.TLSSocket._finishInit (_tls_wrap.js:582:8)
        at TLSWrap.ssl.onclienthello.ssl.oncertcb.ssl.onnewsession.ssl.onhandshakedone (_tls_wrap.js:424:38)

    Coté serveur voici ce qui est affiché :
    server bound
    server connected authorized

    Quelqu'un aurait-il une solution ? Car là je sèche dessus depuis plusieurs jours…


    Respectueusement,

    Yoratheon

    -
    Edité par Heziode 13 août 2016 à 15:17:12

    • Partager sur Facebook
    • Partager sur Twitter
    Ensemble créons l'avenir !
      25 août 2016 à 17:00:21

      Bonjour,
      Je suis finalement parvenu à résoudre mon problème en me basant sur un poste sur un blogue pour la génération des clés et certificats auto-signés (Using client certs in node.js).
      Voici un script que j'ai créé se basant sur ce qui est dit dans le poste du blogue précédemment cité :

      #!/bin/bash
      if test $# -ne 3
      then
          echo "Wrong number of arguments"
          exit 1
      fi
      
      ROOTPATH="$1"
      FQDN=$2
      PASSWORD=$3
      RSABITS=4096
      
      # make directories to work from
      mkdir -p $ROOTPATH/certs/{server,client,ca,tmp}
      
      PATH_CA=$ROOTPATH/certs/ca
      PATH_SERVER=$ROOTPATH/certs/server
      PATH_CLIENT=$ROOTPATH/certs/client
      PATH_TMP=$ROOTPATH/certs/tmp
      
      ######
      # CA #
      ######
      
      openssl genrsa -des3 -passout pass:$PASSWORD -out $PATH_TMP/ca.key $RSABITS
      
      # Create Authority Certificate
      openssl req -new -x509 -days 365 -key $PATH_TMP/ca.key -out $PATH_CA/ca.crt -passin pass:$PASSWORD -subj "/C=FR/ST=./L=./O=ACME Signing Authority Inc/CN=."
      
      ##########
      # SERVER #
      ##########
      
      # Generate server key
      openssl genrsa -out $PATH_SERVER/server.key $RSABITS
      
      # Generate server cert
      openssl req -new -key $PATH_SERVER/server.key -out $PATH_TMP/server.csr -passout pass:$PASSWORD -subj "/C=FR/ST=./L=./O=ACME Signing Authority Inc/CN=$FQDN"
      
      # Sign server cert with self-signed cert
      openssl x509 -req -days 365 -passin pass:$PASSWORD -in $PATH_TMP/server.csr -CA $PATH_CA/ca.crt -CAkey $PATH_TMP/ca.key -set_serial 01 -out $PATH_SERVER/server.crt
      
      ##########
      # CLIENT #
      ##########
      
      openssl genrsa -out $PATH_CLIENT/client.key $RSABITS
      
      openssl req -new -key $PATH_CLIENT/client.key -out $PATH_TMP/client.csr -passout pass:$PASSWORD -subj "/C=FR/ST=./L=./O=ACME Signing Authority Inc/CN=CLIENT"
      
      openssl x509 -req -days 365 -passin pass:$PASSWORD -in $PATH_TMP/client.csr -CA $PATH_CA/ca.crt -CAkey $PATH_TMP/ca.key -set_serial 01 -out $PATH_CLIENT/client.crt
      
      exit 0
      


      Voici le code du serveur :

      #!/usr/bin/env node
      'use strict';
      
      const tls = require('tls');
      const fs = require('fs');
      const port = 8000;
      
      const options = {
          key: fs.readFileSync('certs/server/server.key'),
          cert: fs.readFileSync('certs/server/server.crt'),
          ca: fs.readFileSync('certs/ca/ca.crt'), // authority chain for the clients
          requestCert: true, // ask for a client cert
          //rejectUnauthorized: false, // act on unauthorized clients at the app level
      };
      
      var server = tls.createServer(options, (socket) => {
        socket.write('welcome!\n');
        socket.setEncoding('utf8');
        socket.pipe(socket);
      })
      
      .on('connection', function(c)
      {
      	console.log('insecure connection');
      })
      
      .on('secureConnection', function (c)
      {
      	// c.authorized will be true if the client cert presented validates with our CA
      	console.log('secure connection; client authorized: ', c.authorized);
      })
      
      .listen(port, function() {
      	console.log('server listening on port ' + port + '\n');
      });
      


      Et le code du client :

      #!/usr/bin/env node
      'use strict';
      
      const port = 8000;
      const hostname = 'localhost';
      
      const tls = require('tls');
      var fs = require('fs');
      
      const options = {
        host: hostname,
        port: port,
      
        // Necessary only if using the client certificate authentication
        key: fs.readFileSync('certs/client/client.key'),
        cert: fs.readFileSync('certs/client/client.crt'),
      
        // Necessary only if the server uses the self-signed certificate
        ca: fs.readFileSync('certs/ca/ca.crt')
      };
      
      var socket = tls.connect(options, () => {
        console.log('client connected',
                    socket.authorized ? 'authorized' : 'unauthorized');
        process.stdin.pipe(socket);
        process.stdin.resume();
      
        socket.end();
      })
      
      .setEncoding('utf8')
      
      .on('data', (data) => {
        console.log(data);
      })
      
      .on('end', () => {
        console.log("End connection");
      });
      


      Lors de l'exécution du serveur et d'un client, la trace côté serveur est la suivante :

      server listening on port 8000
      
      insecure connection
      secure connection; client authorized:  true
      


      Et côté client on obtient :

      client connected authorized
      End connection
      


      Tout fonctionne parfaitement bien, je parviens à avoir une connexion sécurisée entre un client et un serveur avec un certificat auto-signé.
      J'ai créé un projet GitHub pour tout centraliser : Simble TLS Client/Server with Node.js

      • Partager sur Facebook
      • Partager sur Twitter
      Ensemble créons l'avenir !

      [Node.js] Application client/serveur TLS problème

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
      • Editeur
      • Markdown