Certificats

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 :

  1. on récupère le temps unix en seconde,
  2. on récupère le dernier « numéro d’ordre » de certificat généré,
  3. 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.

2 Responses to Certificats

  1. Pingback: Serveur/LAMP | Je bricole

  2. Pingback: Let’s encrypt ou la signature OpenSource de certificats | Je bricole

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *