Une autorité de certification ou mini PKI à la maison avec openssl

Pourquoi faire ? Pour délivrer vos propres certificats TLS et clients. Distribuer vos propres certificats pour votre famille, vos proches pour se connecter à vos sites web ou votre réseau. C’est un moyen d’authentification sur et sans mot de passe.

Le présent article vise à proposer le strict minimum pour ces deux usages.

Vous pouvez aussi lire ce tutoriel de Stefan H. Holek. Il propose des implémentations avec des AC intermédiaires ce qui est superflu pour un usage domestique.

Commençons par un peu théorie

Quoique vous pouvez passer ce chapitre et revenir dessus ultérieurement.

Un certificat est une carte d’identité. L’autorité de certification (AC) est l’autorité qui les délivre. Les serveurs web et les navigateurs, à partir de la connaissance de l’AC, savent vérifier un certificat et que celui qui le présente est le détenteur légitime.

De quoi est composé un certificat ?

  • une identité ou un nom,
  • la clé publique,
  • une période de validité
  • la signature du certificat,
  • des usages

L’ identité ou objet sous la forme d’un « distinguished name » (DN) : généralement représenté /C=FR/O=<Société>/OU=<valeur Libre>/L=<Ville>/CN=<nom de personne ou de serveur>. Où C signifie country (pays), O organization (organisation), OU unité organisationnelle (organizational unit), L locality (ville), CN Common Name (nom).

La clé publique est associée à une clé privée. Ces deux clés sont générées en même temps, intimement liées  et obtenues à l’aide d’un algorithme cryptographique asymétrique tel que RSA. Si on chiffre avec une des clés, on doit déchiffrer avec l’autre. Si elles sont suffisamment longue (ex 2048 bits), il n’est pas possible d’obtenir, dans un temps raisonnable, la clé privée à partir de la clé publique. La clé privée doit être jalousement protégée.

La période de validité débute généralement à l’émission du certificat et dure quelques années. Dans notre cas c’est d’assez peu d’importance.

La signature du certificat est le truc qui permet de valider l’origine du certificat. Il est obtenu par le chiffrement du condensat du certificat par la clé privée de l’AC.

Les algorithmes (ex SHA-2)  qui génère les condensats (hash) sont des fonctions à sens unique. Il n’est pas possible dans un temps raisonnable de construire un message à partir d’un condensat. SHA-1 n’est plus sur. Des spécialistes l’ont récemment démontré.

Optionnellement, on peut préciser les usages (authentification, signature, chiffrement,..)

Qu’allons nous faire ?

Dans l’ordre nous allons :

  • fabriquer la mairie qui va délivrer les cartes d’identité : générer l’autorité de certification,
  • créer une première demande de carte d’identité : une requête de certification ou CSR,
  • valider la demande et créer la première carte d’identité : signer la requête de certification,
  • ranger la nouvelle carte dans son portefeuille : stocker l’AC et le certificat dans son magasin sur votre machine.

Que vous faut-il ?

Du point de vue minimaliste, il ne vous faut qu’un ordinateur avec une librairie openssl et quelques dizaines de Ko de disponibles sur le disque.

La clé privée de votre future AC est la clé de voûte de l’ensemble. Si un tiers malintentionné s’en empare, l’édifice s’écroule. Partant du principe qu’un ordinateur sur est un ordinateur éteint, vous pouvez dédié une petite VM à votre AC que vous allumez pour l’occasion. Sinon, un compte dédié fera l’affaire.

Dans l’exemple ci-dessous, je vais partir d’une distribution debian. Sur la distribution que j’ai utilisée, le package openssl est déjà installé.

Préparer l’environnement

Création de l’utilisateur ac

Je crée mon utilisateur ac. Sous root :

root@deby:~# adduser ac
Ajout de l'utilisateur « ac » ...
Ajout du nouveau groupe « ac » (1001) ...
Ajout du nouvel utilisateur « ac » (1001) avec le groupe « ac » ...
Entrez le nouveau mot de passe UNIX :
Retapez le nouveau mot de passe UNIX :
passwd : le mot de passe a été mis à jour avec succès
Modification des informations relatives à l'utilisateur ac
Entrez la nouvelle valeur ou « Entrée » pour conserver la valeur proposée
 Nom complet []: Autorite de certification
 N° de bureau []:
 Téléphone professionnel []:
 Téléphone personnel []:
 Autre []:
Cette information est-elle correcte ? [O/n]O

Je me connecte sous ac. Le umask est à 022 par défaut tous les utilisateurs et ceux du groupe ac peuvent lire les fichiers que l’utilisateur ac crée. Pas top du point de sécurité. j’édite (avec vi, emacs ou nano) le fichier .profile. Je dé-commente la ligne umask et change la valeur :

umask 077

Je recharge le .profile, puis je teste :

ac@deby:~$ . .profile
ac@deby:~$ umask
0077
ac@deby:~$ touch toto
ac@deby:~$ ls -l toto
-rw------- 1 ac ac 0 mai 5 22:50 toto
ac@deby:~$ rm toto
ac@deby:~$

création du fichier de configuration pour openssl

