Certificats x509 et mTLS : comprendre et pratiquer avec OpenSSL

Chiffrement symétrique et asymétrique, signature, autorité de certification, chaîne de confiance : les bases pour comprendre les certificats x509. Puis la pratique avec OpenSSL : créer sa propre CA, signer des certificats serveur et client, et monter une connexion mTLS.

Introduction

Ce cours, je l'ai donné sous forme de TP en avril 2023, avec des slides reveal.js hébergées sur mon ancien blog. Je le reprends ici sous forme d'article, en le mettant à jour, et les slides d'origine restent disponibles en fin d'article.

L'objectif : comprendre ce qu'est un certificat x509, ce qu'est une autorité de certification (CA), savoir générer ses propres certificats avec OpenSSL, et mettre en place une connexion mTLS (TLS mutuel), où le client s'authentifie lui aussi avec un certificat.

SSL ou TLS ?

On entend encore parler de « certificat SSL », mais SSL et TLS sont des protocoles, pas des certificats. Les protocoles utilisent des certificats.

SSL est obsolète depuis longtemps : aujourd'hui on fait du TLS, et l'ANSSI recommande de n'utiliser que TLS 1.2 et TLS 1.3. Si les vendeurs parlent toujours de « certificats SSL », c'est historique : le nom a été conservé pour ne pas perdre les clients.

Rappels de cryptographie

Symétrique vs asymétrique

En chiffrement symétrique, Alice et Bob utilisent la même clé secrète pour chiffrer et déchiffrer. C'est rapide et adapté aux gros volumes de données, mais il faut pouvoir s'échanger la clé de manière sûre.

En chiffrement asymétrique, chacun possède une paire de clés :

  • une clé publique, que l'on peut distribuer à tout le monde ;
  • une clé privée, qui ne doit jamais sortir de chez son propriétaire.

Il est (en l'état actuel des connaissances) impossible de retrouver la clé privée à partir de la clé publique. Deux usages en découlent :

  • Chiffrer : Alice veut envoyer un message confidentiel à Bob, elle le chiffre avec la clé publique de Bob. Seul Bob, avec sa clé privée, pourra le lire.
  • Signer : Alice signe un message avec sa propre clé privée. N'importe qui peut vérifier la signature avec la clé publique d'Alice, et donc s'assurer que le message vient bien d'elle et n'a pas été modifié.

Fonctions de hachage

Une fonction de hachage transforme une donnée de taille quelconque en une empreinte de taille fixe (SHA-256 par exemple). On ne signe d'ailleurs jamais un document entier : on signe son empreinte.

Les suites cryptographiques

On a donc trois familles d'outils : le symétrique pour chiffrer beaucoup de données, l'asymétrique pour l'échange de clés et l'authentification, et le hachage pour l'intégrité. Une connexion TLS combine les trois, et cette combinaison s'appelle une suite cryptographique.

Exemple en TLS 1.2 : TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

  • Échange de clés : ECDHE
  • Authentification : RSA
  • Chiffrement : AES 128 en mode GCM
  • Hachage : SHA-256

En TLS 1.3, les suites sont simplifiées (TLS_AES_128_GCM_SHA256) : l'échange de clés est toujours éphémère et négocié à part. Pour explorer les suites et savoir lesquelles sont sûres : ciphersuite.info.

Le certificat x509

Un certificat X.509 lie une identité à une clé publique grâce à une signature numérique. Il contient une identité (un nom d'hôte, une organisation, une personne) et une clé publique, et il est soit signé par une autorité de certification, soit auto-signé.

Concrètement, un certificat contient notamment : le sujet (CN, O…), l'émetteur, une période de validité, la clé publique, des extensions (usages autorisés, noms alternatifs…) et la signature de l'émetteur.

L'autorité de certification (CA)

La CA garantit le lien entre une clé publique et son propriétaire en signant le certificat avec sa clé privée. Tout le monde peut ensuite vérifier cette signature avec la clé publique de la CA. C'est la base d'une PKI.

La chaîne de certificats

Votre système et votre navigateur disposent d'un magasin de certificats contenant les CA racines de confiance. Une CA racine signe des CA intermédiaires, qui signent à leur tour les certificats des sites. Pour valider un certificat, on remonte la chaîne jusqu'à une racine connue.

TP 1 : créer sa CA et signer des certificats

Tout se fait avec openssl, dans un dossier de travail.

La CA

On génère la clé privée de la CA puis son certificat auto-signé :

openssl genrsa -out ca.key 4096

openssl req -x509 -new -key ca.key -sha256 -days 3650 \
  -subj "/CN=Ilogus Lab CA" \
  -out ca.crt

Pour inspecter le certificat :

openssl x509 -in ca.crt -noout -text

Le certificat serveur

Le serveur génère sa clé et une CSR (Certificate Signing Request) : une demande qui contient sa clé publique et son identité, à faire signer par la CA.

openssl req -newkey rsa:2048 -nodes \
  -keyout server.key \
  -subj "/CN=localhost" \
  -out server.csr

Les usages du certificat sont définis par des extensions. Plutôt que de copier tout openssl.cnf comme dans les slides d'origine, un petit fichier server.ext suffit :

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:localhost, IP:127.0.0.1

Le subjectAltName est indispensable : les navigateurs et la plupart des clients ignorent le CN et ne vérifient que les noms alternatifs.

La CA signe la CSR :

openssl x509 -req -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -days 365 -sha256 -extfile server.ext \
  -out server.crt

Le certificat client

Même principe, avec un fichier client.ext qui autorise l'authentification client (et la signature d'emails) :

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
openssl req -newkey rsa:2048 -nodes \
  -keyout client.key \
  -subj "/CN=alice" \
  -out client.csr

openssl x509 -req -in client.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -days 365 -sha256 -extfile client.ext \
  -out client.crt

On vérifie que tout est bien signé par notre CA :

openssl verify -CAfile ca.crt server.crt client.crt

TP 2 : une connexion mTLS

En TLS classique, seul le serveur présente un certificat. En mTLS, le serveur exige aussi un certificat du client, signé par une CA qu'il connaît. C'est très utilisé entre services (API internes, IoT, accès d'administration).

On lance un serveur de test qui exige un certificat client :

openssl s_server -accept 8443 \
  -cert server.crt -key server.key \
  -CAfile ca.crt -Verify 1 -www

Sans certificat client, la poignée de main échoue :

curl --cacert ca.crt https://localhost:8443/

Avec le certificat client, la connexion passe et le serveur renvoie les détails de la session TLS :

curl --cacert ca.crt --cert client.crt --key client.key https://localhost:8443/

En production, c'est le même principe côté Nginx :

ssl_client_certificate /etc/nginx/mtls/ca.crt;
ssl_verify_client on;

Pendant le TP d'origine, on faisait la même chose avec Postman (Settings → Certificates) et on observait la poignée de main dans Wireshark, en comparant les versions de TLS. C'est un très bon exercice pour voir passer les certificats.

Pour aller plus loin : Extended Key Usage

Les extensions keyUsage et extendedKeyUsage restreignent ce que l'on peut faire avec la clé : un certificat serverAuth ne doit pas pouvoir authentifier un client, et inversement. C'est ce que nous avons fait avec les fichiers .ext.

Pour importer son certificat client dans un navigateur ou un client mail (signature S/MIME), on combine clé et certificat dans un fichier PKCS#12 :

openssl pkcs12 -export -out client.p12 \
  -inkey client.key -in client.crt -certfile ca.crt

Les slides du cours

Voici les slides d'origine du cours (en anglais). Naviguez avec les flèches, la barre d'espace, ou ouvrez-les en plein écran.

Cliquez dans les slides puis utilisez les flèches du clavier · Ouvrir en plein écran ↗

Conclusion

Un certificat x509, c'est une clé publique, une identité et une signature qui les lie. Une fois ce principe compris, la CA, la chaîne de confiance et le mTLS deviennent assez naturels. Avec OpenSSL et quelques fichiers .ext, vous avez tout ce qu'il faut pour monter un environnement de test complet en local.