Des certificats signés par votre autorité de certification avec OpenSSL

Une autorité de certification (AC ou CA pour certificate authority) est un tiers de confiance qui a un rôle central dans le mécanisme d'une PKI. Pour initier une transaction sécurisée par SSL, un serveur doit fournir un certificat et une clé publique. Ce certificat doit être signé par un CA afin de garantir son authenticité.

Il existe des CA "publiques" (par exemple, Verisign). Ce sont des fournisseurs qui facturent la génération du certificat. Afin de garantir leur identité, les CA signent le certificat donné avec leur clé privée. L'avantage des CA "publiques" et que la plupart des systèmes d'exploitations possèdent la clé publique de ces CA. Le désavantage est que chaque certificat émis est payant et assez cher.

Il peut être très intéressant de créer son propre CA pour son réseau interne. Des économies sont réalisées, et nous ne dépendons plus d'une entreprise externe pour la vérification des certificats. Le problème est que les clients externes ne feront pas confiance à nos certificats, à cause de l'absence de la clé publique dans le système d'exploitation. Ce n'est pas un problème bloquant dans le cadre d'un réseau interne, il suffira juste de transmettre la clé publique du CA à nos clients.

Nous allons travailler avec OpenSSL, qui nous fournira tous les outils nécessaires.

# aptitude install openssl

Pour accéder à la boite à outil d'OpenSSL, il faudra entrer une commande du type :

$ openssl commande [paramètres de la commande]

J'expliquerai rapidement, dans cet article, les lignes que nous entrerons. Pour de plus amples détails, sachez que chaque commande d'openssl possède sa page de man, accessible en tapant

$ man commande

Préparation

Partons sur des bases saines en créant un dossier dédié au CA. Par exemple ici, un dossier certificate-authority dans notre répertoire home. Dans ce dossier, nous allons créer quatre sous-dossiers :

  • private : contiendra les clés privés pour le CA ainsi que pour les certificats que nous créerons.
  • certs : contiendra les certificats pour le CA ainsi que pour les requêtes que nous traiterons.
  • newcerts : tout nouveau certificat créé sera également copié dans ce répertoire avec pour nom de fichier, un serial number.
  • crl : contiendra le Certificate Revocation List.
$ mkdir -p certificate-authority/{private,certs,newcerts,crl}

Toujours dans le dossier certificate-authority, nous allons créer deux fichiers :

  • index.txt : un fichier utilisé par OpenSSL pour stocker les informations des certificats signés
  • serial : chaque certificat possède un serial. Ce fichier contient le serial du prochain certificat. La valeur est incrémentée automatiquement.
$ touch index.txt
$ echo "01" > serial

Dernière étape, copier le fichier de configuration d'OpenSSL vers notre CA et l'ajuster pour qu'il pointe vers les répertoires et fichiers que nous venons de créer.

$ cp /etc/ssl/openssl.cnf ca-config
[ CA_default ]

dir             = .                     # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $dir/certs/ca.crt    # The CA certificate
serial          = $dir/serial           # The current serial number
#crlnumber      = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/ca.key   # The private key

Note : toutes les commandes OpenSSL que nous allons aborder sont, avec cette configuration, à exécuter depuis le dossier certificate-authority.

Toujours dans le fichier ca-config, vous pouvez ensuite modifier les valeurs par défaut des certificats.

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = FR
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = LANGUEDOC ROUSSILLON

localityName                    = Locality Name (eg, city)
localityName_default            = MONTPELLIER

0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = JEYG

organizationalUnitName          = Organizational Unit Name (eg, section)
#organizationalUnitName_default =

commonName                      = Common Name (eg, YOUR name)
commonName_max                  = 64

emailAddress                    = Email Address
emailAddress_max                = 64

La durée de validité par défaut des certificats peut également être modifiée :

default_days    = 365                  # how long to certify for

Enfin, vous pouvez définir quels champs devront être présents pour la création d'un certificat. Notez qu'il vous faut au minimum un commonName.