Il en existe un modèle sous /etc/ssl. J’en faite une copie.

ac@deby:~$ cp /etc/ssl/openssl.cnf monac.cnf

La section CA_default définit notre autorité de certification. Ce que j’y ai changé :

dir             = /home/ac
...
unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
...
# Extension copying option: use with caution.
copy_extensions = copy
... default_days = 1096 # how long to certify for default_crl_days= 366 # how long before next CRL default_md = SHA256 # use public key default MD ... policy          = policy_anything

dir  est le répertoire de base.

unique_subject = no permet d’avoir plusieurs certificat du même nom.

copy_extensions = copy va recopier les extensions de la requête dans le certificat (utile pour les certificats serveurs).

default_days est la durée de validité du certificat, je propose 3 ans.

default_crl_days est la durée de validité de la CRL

default_md positionné à SHA256 est l’algorithme de condensat SHA-2 à 256 bits (c’est l’usage).

policy : les contraintes imposées sur les différents champs du certificat. Ici seul le ‘Common name’ est requis et l’adresse e-mail est optionnel.

La CRL est la liste des certificats révoqués identifiés par leurs numéros de série, signée par l’autorité de certification. Dans le cas où une clé privée d’un certificat est compromise, il convient de le déclarer inutilisable. Pour une utilisation domestique, je conseille de ne pas utiliser la révocation, mais plutôt de ne plus attribuer de droit à un certificat douteux. Pour le malheureux ou l’imprudent dont la clé privée est compromise, je conseille de lui en re-générer un autre avec un nom différent.

Dans la section policy_anything je commente les champs non-désiré et elle devient :

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

Dans la section req, je commente la ligne des attributs et extensions :

#attributes = req_attributes
 = v3_ca # The extentions to add to the self signed cert

Dans la section v3_ca (elle ne servira que pour la création de l’autorité) je décommente keyUsage

[ v3_ca ]

...

keyUsage = cRLSign, keyCertSign

J’aligne la section req_distinguided_name , je modifie les valeurs par défaut

[ req_distinguished_name ]

