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
subjectAltNameest indispensable : les navigateurs et la plupart des clients ignorent leCNet 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.
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.