Aller au contenu

Gestion de certificats x509

cover

Que sont les certificats x509 ?

D'après Wikipedia, x509 est une norme définissant le format des certificats de type clé publique. Ils sont utilisés dans de nombreux protocoles Internet, dont TLS/SSL, qui est à la base de HTTPS (le protocole de navigation sécurisé sur le Web).

But

Le but d'avoir ma propre autorité de certification (CA) me permet de générer des certificats auto-signés pour des utilisations non publiques. Mes services étant hébergés sur mon propre réseau privé m'empêchent d'obtenir des certificats gratuits de la populaire autorité certification Let's Encrypt.

Vu que j'héberge plus d'un service et que je veux que tous mes appareils (ordinateur portable, téléphone, ...) puissent y avoir accès sans avoir à installer de certificat toutes les 3 semaines (lorsque je mets à jour les noms d'hôtes par exemple). J'ai décidé de créer ma propre autorité de certification et de générer des certificats signés et validés par celle-là. De cette façon, je n'ai qu'à installer l'autorité de certification racine sur tous mes appareils pour que cela fonctionne.

Création de ma propre autorité de certification

Tout ce dont j'ai besoin est un environnement Linux et openssl.

Génération du secret

Tout d'abord je génère la clé privée avec la commande suivante :

openssl genrsa -out root-CA.key 4096

Résultat :

Generating RSA private key, 4096 bit long modulus
.................................................................++
......................................................................................................................................................................++
e is 65537 (0x10001)

J'ai maintenant une belle clé privée :

-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEA2IxiR6U/B6Ypd1/3KG5Pxk/BY47HzHpBAHnEFsMHdcpCNNXO
GxqhUsIHBGMc0I2xa0WiyNJB4k5qGwL58J1TK/kKaW8yOOGajawvhjL/6bYXgN1I
[...]
rcL3YJyl/m0mlYl80syPPViHM9TD7uwQi/M9DPeOGLwVuCYzpl3qAkQRaTwQc2Ev
5hffBNz+evhf2Q7iUCmWQFizIFlFpOCq1f/jvpleqf8ChG6EhNRgvAFIUMc=
-----END RSA PRIVATE KEY-----

Ce fichier doit être gardé secret et stocké de manière sécurisé hors ligne.

Génération de la configuration du certificat

Maintenant que j'ai la partie secrète, je dois générer la partie publique : le certificat x509. En utilisant de la configuration OpenSSL par défaut :

[ req ]
default_bits       = 4096
default_keyfile    = root-CA.key
encrypt_key        = no
utf8               = yes
distinguished_name = req_distinguished_name
prompt             = no
x509_extensions    = v3_ca

[ req_distinguished_name ]
countryName         = FR
stateOrProvinceName = France
localityName        = Paris
organizationName    = Example
commonName          = example.org

[ v3_ca ]
subjectKeyIdentifier = hash
basicConstraints     = critical,CA:true,pathlen:1
keyUsage             = critical,keyCertSign

Cette configuration doit être conservée pour la prochaine fois que je dois regénérer le certificat racine. Gardez à l'esprit que ce certificat ne doit pas être modifié trop souvent, sinon cela rendrait l'objectif principal inutile.

Vous pouvez ajuster cette configuration en fonction de vos besoins.

Génération du certificat racine

En utilisant la configuration précédente, j'ai généré l'autorité de certification racine auto-signée :

openssl req -x509 -new -nodes \
  -config root-CA-openssl.cnf \
  -key root-CA.key \
  -sha256 -days 1024 \
  -out root-CA.crt

Vérification du contenu du certificat :

openssl x509 -in root-CA.crt -noout -text

Résultat :

Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 11676879669831540892 (0xa20c9c31654a209c)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=FR, ST=France, L=Paris, O=Example, CN=example.org
        Validity
            Not Before: Feb  6 15:53:58 2022 GMT
            Not After : Nov 26 15:53:58 2024 GMT
        Subject: C=FR, ST=France, L=Paris, O=Example, CN=example.org
[...]
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                F1:FA:C4:50:A4:7F:53:D3:6C:D5:EF:48:72:24:B8:CE:08:10:3F:94
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:1
            X509v3 Key Usage: critical
                Certificate Sign
[...]

Cette commande génère le fichier certificat et signe son contenu avec la clé privée.

J'ai maintenant un certificat d'autorité, je peux générer tous les certificats de mes applications et les signer avec.

Créer des certificats pour mes applications

Génération du secret

Comme pour l'autorité de certification racine, j'ai besoin de générer une clé secrète.

Je peux utiliser une commande identique à précédemment :

openssl genrsa -out my-app.key 2048

Génération de la configuration openssl

Je dois maintenant créer la configuration OpenSSL pour mon certificat en utilisant la configuration OpenSSL par défaut :

[ req ]
default_bits       = 2048
default_keyfile    = my-app.key
encrypt_key        = no
utf8               = yes
distinguished_name = req_distinguished_name
req_extensions     = v3_req
prompt             = no

[ req_distinguished_name ]
countryName         = FR
stateOrProvinceName = France
localityName        = Paris
organizationName    = Example
commonName          = my-app.example.org

[v3_req]
subjectKeyIdentifier = hash
subjectAltName       = @alt_names

[ alt_names ]

DNS.1 = my-app.example.org
DNS.2 = extra.my-app.example.org

Notez ici que le paramètre subjectAltName et les alt_names sont très importants. Désormais, chaque navigateur ou application sur téléphone nécessite que le nom d'hôte exposé par l'application Web soit spécifié dans cette section.

Vous pouvez toujours ajouter plusieurs noms alternatifs au certificat. Cela vous permet d'utiliser le même certificat pour plusieurs applications. Assurez-vous d'utiliser un certificat différent en fonction du niveau de sécurité dont vous avez besoin pour vos applications.

Génération de la demande de certificat

Afin de générer un certificat signé par mon autorité de certification racine, je dois générer une demande de certificat. À l'aide de la commande suivante, je peux générer la requête et la signer avec la clé privée de l'application :

openssl req -sha256 -new \
  -key my-app.key \
  -config my-app.cnf \
  -out my-app.csr

Je peux vérifier le contenu de ma demande avec :

openssl req -in my-app.csr -noout -text

Résultat :

Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=FR, ST=France, L=Paris, O=Example, CN=my-app.example.org
[...]

Signer mon certificat d'application avec l'autorité de certification racine

Enfin, je dois utiliser mon autorité de certification racine pour générer mon certificat d'application en fonction de la demande et garantir son authenticité.

J'ai seulement besoin d'utiliser la commande suivante :

openssl x509 -req \
  -CA root-CA.crt \
  -CAkey root-CA.key \
  -CAcreateserial \
  -in my-app.csr \
  -days 500 -sha256 \
  -out my-app.crt

Pour vérifier le contenu du certificat nouvellement généré, je peux exécuter la commande suivante :

openssl x509 -in my-app.crt -noout -text

Résultat :

Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 15807445207358136962 (0xdb5f53aa27086282)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=FR, ST=France, L=Paris, O=Example, CN=example.org
        Validity
            Not Before: Feb  6 16:22:38 2022 GMT
            Not After : Jun 21 16:22:38 2023 GMT
        Subject: C=FR, ST=France, L=Paris, O=Example, CN=my-app.example.org

Vérification de la chaîne de confiance complète

Maintenant que j'ai le certificat de mon application, je dois m'assurer que l'autorité de certification racine en valide l'authenticité.

En utilisant une dernière commande openssl :

openssl verify \
  -CAfile root-CA.crt \
  my-app.crt

Résultat :

my-app.crt: OK