Sécurisation d'un chat réseau Qt avec QSslSocket

Formation

En Ligne

Prix sur demande

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Description

  • Typologie

    Formation

  • Méthodologie

    En ligne

Grâce à cette formation vous pourrez acquérir les connaissances nécessaires qui vous permettrons d’ajouter des compétences à votre profil et obtenir de solides aptitude qui vous offriront de nombreuses opportunités professionnelles.

Questions / Réponses

Ajoutez votre question

Nos conseillers et autres utilisateurs pourront vous répondre

À qui souhaitez-vous addresser votre question?

Saisissez vos coordonnées pour recevoir une réponse

Nous ne publierons que votre nom et votre question

Les Avis

Les matières

  • Chat
  • Mise en réseau
  • Réseau

Le programme

Introduction du cours

Bonjour à tous ! :)
Aujourd'hui, toutes les applications de chat connues sont cryptées. C'est pourquoi j'ai cherché pendant de nombreuses heures comment crypter le système du chat issue de ce tutoriel. Sans cryptage, n'importe quelle personne avec un minimum de compétences informatiques est capable d'espionner vos conversations les plus intimes.

Je vous mets ici le résultat de mes recherches, je tiens à préciser que je suis débutant et qu'il peut y avoir des erreurs. :-°

J'ai choisi de me servir de Qt, en utilisant QSslSocket qui implémente le protocole SSL dans un QTcpSocket. Ceci n'est pas une solution exhaustive, il a de nombreuses façons de crypter une communication en C++.

SSL ? C'est qui celui-là ?

SSL est un protocole de sécurisation des échanges sur internet. Il est notamment utilisé dans les sites en « https ». Il sert à la fois à crypter les données transmises et à vérifier l’identité des acteurs du dialogue (clients et serveur).

SSL utilise le principe de la cryptographie asymétrique.
Il repose sur le principe d'une clé publique et d'une clé privée par acteur. La clé publique sert à crypter et la clé privée sert à décrypter.
La clé privée doit absolument rester PRIVÉE, c'est pour cela qu'elle est généralement stockée dans un fichier crypté par une passphrase.

A l'établissement de la connexion, les différents acteurs s'échangent leurs clés publiques, on parle de transaction :

Ainsi le serveur possède la clé publique du client1 et du client2, le client1 et le client2 possèdent celle du serveur.

Lorsque le client1 va vouloir dialoguer avec le serveur (exemple : « Salut tu vas bien ? »), il va crypter le message avec la clé publique du serveur.
Il n'y a que le serveur qui est capable de décrypter le message car il est le seul à posséder la clé privée.

L'échange serveur vers client se fera de la même façon :

Un problème de sécurité reste cependant présent :(
Vous ne le voyez pas ? :-°
Comment peut-on être sûr que l'on utilise la bonne clé publique pour crypter ? En effet un « méchant pirate » peut s'interposer entre le client et le serveur en injectant sa clé publique au client. Il sera donc capable de déchiffrer tout ce qui vient du client.

Pour résoudre ce problème de sécurité, on a crée des autorités de certification qui signent les clés publiques. Cette signature permet de certifier l'origine de la clé publique. Une clé publique signée s'appelle un certificat.

Cette page n'a pas pour but de vous former entièrement sur SSL, elle pose juste les bases nécessaires à la compréhension du reste du tutoriel. Pour plus d'informations, vous pouvez lire la bible du SSL en français.

Nous allons donc utiliser SSL pour crypter les connexions entre notre serveur de chat et les clients. Il faut donc générer des clés pour le serveur et tous les clients.

Pour obtenir plus d'information sur le cryptage, je vous invite à lire le tutoriel de L01c et Yruama.

Où trouver les clés ?

Les clés privées et publiques ne se trouvent pas comme ça, il faut les générer !

Installation d'OpenSSL

J'ai choisi d'utiliser OpenSSL pour créer mes clés.

Installation pour Linux

Avec les sources :
Vous devez télécharger l'archive la plus récente sur le site officiel, c'est à dire ici. Ensuite il vous suffit d'effectuer les commandes suivantes

./Configure linux-elf --prefix=/usr --openssldir=/usr/openssl make su make install exit

Pour Debian :
Si vous utilisez Debian, l'installation est encore plus simple :
Si vous utilisez Debian, l'installation est encore plus simple :

apt-get install openssl Installation pour Windows

Pour installer OpenSSL pour Windows, il vous suffit de télécharger un des installateur suivant et de réaliser l'installation.

Windows 32 bits

Windows 64 bits

A la fin de l'installation l'exécutable openSSL.exe se trouve dans " C:\OpenSSL-Win32\bin\ " ou " C:\OpenSSL-Win64\bin\ "

Génération des clés

Nous allons tout d'abord générer la clé et le certificat de notre CA (autorité de certification), j'ai choisi de faire un certificat autosigné dans le cadre du tutoriel, pour une mise en production, il faudra prévoir l'achat d'un certificat trust et la création de clé minimum 1024 bits (man openssl :p je vais pas tout faire à votre place :D).

On génère la clé privée de notre autorité

Cette clé nous permettra de signer tous les certificat émis par notre CA ! L'option des3 permet d'ajouter une passphrase pour crypter notre clé.

openssl genrsa -des3 -out ca/ca.key

Résultat :

Generating RSA private key, 512 bit long modulus ...............++++++++++++ ...............++++++++++++ e is 65537 (0x10001) Enter pass phrase for ca.key: Verifying - Enter pass phrase for ca.key:

Notez bien cette passphrase, elle vous sera utile pour tout le reste du tuto (voir de votre vie) si vous la perdez, il vous faudra tout recommencer !

Une clé privée non cryptée ressemble à ça:

-----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQDQG9wvnuLC4aqzaJCAWGA1AxFzg00hjPObhq1mukzsGyuuWBFG vj/k9vFNYX55DHctb/4cXtsZRWWvgcjtYnCVwRu+DAjFsk//kOMfhplmiv9xQ+ZL 8w/Xrnm8JWdSS+S4LCMnsuIiQtLbhMrQnUV02hAtbIZiSM3k6OjShEZhDQIDAQAB AoGAHi0cBW+1k+qjFPbBlUq7UJSMUEKmyYmlvVSPCklTZB0gfVxZzPdDTpEcNks/ yo+rLFSD9Vsvy/9LGmLoXruadWlK67PCUnpM5/oRRGgy8t73YKrxflAU5Gtymjvc ZCf0CAs6wBft3yLU31Qc4WqVM2vTyUH76jebVhxEw8k63OUCQQD/1OmAXV+TxBPG ZTPFbzUeAE5rQqqOW4aoMNvM61Yn/19h6SzY2MfSQvF1BNns/efCRrqOMeyvPWUG g1okfogTAkEA0D7pDf/D2Yu5msbOAGF4QBU1erLzpi/s6Rv6VEPYCGnHQlo3jbg9 FZbjHJ4UcYyYaA8jIrkY+FIJM88YlGbWXwJBAILEdvJ5R/CFCkKf2j2yIWmLaIol En8fw43XI5L0PB7Hxx6KDLVu4XzVYQyahTZBdqR0eMlUNZJBhJE2tO3wi2cCQQCp JkCFd3es0BrNxqfzlThozRFofcz88za7TldydL0YcFtC4Sb4vWsYizwktZ6jcPEm rQz8Gl9W7MO+ynwLptB/AkEA1tsnFXoYzI71enmTdugGxbv0RqAd5iQpDYQkDSdn 2LImp/3YnXNJ9qpY91j87tKthh/Oetu6SHlmLg1LOYNIdw== -----END RSA PRIVATE KEY-----

… et une clé privée cryptée à ça:

-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,F1AB4765D89854CA twxvZobZKXDaJFv8LBkYlbv2OyP8/X3WeLMyJVhHauhAXzcYlxS1DBWgcp6Lb6Yt LrYS95NSs34ymH84j9kIfu/xp3XPMy+6s/0BMAmSIr+kK1n/0KbaEJHxrEhXKr2b UQtGa8qMC1+z9T8sDXk0CEe8Ar1C14qNseCjON4RTOXQx0HQ2LIJjPdzestZSglQ cFk1xhibSBorsKDWIn91I9+dpDtXL3Os+FLjABkHH3JK2qsk7Tf8zEKjzuVuJJJY mfnH0UJX8qZ3fuJmCJ4FIeh1yhUeELlxlNgxB8lcJudktBO6rD8SomppAhdfkONx Nml97DsFTQopzKf4qDYuMPwv1EtlJu8OO+jZWHiBGn1VDvcePlTxXRdkil1/aO7D ly9RXRUN4Y2D9G+UizBasNUiFNoHmpvudwe+XmGIwoY= -----END RSA PRIVATE KEY-----

On peut remarquer les informations sur l'algorithme de cryptage dans les en-têtes PEM de la clé privée cryptée.(Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,F1AB4765D89854CA). Cela vous permet de vérifier que votre clé a bien été cryptée, sans ces en-têtes, en lisant seulement la clé je suis incapable de vous dire si elle est cryptée ou non.

On crée le certificat autosigné

Le certificat est la clé publique de notre CA signé par… heu, notre CA. Je vous rappelle que pour que votre certificat soit trust, il faut normalement le faire signer par une autre CA reconnu, ce qui vous permet de créer une CA intermédiaire. Pour avoir plus de détails sur la mise en production, je vous conseille le site de TBS

openssl req -new -x509 -key ca/ca.key -out ca/ca.pem

Je vous laisse remplir les informations demandées tout seuls, vous êtes grands ! :D
je ne vous fait pas l'affront de vous le traduire. :)

Country Name (2 letter code) [AU]:FR State or Province Name (full name) [Some-State]: Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]: Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []: Email Address []:

Le fichier généré est :

-----BEGIN CERTIFICATE----- MIICKzCCAdWgAwIBAgIJAJ5/od5TrWDmMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV BAYTAkZSMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQwHhcNMTAwNzE1MDkxMzI5WhcNMTAwODE0MDkxMzI5WjBF MQswCQYDVQQGEwJGUjETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMzN 5M2f7NP1yohEk4tw+V3LI0wyxWe6guT7sZO0NJDE3qNqK7LE6u6INJeEFUKREdJj DdHieoVJT/26qN0zkSMCAwEAAaOBpzCBpDAdBgNVHQ4EFgQUwLP8aXE8dKQso73D 1oXf2xYCyh0wdQYDVR0jBG4wbIAUwLP8aXE8dKQso73D1oXf2xYCyh2hSaRHMEUx CzAJBgNVBAYTAkZSMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl cm5ldCBXaWRnaXRzIFB0eSBMdGSCCQCef6HeU61g5jAMBgNVHRMEBTADAQH/MA0G CSqGSIb3DQEBBQUAA0EAAH5/Ml4mqw3rjooMStA7S1gFeDOPvSVdOCdhjiNeA2BW j+pJH49hIKhgptZrW0GbbvjXGAYCq7y9QN676a1BHg== -----END CERTIFICATE-----On génère la clé privée du client

Si l'on veut crypter la clé on peut utiliser l'option -des3

openssl genrsa -out client-key.pem Generating RSA private key, 512 bit long modulus ....................++++++++++++ ...++++++++++++ e is 65537 (0x10001)

On obtient un fichier client-key.pem

On génère la demande de certificatopenssl req -new -key client-key.pem > client.csr ----- Country Name (2 letter code) [AU]:FR State or Province Name (full name) [Some-State]: Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]: Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []: Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:On génére le certificat signé par notre CAopenssl x509 -req -in client.csr -out client-crt.pem -CA ca/ca.pem -CAkey ca/ca.key -CAcreateserial -CAserial ca.srl On génère la clé du serveuropenssl genrsa -out server-key.pem On génère la demande de certificatopenssl req -new -key server-key.pem > server.csr On génère le certificat signé par notre CAopenssl x509 -req -in server.csr -out server-crt.pem -CA ca/ca.pem -CAkey ca/ca.key -CAcreateserial -CAserial ca.srl

Voila nous avons généré nos clés :) (le plus dur est derrière nous) !
Si vous avez plus d'un client il vous faudra générer une clé et un certificat pour chaque client.

Le serveur

Pour suivre cette partie, vous devez connaitre Qt. Si ce n'est pas le cas il faut commencer par là !

Qt, depuis sa version 4.3, permet d'utiliser des socket SSL via la classe QSslSocket, je vous invite à ouvrir la documentation en parallèle de ce tutoriel car c'est cette classe que nous allons utiliser ici.

