Pour sécuriser une connexion web en utilisant le protocole https, il faut un certificat.
Nous allons voir comment les générer sans trop de fatigue !
Recommandations
L’ANSSI déconseille fortement de générer des certificats sur un serveur fraîchement installé ou pire sur une machine virtuelle, car il n’y a pas suffisamment d’entropie. cf p8/21 Anssi – Note technique Recommandations pour un usage sécurisé d’OpenSSH
Quelques règles permettent de s’assurer que le réservoir d’entropie est correctement rempli :
- la machine de génération de clés doit être une machine physique ;
- elle doit disposer de plusieurs sources d’entropie indépendantes ;
- l’aléa ne doit être obtenu qu’après une période d’activité suffisamment importante (plusieurs minutes voire heures).
Il parait donc nécessaire de générer les clefs et certificats sur son poste de travail, qui a de nombreuses applications en service, générant de l’entropie.
L’autorité de certification
Il est possible de faire signer ses certificats par une autorité de certification, qui vous facturera l’opération.
Sinon il est possible de créer sa propre autorité de certification.
Nous allons donc créer le certificat et la clef privée de notre autorité. Ceci servira ensuite à signer les certificats des serveurs et des utilisateurs.
Création du fichier de configuration
Ce fichier servira pour définir les paramètres de configuration lors de la génération des certificats/clefs, dans la suite il sera nommé « openssl.cnf ».
[ req ] default_md = sha1 distinguished_name = req_distinguished_name [ req_distinguished_name ] countryName = Country countryName_default = FR countryName_min = 2 countryName_max = 2 localityName = Locality localityName_default = xxxx #Ville à renseigner organizationName = Organization organizationName_default = xxxx #Nom de votre organisation ou votre nom organizationalUnitName = Organization Unit organizationalUnitName_default = xxxx #Même info que pour organizationName commonName = Common Name commonName_max = 64 emailAddress = E-mail address #Facultatif [ certauth ] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always basicConstraints = CA:true crlDistributionPoints = @crl [ server ] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth nsCertType = server crlDistributionPoints = @crl [ client ] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment, dataEncipherment extendedKeyUsage = clientAuth nsCertType = client crlDistributionPoints = @crl [ crl ] URI=http://serveur/ca.crl #Certificat Revocation List, c'est donc la liste des certificats que vous avez émis et révoqués (car expirés, perdus, volés ...) Il faudrait donc mettre une adresse valide
Création du certificat de l’autorité de certification
Si vous voulez faire signer vos certificats par une autorité officielle, vous pouvez passer cette étape.
Nous retrouvons la référence au fichier openssl.cnf, la clef est en RSA, j’ai choisi 4096, mais généralement 2048 est utilisé, la durée de validité est de 10 ans.
Concernant la durée, il s’agit de celle de notre autorité de certification, elle doit être assez longue, contrairement à celle des serveurs et/ou des utilisateurs.
openssl req -config ./openssl.cnf -newkey rsa:4096 -nodes -keyform PEM -keyout ca.key -x509 -days 3652 -extensions certauth -outform PEM -out ca.cer
Il faut donc renseigner les différents champs, si vous avez renseigné les différentes valeurs default dans openssl.cnf, vous n’avez presque qu’à appuyer sur entrée.
Vous obtenez donc deux fichiers :
- ca.cer le certificat de l’autorité de certification
- ca.key la clef privée de l’autorité de certification
Création du certificat d’un serveur
Si vous souhaitez signer vos certificats via votre propre autorité de certification, voici comment procéder.
J’ai encore mis 4096 bits pour la clef privée. La durée du certificat serveur a été fixée à 3 ans.
Lors de la génération de la demande de signature, dans le champs Common Name il faut renseigner le domaine auquel sera associé le certificat (sans le protocole « https:// »).
J’ai complexifié le script suivant afin d’ajouter quelques fonctionnalités, telles que :
- la saisie du nom du certificat et de la clef générée (c’est plus pratique lorsque l’on fait de la série),
- la gestion automatique du serial number.
Lorsque l’on signe des certificats avec notre propre autorité, ils doivent avoir des serial numbers différents, sinon c’est le chaos et le navigateur web bloque les sites en question.
J’assigne donc un serial via la directive -set_serial. Le calcul de la valeur est fait de la façon suivant :
- on récupère le temps unix en seconde,
- on récupère le dernier « numéro d’ordre » de certificat généré,
- on les multiplie.
De cette façon, il on a des serial numbers très différents et il est impossible qu’il y ait deux valeurs identiques.
Il y donc deux fichiers générés qu’il faut conserver :
- serial.last, qui contient seulement le numéro d’ordre du dernier certificat généré, c’est un compteur,
- history.log, qui permet de garder une trace des générations effectuées.
#!/bin/bash echo "Veuillez renseigner le nom des certificats :" read file serial=$(more serial.last) unixTime=$(date +"%s") echo "#####################################" echo "#Nombre de certificats générés précédemment : $serial" echo "#Le temps unix : $unixTime" serial=$((serial+1)) serialNumber=$((unixTime*(serial))) echo "#Le serial number est de : $serialNumber" echo "#####################################" echo "Génération d'un certificat pour le serveur" echo "Génération de la clé privée" openssl genrsa -out $file.key 4096 echo "Génération de la demande de signature" openssl req -config ./openssl.cnf -new -key $file.key -out $file.req echo "Génération du certificat avec notre autorité de certification" openssl x509 -req -in $file.req -CA ca.cer -CAkey ca.key -extfile openssl.cnf -extensions server -days 1096 -outform PEM -out $file.cer -set_serial $serialNumber echo "Suppression de la requête de signature" rm $file.req echo $serial > serial.last echo $serial "-" $file >> history.log
Ce qui donne ceci :
Veuillez renseigner le nom du fichier : mon_site_securise ##################################### #Nombre de certificats générés précédemment : 47 #Le temps unix : 1483818039 #Le serial number est de : 69739447833 ##################################### Génération d'un certificat pour le serveur Génération de la clé privée Generating RSA private key, 4096 bit long modulus .................++ .................................................................++ e is 65537 (0x10001) Génération de la demande de signature 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 [FR]: Locality [xxx]: Organization [xxx]: Organization Unit [xxx]: Common Name : serveur.com E-mail address : webmaster@serveur.com Génération du certificat avec notre autorité de certification Signature ok subject=/C=FR/L=Ville/O=Organisation/OU=Organisation/CN=serveur.com/emailAddress=webmaster@serveur.com Getting CA Private Key
Nous obtenons donc :
- mon_site_securise.cer le certificat du serveur
- mon_site_securise.key la clef privée du serveur
En revanche, si vous souhaitez faire signer vos certificats par une autorité de certification, il y a quelques différences.
En effet, il ne faut plus générer le certificat, et il faut absolument garder le fichier de requête, qui devra être envoyé à l’autorité de certification.
echo "Génération d'un certificat pour le serveur" echo "Génération de la clé privée" openssl genrsa -out server.key 4096 echo "Génération de la demande de sigServernature" openssl req -config ./openssl.cnf -new -key server.key -out server.req
Afin de vérifier que le certificat est le correct et qu’il n’y a pas de vulnérabilités, j’ai trouvé un site très utile : digicert il est gratuit et plutôt réactif.
Création du certificat d’un utilisateur
Fichier de génération des certificats utilisateurs
#!/bin/bash FILE="client" SERIAL=200 if [ "$1" != "" ]; then FILE="$1" fi if [ "$2" != "" ]; then SERIAL="$2" fi echo "Génération d'un certificat pouServerr le client : $FILE" echo "Génération de la clé privée" openssl genrsa -out "${FILE}.key" 4096 echo "Génération de la demande de signature" openssl req -config ./openssl.cnf -new -key "${FILE}.key" -out "${FILE}.req" echo "Génération du certificat avec notre autorité de certification" openssl x509 -req -in "${FILE}.req" -CA ca.cer -CAkey ca.key -set_serial ${SERIAL} -extfile openssl.cnf -extensions client -days 365 -outform PEM -out "${FILE}.cer" echo "Génération du certificat au format PKCS#12" openssl pkcs12 -export -inkey "${FILE}.key" -in "${FILE}.cer" -out "${FILE}.p12" echo "Suppression de la requête de signature" rm "${FILE}.req" "${FILE}.key" "${FILE}.cer"
Nous allons générer un certificat pour un utilisateur.
Dans le champs Common Name, il faut renseigner vos noms et prénoms, il est aussi intéressant de renseigner l’adresse e-mail dans le champ prévu.
Cette fois-ci, nous obtenons qu’un seul fichier : client.p12, qui pourra être importé dans le navigateur.
Voici des commandes permettant de lire certificat & clef
openssl x509 -in certificate.cer -text -noout openssl rsa -in fr_rmaziere_cloud.key -check
Remerciement :
Un grand merci à notre formateur de l’ANSSI venu nous sensibiliser à la sécurité informatique lors de la semaine dernière à l’ENSG.