[ 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 = Some-State

localityName = Locality Name (eg, city)

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

# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

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


commonName = Common Name (e.g. server FQDN or YOUR name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64

Dans la section usr_cert,  je décommente la ligne KeyUsage et ajoute une ligne ExtendedKeyUsage

# This is typical in keyUsage for a client certificate.
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
ExtendedKeyUsage = serverauth, clientauth, emailprotection

J’en ai terminé avec le fichier de configuration, on sauvegarde et on sort. Le résultat est .

Dans la section ac, plusieurs répertoires et fichiers sont référencés. Il faut les créer.

ac@deby:~$ mkdir certs
ac@deby:~$ mkdir crl
ac@deby:~$ touch index.txt
ac@deby:~$ mkdir newcerts
ac@deby:~$ echo 00 > serial
ac@deby:~$ echo 00 > crlnumber
ac@deby:~$ mkdir private

Générer l’autorité de certification

Cela se passe en trois étape. Je commence par générer le secret du tampon magique, je crée mon dossier de demande de validation de mon tampon et je me l’auto-valide. C’est qui le chef ?

Je pense très fort à un mot de passe compliqué (mdp-ca par la suite) qui va protéger la clé privée de mon AC. Ce mot de passe ne doit pas être oublié, il sera demandé à chaque fois que je signerai un certificat. Je demande à générer une bi-clé chiffrée en AES 256, d’une longueur de 2048 bits stockées dans le fichier private/cakey.pem.

ac@deby:~$ openssl genrsa -aes256 -out private/cakey.pem 2048
Generating RSA private key, 2048 bit long modulus
..........+++
............................+++
e is 65537 (0x10001)
Enter pass phrase for private/cakey.pem:
Verifying - Enter pass phrase for private/cakey.pem:

En fait c’est un fichier texte, vous pouvez regarder :

ac@deby:~$ cat private/cakey.pem
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,48169FC778C3D541B1297B4D7E078FB5

/XCoh/N8K+mdrud53f7Rue8YC1YzMSwSDIRNc0konlNh2l5U0W1+I/BVoWjzQAF8
rdqIYVIhlL3QdwvZyAvn4FEX8FhRDXWpOHlyD0WrZQfaj81NyHZ4M3IvNdMNRCpu
...
4Mi9lwn2StNPg82kDLf5cyxv9V5taep59TP4xkmHGaCosEASNfe7iDL4KTQbrMk1
-----END RSA PRIVATE KEY-----

Je crée le certificat autosigné de mon autorité de certification :

ac@deby:~$ openssl req -x509 -subj '/C=FR/O=A la maison/L=Ma ville/CN=AC Maison' -key private/cakey.pem -days 10958 -extensions v3_ca -config monac.cnf -out cacert.pem
Enter pass phrase for private/cakey.pem:

Explication des options

-x509 : fabrique un certificat autosigné
-subj : l'objet de mon certificat
-key : la clé du certificat
-days : durée de validité de mon autorité de certification (30ans)
-extensions : ajoute les extensions nécessaires à l'autorité de certification
-config : pour lire notre fichier de configuration

Je peux relire le certificat :

ac@deby:~$ openssl x509 -noout -in cacert.pem -text

Générer un certificat

Pour générer un certificat, je déroule des étapes identiques : je génère les secrets, je créé mon dossier et la mairie le valide.

Le mot de passe protégeant la bi-clé sera appelé par la suite (mdp-user1)

ac@deby:~$ openssl genrsa -aes256 -out certs/user1.key 2048
Generating RSA private key, 2048 bit long modulus
.......................................................+++
..........+++
e is 65537 (0x10001)
Enter pass phrase for certs/user1.key:
Verifying - Enter pass phrase for certs/user1.key:

Je crée la requête de certification, avec mdp-user1 :

ac@deby:~$ openssl req -new -config monac.cnf -key certs/user1.key -out certs/user1.csr
Enter pass phrase for certs/user1.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) []:
Locality Name (eg, city) []:
Organization Name (eg, company) [Maison]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:Mon premier utilisateur
Email Address []:u1@alamaison.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Je signe la requête avec l'AC (mdp-ca)
ac@deby:~$ openssl ca -in certs/user1.csr -out certs/user1.cert -config monac.cnf
Using configuration from monac.cnf
Enter pass phrase for /home/ac/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 0 (0x0)
Validity
Not Before: Aug 5 13:26:15 2019 GMT
Not After : Aug 5 13:26:15 2022 GMT
Subject:
countryName = FR
organizationName = Maison
commonName = Mon premier utilisateur
emailAddress = u1@alamaison.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
DD:46:F8:B0:50:75:15:C0:75:95:E9:7D:B4:80:44:DD:4F:10:64:52
X509v3 Authority Key Identifier:
keyid:4B:73:88:4E:41:8D:79:11:87:2E:3D:B0:10:03:FC:F7:34:13:E2:8A

Certificate is to be certified until Aug 5 13:26:15 2022 GMT (1096 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

Et là je note que le fichier serial a été incrémenté et que le fichier index.txt a été mis à jour.

La dernière étape consiste à rassembler les différents éléments nécessaires à un utilisateur en un seul fichier au format PKCS#12, en utilisant mdp-user1. Le nouveau mot de passe créé devra être transmis à l’utilisateur avec le fichier p12.

ac@deby:~$ openssl pkcs12 -export -inkey certs/user1.key -in certs/user1.cert -certfile cacert.pem -out certs/user1.p12
Enter pass phrase for certs/user1.key:
Enter Export Password:
Verifying - Enter Export Password:

Intégration du certificat à votre navigateur

Sur Chromium sous linux, je clique sur les trois petits points en haut à droite, je vais dans settings. Puis, je clique sur « advanced settings », là un bouton « manage certificates… » apparaît. Après avoir cliquer sur ce bouton, une fenêtre s’ouvre, je clique sur « import… », je sélection mon fichier .p12 (user1.p12) , le mot de passe à saisir est celui généré lors de l’export. Je viens d’importer mon certificat et celui de l’autorité de certification.

Copie écran certificat client copie d'écran AC

Sous windows, il suffit de double-cliquer sur le fichier .p12 pour l’importer. Sous iOS, le toucher suffit.

Usage pour un certificat serveur

Certains navigateurs demandent à ce que le nom du serveur soit dans le champ SubJectAltName. Je n’ai pas trouvé comment recopier automatiquementle champ common name dans le champ SubjectAltName. Je propose de le positionner dans la requête avec l’option -addext « SubjectAltName=DNS:<NomServeur> ».

Exécuter la commande suivante sur votre serveur web.

marc@t2:~$ openssl req -newkey rsa:2048 -out t2.home.csr -keyout t2.home.key -subj "/C=FR/O=Maison/CN=t2.home" -addext "subjectAltName=DNS:t2.home"
Generating a RSA private key
..................................................................+++++
...................................................................+++++
writing new private key to 't2.home.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----

Sur la machine avec l’autorité de certification :

ac@deby:~$ openssl ca -in certs/t2.home.csr -out certs/t2.home.cert -config monac.cnf
Using configuration from monac.cnf
Enter pass phrase for /home/ac/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Aug 5 13:57:38 2019 GMT
Not After : Aug 5 13:57:38 2022 GMT
Subject:
countryName = FR
organizationName = Maison
commonName = t2.home
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication, E-mail Protection
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
15:A5:07:EA:39:1D:8E:A6:87:5F:BC:BD:0F:4F:90:71:E4:44:1D:7D
X509v3 Authority Key Identifier:
keyid:4B:73:88:4E:41:8D:79:11:87:2E:3D:B0:10:03:FC:F7:34:13:E2:8A

X509v3 Subject Alternative Name:
DNS:t2.home
Certificate is to be certified until Aug 5 13:57:38 2022 GMT (1096 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

Pour supprimer le mot de passe de la clé privée :

marc@t2:~$ openssl pkey -in t2.home.key -out t2.home.sans-mot-de-passe.key

Mise à jour le 5 août 2019 :

– ajout des extensions x509,

– usage pour un serveur.

Laisser un commentaire

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