J'ai choisi de ne pas vous mettre le code complet du serveur, juste les parties qui utilisent SSL, :( ne soyez pas tristes vous trouverez tous les éléments manquants ici.

J'ai choisi d'utiliser 3 classes :

  • FenServeur pour la fenêtre principale de mon serveur

  • Serveur pour ma classe serveur

  • ClientServeur pour les socket du serveur

La classe Serveur#ifndef SERVEUR_H #define SERVEUR_H #include <QTcpServer> #include <ClientServeur.h> class Serveur : public QTcpServer { Q_OBJECT public: Serveur( QObject *parent = 0 ); signals: void nouveauClient(ClientServeur *client); void sslErreur(const QString &error); protected: void incomingConnection( int descriptionSocket ); }; #endif #include "Serveur.h" #include "ClientServeur.h" Serveur::Serveur( QObject *parent ) :QTcpServer( parent ) { } //on surcharge la methode incomingConnection //le but ici est de récupérer un QSslSocket au lieu d'un QTcpSocket void Serveur::incomingConnection( int descriptionSocket ) { ClientServeur *client =new ClientServeur( descriptionSocket, this ); connect(client, SIGNAL(sslError(const QString&)),this, SIGNAL(sslErreur(const QString&)) ); emit nouveauClient(client); }

Cette classe est obligatoire, elle hérite de QTcpServer et surchage la méthode incomingConnection.
Dans cette méthode j'instancie un ClientServeur qui hérite de QSslSocket.

La classe ClientServeur#ifndef CLIENTSERVEUR_H #define CLIENTSERVEUR_H #include <QSslSocket> #include <QtGui> #include <QtNetwork> class ClientServeur: public QSslSocket { Q_OBJECT public: ClientServeur( int descriptionSocket, QObject *parent ); signals: void sslError(const QString &erreur); private slots: void sslErreur( const QList<QSslError> &err ); }; #endif #include "ClientServeur.h" ClientServeur::ClientServeur( int descriptionSocket, QObject *parent ) : QSslSocket( parent ) { connect( this, SIGNAL(disconnected()), SLOT(deleteLater()) ); connect( this, SIGNAL(sslErrors(QList<QSslError>)), SLOT(sslErrors(QList<QSslError>)) ); if( !setSocketDescriptor( descriptionSocket ) ) { return; } //on charge la clé privé QFile file( "../../key/server-key.pem" ); if( ! file.open( QIODevice::ReadOnly ) ) { qDebug() << "ouverture de la clé impossible" << "../../key/server-key.pem"; return; } QSslKey key( &file, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "mapassphrase" ); file.close(); setPrivateKey( key ); //on charge le certificat de la ca if( ! addCaCertificates( "../../key/ca/ca.pem" ) ) { qDebug() << "ouverture du certificat de la ca impossible" << "../../key/ca/ca.pem"; return; } //on charge le certificat du serveur setLocalCertificate( "../../key/server-crt.pem" ); //j'enleve la vérification des clients, mon but ici est de crypter la connexion pas de vérifier l'identité des différents clients setPeerVerifyMode(QSslSocket::VerifyNone); //on ignore les erreurs ssl car on a un certificat autosigné qui est donc non sure, on a la possiblité de choisir les erreurs à ignorer en les passant en arguments à la méthode ignoreSslErrors(); //on demarre le cryptage startServerEncryption(); } void ClientServeur::sslErreur( const QList<QSslError> &errors ) { foreach( const QSslError &error, errors ) { emit sslError(QString::number(error.error())); } }

Cette classe va charger la clé et le certificat de notre serveur, elle va aussi charger le certificat de notre CA. Ce certificat est utilisé si on active la vérification des peers dans SSL avec l'option setPeerVerifyMode. J'ai choisi ici de supprimer cette vérification pour rendre le tutoriel plus simple.
N'oubliez pas de changer « mapassphrase » par votre passphrase (enregistrée lors de la génération des clés).

La classe FenServeur

Dans la classe FenServeur, il suffit juste d'instancier un Server et de connecter les signaux.

serveur = new Serveur(this); if (!serveur->listen(QHostAddress::Any, 50885)) // Démarrage du serveur...

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Sécurisation d'un chat réseau Qt avec QSslSocket

Prix sur demande