Artisan Numérique

/système/sécurité/ Créer sa propre (mini) PKI

Pour sécuriser une connection à un serveur web (https), un serveur imap (imaps) ou tout autre client utilisant SSL ou TLS, nous avons besoin d'un certificat. Dans une première approche il est possible d'utiliser des certificat dits "auto-signés". Générés très facilement, il sont très pratique pour développer et tester un site sécurisé mais beaucoup moins s'agissant d'une utilisation régulière et publique, principalement à cause des avertissements de sécurité qu'ils génèrent sur l'application cliente. L'autre option est alors d'acheter un certificat auprès d'un tiers de confiance. Certificat qui vous permettra à votre tour d'en générer d'autres qui cette fois seront acceptés sans erreur.

La troisième voie développée ici, entre l'auto-signature et l'achat, consiste à créer sa propre autorité certifiante qui, une fois importée, par exemple dans un navigateur, se comportera exactement de la même manière que si vous l'aviez achetée. Au delà de la compréhension technique des mécanismes mis en jeu, cette approche est plutôt bien adaptée à une petite structure qui n'a pas le goût de payer un certificat et pour qui distribuer ou pré-installer une autorité ne pose pas de problèmes (nombre restreint d'utilisateurs, postes pré-installés, etc.).

Pour sécuriser une connection à un serveur web (https), un serveur imap (imaps) ou tout autre client utilisant SSL ou TLS, nous avons besoin d'un certificat. Dans une première approche il est possible d'utiliser des certificat dits "auto-signés". Générés très facilement, il sont très pratique pour développer et tester un site sécurisé mais beaucoup moins s'agissant d'une utilisation régulière et publique, principalement à cause des avertissements de sécurité qu'ils génèrent sur l'application cliente. L'autre option est alors d'acheter un certificat auprès d'un tiers de confiance. Certificat qui vous permettra à votre tour d'en générer d'autres qui cette fois seront acceptés sans erreur.

La troisième voie développée ici, entre l'auto-signature et l'achat, consiste à créer sa propre autorité certifiante qui, une fois importée, par exemple dans un navigateur, se comportera exactement de la même manière que si vous l'aviez achetée. Au delà de la compréhension technique des mécanismes mis en jeu, cette approche est plutôt bien adaptée à une petite structure qui n'a pas le goût de payer un certificat et pour qui distribuer ou pré-installer une autorité ne pose pas de problèmes (nombre restreint d'utilisateurs, postes pré-installés, etc.).

Quelques bases

Dés que l'on souhaite mettre en oeuvre une connection cryptée par SSL, que ce soit pour Cyrus (IMAPS) ou pour Apache (HTTPS), il est nécessaire d'avoir un certificat. Ce certificat installé sur le serveur contient une paire de clef qui vont permettre aux deux parties de mettre en place un échange chiffré. Une des informations échangée à ce stade est une autre clef qui va servir quant à elle à chiffrer, par un algorithme dit "symétrique", le reste de la communication. La raison de ce changement de clef tient à ce que le chiffrement asymétrique est plus demandeur en ressources, mais aussi plus sécurisé, que sa contrepartie symétrique. Ce protocole permet en quelque sorte d'arriver au meilleur des deux mondes.

Un certificat peut très facilement être généré en utilisant les outils du paquet openssl. Mais pour qu'un certificat serveur soit déclaré valide sur le client il doit répondre à trois règles, et tout manquement à l'une de ces règles entraîne l'affichage d'un message d'avertissement sur le navigateur client.

  1. Le certificat doit contenir le nom du site qu'il sécurise (ex. www.mon_site.fr). Si ce n'est pas le cas, le navigateur protestera que le certificat ne provient pas de la bonne adresse.
  2. Le certificat doit contenir une signature fiable. Si ce n'est pas le cas, certain navigateurs se contenterons de pleurer un peu, d'autres, comme FireFox, bloquera l'accès avec un signature invalide
  3. Le certificat doit être signé par un AC (Autorité de Certification) ou par un certificat qui lui même est signée par un AC. Et c'est ici le point le plus délicat dont nous allons maintenant discuter.

Revenons à la règle n°3. Un certificat doit être signé à un moment ou à un autre par ce que l'on appelle "un tiers de confiance". Sur Internet, le rôle de tiers de confiance est joué par des sociétés commerciales que l'on paye grassement juste pour signer un certificat d'AC à notre nom et qui va nous permettre de générer nos certificats... Et si en tant que petite société, pour son intranet par exemple, nous désirons nous débarrasser des messages d'erreur du navigateur, il faut soit payer sa dîme, soit s'auto-proclamer AC...

Bien évidemment, ce n'est pas aussi simple. Les certificats sont un maillon important de la sécurisation des transactions par internet. La signature par un AC assure par exemple au client d'une banque qu'il est bien sur SA banque (c'est écrit dans le certificat). Un navigateur web, par exemple, va donc vérifier que le certificat du site que vous cherchez à consulter est légitimement signé. Plus exactement il va vérifier la validité de la chaîne des signatures. Il va commencer par regarder si le certificat est valide (non périmé, réprouvé, etc.), puis si le certificat est signé par une AC de confiance. Si c'est le cas il s'arrête là, sinon, il regarder qui a signé le certificat de cette AC, si son certificat est valide, s'il est signé par une AC de confiance, etc. Pour faire cela, tout navigateur connaît donc en standard la série complète de ces AC "de confiance".

Cependant, pour notre salut, tout client prenant en charge SSL permet à l'utilisateur de rajouter sa propre AC. C'est une action volontaire qui ne peut être automatisée. Vous allez ainsi fournir à vos utilisateur un fichier dit "DER" qu'il va importer dans son logiciel (FireFox, IE, etc..). Ceci fait, tout les certificats que vous signerez de cette AC maison, seront valides et le navigateur ne couinera plus, les 3 règles seront satisfaites.

Fabrication d'une petite PKI

Nous allons très modestement faire notre petite PKI à la mano. Cette PKI (Private Key Infrastructure) vas nous permettre de générer et de signer à la chaîne nos certificats. J'utilise le mot pki pour rire car une vraie PKI est un ensemble complexe comprenant non seulement la génération des certificats, mais aussi et entre autre leur révocation. Cependant, nous disposerons bientôt d'une mini-pki avec son AC et sa base de certificats ce qui n'est déjà pas si mal.

Première étape créer un dossier qui contiendra nos données, disons /root/pki, et la base de données des certificats :

Création de l'infrastructure
rootmkdir /root/pki
rootcd /root/pki
rootmkdir -p db/ca.db.certs
rootmkdir config
rootmkdir certificats

Initialisation des numéros de séries à 1
rootecho '01'> db/ca.db.serial

Initialisation de l'index des certificats
rootcp /dev/null db/ca.db.index
initialisation de la base de données

Ce dossier est sensible, il contient des donnes importantes qui permettrait, si son contenu venait à "fuiter", n'importe qui serait en capacité de créer des certificats à votre nom !!

Maintenant nous allons créer le fichier de configuration config/ca.config qui va permettre à openssl d'utiliser notre nouvelle base :

[ ca ]
default_ca      = CA_own

[ CA_own ]
dir             = /root/pki/db
certs           = /root/pki/db
new_certs_dir   = /root/pki/db/ca.db.certs
database        = /root/pki/db/ca.db.index
serial          = /root/pki/db/ca.db.serial
RANDFILE        = /root/pki/db/ca.db.rand
certificate     = /root/pki/certificats/ca.crt
private_key     = /root/pki/certificats/ca.key
default_days    = 3000
default_crl_days = 30
default_md      = md5
preserve        = no
policy  = policy_anything

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

Tout est en place, nous allons maintenant générer la clef privée de notre AC maison.

rootopenssl genrsa -des3 -out certificats/ca.key 1024
Generating RSA private key, 1024 bit long modulus
.........................++++++
..........++++++
e is 65537 (0x10001)
Enter pass phrase for certificats/ca.key:# toto
Verifying - Enter pass phrase for certificats/ca.key:# toto
root#
création de la clef privée de la AC

Juste un détail, toto n'est pas un mot de passe intelligent... Préférez un mot de passe à 12 caractères contenant des chiffres, des symboles, des lettres, et des variations de majuscules/minuscules, et surtout, ne voulant rien dire !! N'utilisez pas non plus de générateur par internet ou de vérificateur de solidité de mot de passe par internet. Rien de plus idiot que de fournir ou de demander votre mot de passe stratégique à un inconnu... Tout ceci est d'ailleurs valable pour tout les mots de passe... Attention aussi à ne pas perdre le mot de passe qui va vous être demandé, il vous servira pour chaque nouvelle signature de certificat.

La clef de notre CA étant générée, nous allons créer un certificat "auto-signé" valable pour 3000 jours (cela nous laisse un peu de marge ;-). Auto-signé veut dire que le certificat est utilisé pour se signer lui-même.

rootopenssl req -utf8 -new -x509 -days 3000 -key cacertificatsca.key -out certificats/ca.crt
Enter pass phrase for certificats/ca.key:# toto
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) [GB]:# FR
State or Province Name (full name) [Berkshire]:# L'île aux enfants
Locality Name (eg, city) [Newbury]:# Nuages
Organization Name (eg, company) [My Company Ltd]:# Casimir SARL
Organizational Unit Name (eg, section) []:# Entertainement
Common Name (eg, your name or your server's hostname) []:# www.casimir.fr
Email Address []:# casimir@casimir.fr
root#
création du certificat CA

Les informations rentrées ici n'ont que peut d'importance mais autant y mettre des choses justes. A ce stade, notre AC est complet, nous allons juste générer un fichier de plus, le "DER". C'est, comme nous l'avons vu, lui que nous allons fournir au clients (navigateur web entre autre) pour que la 3ième règle soit satisfaite et que le client ne couine plus pour tous les futurs certificats générés.

```génération du certificat utilisable par les clients.traces root# openssl x509 -in certificats/ca.crt -outform DER -out certificats/ca.der

Le fichier `ca.der` est le seul fichier que vous donnerez aux utilisateurs. Tout le reste doit être strictement privé !!

A ce stade notre pki est fonctionnelle, il ne nous reste plus qu'à générer notre premier certificat serveur.

## Génération d'un certificat

La procédure est assez simple. Dans la mesure où un certificat est lié à un nom de machine (par exemple le certificat https pour `www.casimir.fr`), j'ai pris le parti de donner ce nom aux fichiers générés (par exemple, `https.www.casimir.fr.crt` pour le certificat).

Pour avoir un certificat en règle, nous devons d'abord, comme pour l'AC, générer une clef. A la différence du AC, nous ne demandons pas de mot de passe.

```bash.traces

root# openssl genrsa -out certificats/https.www.casimir.fr.key 1024
Generating RSA private key, 1024 bit long modulus
............++++++
...........++++++
e is 65537 (0x10001)

L'étape suivante change un peu. Comme nous devons faire signer notre certificat, nous allons générer un ficher intermédiaire appelé CSR pour Certificate Signature Request (ou Demande de Signature de Certificat). Ce fichier contient déjà tout ce qu'un certificat contiendra sauf la signature du CA. C'est là qu'intervient notre tiers de confiance qui, en signant notre demande de certificat, nous permet d'obtenir en retour un certificat valide. La seule chose que nous devons donner comme information est le nom de la machine. C'est très important car sans cela, nous violerions la règle n°2 donnée plus haut. Dans notre exemple, lorsque openssl demandera YOUR name, vous répondrez www.casimir.fr, et ce n'est pas la peine de rajouter un mot de passe.

rootopenssl req -days 365 -new -key certificats/https.www.casimir.fr.key -out certificats/https.www.casimir.fr.csr
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) [GB]:# FR
State or Province Name (full name) [Berkshire]:# L'île aux enfants
Locality Name (eg, city) [Newbury]:# Nuages
Organization Name (eg, company) [My Company Ltd]:# Casimir SARL
Organizational Unit Name (eg, section) []:# Entertainement
Common Name (eg, your name or your server's hostname) []:# www.casimir.fr
Email Address []:# casimir@casimir.fr

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:#
An optional company name []:#
root#
Demande d'un nouveau certificat

Nous allons maintenant utiliser notre PKI et notre CA pour signer cette demande et obtenir notre certificat final :

rootopenssl ca -config config/ca.config -out https.www.casimir.fr.crt -infiles certificats/https.www.casimir.fr.csr
cats/https.www.casimir.fr.crt -infiles certificats/https.www.casimir.fr.csr
Using configuration fromconfig/ca.config
Enter pass phrase for /root/pki/certificats/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'FR'
stateOrProvinceName   :ASN.1 12:'L'\0xFFFFFFC3\0xFFFFFF83\0xFFFFFFC2\0xFFFFFFAEle aux enfants'
localityName          :PRINTABLE:'Nuages'
organizationName      :PRINTABLE:'Casimir SARL'
organizationalUnitName:PRINTABLE:'Entertainement&039;
commonName            :PRINTABLE:'www.casimir.fr'
emailAddress          :IA5STRING:'casimir@casimir.fr'
Certificate is to be certified until Mar 31 10:22:44 2017 GMT (3000 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
root#
Génération du certificat serveur

Voilà, vous avez maintenant un certificat tout neuf. Vous pouvez en vérifier le contenu par la commande :

rootopenssl x509 -text -in certificats/https.www.casimir.fr.crt
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=FR, ST=L'\xC3\x83\xC2\xAEle aux enfants, L=Nuages, O=Casimir SARL, OU=Entertainement, CN=http://www.casimir.fr/emailAddress=casimir@casimir.fr
Validity
Not Before: Jan 12 10:22:44 2009 GMT
Not After : Mar 31 10:22:44 2017 GMT
Subject: C=FR, ST=L'\xC3\x83\xC2\xAEle aux enfants, L=Nuages, O=Casimir SARL, OU=Entertainement, CN=www.casimir.fr/emailAddress=casimir@casimir.fr
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:a6:09:11:5b:9a:28:cf:b9:a0:0f:17:86:45:9b:
...
0d:0c:99:87:4a:5b:15:ef:ff
Exponent: 65537 (0x10001)
Signature Algorithm: md5WithRSAEncryption
2a:50:4a:3d:f2:a0:b7:68:1c:62:54:24:3f:13:81:be:db:20:
...
9d:18
-----BEGIN CERTIFICATE-----
MIICyjCCAjMCAQEwDQYJKoZIhvcNAQEEBQAwgbAxCzAJBgNVBAYTAkZSMR0wGwYD
...
bt6uImb9n7Xx9dqVUr5dd29E4fh0KKqBXWdWkStw73AP3snEo8xePf5bWladGA==
-----END CERTIFICATE-----
Vérification du certificat

Automatisation

Pour automatiser tout cela, vous pouvez utiliser ce script. La commande ./pki generate fabrique un dépôt en ~/.pki et ./pki generat génère des certificats. Lancez ./pki --help pour plus d'informations.

Installation des certificats

Une fois nos certificats générés, il ne nous reste plus qu'à déplacer les 3 fichiers là où ils seront utiles et de paramétrer Apache, Cyrus, ou tout autre système pour que cela fonctionne en SSL.

La bonne pratique dans le domaine semble vouloir que les certificats (.key, .csr et .crt) soient stockés dans le dossier /etc/ssl/{application}application est par exemple apache pour le web, cyrus pour l'imap, etc...

Installation du certificat de l'AC sur un client

L'idée générale est de fournir d'une manière ou d'une autre le fichier ca.der (et aucun autre !!) au client. Ensuite il y a autant de méthodes que de client.

Pour FireFox & Thunderbird

Aller dans edit/preferences, dans l'onglet Advanced, cliquer sur view certificates, puis aller sur l'onglet Authorities, cliquer sur Import. Aller chercher le fichier .der et validez. Cocher Trust this CA to identify web sites. Cocher aussi l'équivalent pour le mail pour thunderbird, puis valider. Le certificat CA devrait apparaître dans la liste. Faites OK pour sortir.

Pour Konqueror & KMail

Aller dans Configuration/Configurer Konqueror. Aller dans la section Cryptographie, dans l'onglet Signataires, cliquer sur import. Aller chercher le fichier .der et validez. Autorisez ou nom l'utilisation du certificat dans KMail puis valider pour sortir.

Pour IE 7

Aller dans Outils/Options Internet, Onglet contenu, cliquer sur Certificats. Aller dans l'onglet Autorités principales de confiance, et cliquer sur Importer... Suivre l'assistant et aller chercher le fichier .der (contrairement à ce qui est indiqué, il l'accepte...). Ceci fait valider.

Pour subversion

Placer le fichier ca.crt dans le dossier /etc/ssl/ca. Puis modifier le fichier /etc/subversion/servers comme suit :

ssl-authority-files = /etc/ssl/ca/ca.crt

Conclusion

Bien évidement cette technique ne remplacera pas une AC officielle et ne vous évitera pas, par exemple pour du commerce en ligne, de payer votre certificat. Mais dans pas mal de cas touchant de près ou de loin à l'intranet pour un nombre réduit d'utilisateurs, cette solution marche à merveille tout en étant simple à mettre en oeuvre.