[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

Création de l'autorité de certification

Pour cela, nous devons créer un certificat qui nous permettra de signer les demandes de certificats futures.

$ openssl req -new -x509 -extensions v3_ca -newkey rsa:4096 -keyout private/ca.key -out certs/ca.crt -config ca-config

Les explications des paramètres, pour la plupart tirées du man.

req : utilitaire de génération de certificats et de demandes de certificat PKCS#10.
-new : nouvelle demande de certificat.
-x509 : cette option génère un certificat auto-signé à la place d'une demande de certificat. Elle est utilisée typiquement pour générer des certificats de test ou le certificat auto-signé racine d'une CA.
-extensions v3_ca : permet de générer un certificat SSL v3, en se référant à la section v3_ca du fichier de configuration d'OpenSSL.
-newkey rsa:4096 : Génération d'une clé privée RSA de 4096 bits.
-keyout private/ca.key : donne le nom de fichier où la clé privée créée sera écrite.
-out certs/ca.crt : spécifie le nom du fichier (le certificat) de sortie.
-config ca-config : permet d'utiliser un fichier de configuration alternatif, à la place d'openssl.cnf.

Si vous ne voulez pas chiffrer la clé privée, ajoutez l'option -nodes.

Entrez la passphrase pour la clé privée puis les renseignements demandés pour le certificat. Appuyez sur entrée pour appliquer ceux que vous avez définis par défaut dans le ca-config.

$ openssl req -new -x509 -extensions v3_ca -newkey rsa:4096 -keyout private/ca.key -out certs/ca.crt -config ca-config
Generating a 4096 bit RSA private key
..........................................................................++
............................................................................++
writing new private key to 'private/ca.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [LANGUEDOC ROUSSILLON]:
Locality Name (eg, city) [MONTPELLIER]:
Organization Name (eg, company) [JEYG]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:ca.jeyg.info
Email Address []:root@localhost

Création du Certificate Signing Request (CSR)

Un CSR est un message qui, une fois soumis au CA, permet de générer un certificat. Nous allons aborder la génération du CSR à travers deux exemples : l'un destiné à un certificat pour serveur, l'autre pour un utilisateur.

CSR pour serveur

Puisque le certificat sera utilisé par un service, et donc qu'il n'y aura a priori pas d'interaction humaine possible lors de la lecture du certificat, il ne doit pas être protégé par une passphrase.

$ openssl req -new -nodes -newkey rsa:2048 -keyout private/webserver.key -out webserver.csr -config ca-config

Pas d'options nouvelles. Comme tout à l'heure, l'option -nodes permet de ne pas spécifier de passphrase. On met le .csr en sortie avec le -out. Il vous est ici aussi demandé de remplir des champs. Le champ commonName, qui doit correspondre à l'URL du serveur.

$ openssl req -new -nodes -newkey rsa:2048 -keyout private/webserver.key -out webserver.csr -config ca-config
Generating a 2048 bit RSA private key
.................................................................+++
.........................+++
writing new private key to 'private/webserver.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [LANGUEDOC ROUSSILLON]:
Locality Name (eg, city) [MONTPELLIER]:
Organization Name (eg, company) [JEYG]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:jeyg.info
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CSR pour utilisateur

Cette fois-ci, le certificat est utilisé par un humain. Il est donc possible et conseillé de le protéger avec une passphrase.

$ openssl req -new -newkey rsa:2048 -keyout private/bill-murray.key -out bill-murray.csr -config ca-config

Il s'agit des mêmes options que pour le CSR serveur, mis à part le -nodes qui a disparu. On remplit le champ commonName avec le nom du futur utilisateur.

$ openssl req -new -newkey rsa:2048 -keyout private/bill-murray.key -out bill-murray.csr -config ca-config
Generating a 2048 bit RSA private key
.....................+++
.......................................................+++
writing new private key to 'private/bill-murray.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [LANGUEDOC ROUSSILLON]:
Locality Name (eg, city) [MONTPELLIER]:
Organization Name (eg, company) [JEYG]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:bill-murray
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Création du certificat signé

Il ne reste plus qu'à utiliser nos CSR pour générer nos certificats.

$ openssl ca -config ca-config -policy policy_anything -out certs/webserver.crt -infiles webserver.csr

ca : application CA minimale qui peut être utilisée pour signer des demandes de certificats.
-config ca-config : permet d'utiliser un fichier de configuration alternatif, à la place d'openssl.cnf.
-policy policy_anything : cette option définit la « politique » de la CA à utiliser. Il s'agit d'une section du fichier de configuration spécifiant les champs qui sont obligatoires ou qui doivent correspondre au certificat de la CA.
-out certs/webserver.crt : spécifie le nom du fichier (le certificat) de sortie.
-infiles webserver.csr : le ou les fichiers CSR à utiliser.

$ openssl ca -config ca-config -policy policy_anything -out certs/webserver.crt -infiles webserver.csr
Using configuration from ca-config
Enter pass phrase for ./private/ca.key:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Mar 20 23:26:58 2012 GMT
            Not After : Mar 18 23:26:58 2022 GMT
        Subject:
            countryName               = FR
            stateOrProvinceName       = LANGUEDOC ROUSSILLON
            localityName              = MONTPELLIER
            organizationName          = JEYG
            commonName                = jeyg.info
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                FA:2A:42:35:47:D0:91:A3:30:CC:30:FF:A8:75:28:CB:9C:6E:0E:66
            X509v3 Authority Key Identifier:
                keyid:82:DD:48:75:CD:57:11:6B:8F:87:5D:18:47:71:D0:74:2E:D5:F9:11

Certificate is to be certified until Mar 18 23:26:58 2022 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Faire parler les certificats

Afficher les informations d'un certificat :

$ openssl x509 -in certs/webserver.crt no-out --text

x509 : utilitaire d'affichage et de signature de certificat.
-in certs/webserver.crt : le certificat à lire.
-noout : permet de ne pas afficher le certificat encodé.
-text : afficher toutes les informations du certificat.

$ openssl x509 -in certs/webserver.crt -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=FR, ST=LANGUEDOC ROUSSILLON, L=MONTPELLIER, O=JEYG, CN=ca.jeyg.info/emailAddress=root@localhost
        Validity
            Not Before: Mar 20 23:26:58 2012 GMT
            Not After : Mar 18 23:26:58 2022 GMT
[..]

Vérifier qu'un certificat est valide pour le CA :

$ openssl verify -CAfile certs/ca.crt certs/webserver.crt

verify : utilitaire de vérification de certificats.
-CAfile certs/ca.crt : le certificat du CA.
certs.webserver.crt : le certificar à vérifier.

$ openssl verify -CAfile certs/ca.crt certs/webserver.crt
certs/webserver.crt: OK

Les certificats reconnus par votre système

Nous l'avons vu au tout début de cet article, il suffit d'importer la clé publique du CA sur notre machine cliente pour que les certificats signés par notre CA soient validés. Cette clé publique est incluse dans le certificat du CA.

Pour un système Debian, il suffit de copier le certificat dans le répertoire /usr/share/ca-certificates/ et de reconfigurer le paquet ca-certificates afin d'ajouter le certificat à la liste des tiers de confiance. Le fichier sera automatiquement copié dans /etc/ssl/certs.

# cp ca.crt /usr/share/ca-certificates/
# dpkg-reconfigure ca-certificates

Les logiciels peuvent nécessiter une configuration spécifique pour ajouter le CA.

Bien entendu, libre à vous de télécharger le certificat du CA de la manière que vous préferez. Pourquoi pas l'automatiser avec un gestionnaire de configurations (Puppet ou Chef).

Voila, comme par magie, les certificats générés par le CA sont reconnus par votre système. Un exemple avec le certificat webserver créé tout à l'heure, utilisé sur un serveur web :

Des manipulations spécifiques aux logiciels, navigateurs, peuvent être nécessaires. Je vous laisse le plaisir de chercher comment réaliser la même démarche sur Windows.

Attention, le commonName du certificat doit être strictement identique à l'URL, sinon...

Conclusion

Nous avons vu comment mettre en place notre propre autorité de certification, créer des certificats adaptés à nos besoins avec cette autorité, retrouver leurs informations, et faire en sorte qu'ils soient reconnus sur les machines clientes, toujours grâce au CA. OpenSSL est un outil très puissant, aux multiples facettes. Aussi je vous recommande de lire le man plus en détail pour débusquer des options intéressantes.

Sur ce, je vous souhaite de bonnes générations de certificats !

Vus : 4481
Publié par Jeyg : 33