HLab

Julien Hautefeuille

Créer une autorité de certification

Création d’une autorité de certification SSL

La création d’une autorité de certification est utile pour sécuriser des sites web intranet ou pour permettre à des clients de s’authentifier sur des serveurs.

Introduction

Une autorité de certification est une entité qui signe des certificats numériques. Généralement, on passe par des entités telles que VeriSign, DigiCert…

Mais il peut être parfois utile de créer sa propre autorité de certification pour des serveurs qui ne sont pas accessibles publiquement : serveurs intranet, clients OpenVPN.

Création d’une paire de clés racine

La première étape est de créer une paire de clés racine :

  • la clé racine ca.key.pem
  • le certificat racine ca.cert.pem

Le certicat d’autorité ne signe pas directement le certificat du serveur ou du client mais est utilisé pour créer un ou plusieurs certificats intermédiaires. Il existe donc une relation de confiance entre le certificat d’autorité et le certificat intermédiaire.

On utilisera ce certificat intermédiaire pour générer les certificats des serveurs. C’est une bonne pratique dans le sens où on peut préserver son aspect confidentiel.

Il est absolument indispensable de préserver la clé racine du certificat d’autorité.

Nous effectuerons toutes les étapes sous l’utilisateur root.

Préparation du répertoire de travail

Nous allons en premier lieu, créer l’arborescence du dossier de travail :

mkdir /root/ca
cd /root/ca
mkdir certs crl newcerts private
chmod 700 private
touch index.txt
echo 1000> serial

Les fichiers index.txt et serial permettent de garder, sous la forme d’une base de données, une trace des certificats signés.

Préparation du fichier de configuration

On crée un premier fichier /root/ca/openssl.cnf dont voici le contenu :

# OpenSSL root CA configuration file.
# Copy to `/root/ca/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir = /root/ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand

# The root key and root certificate.
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem

# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256

name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_strict

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256

# Extension to add when the -x509 option is used.
x509_extensions = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address

# Optionally, specify some defaults.
countryName_default = FR
stateOrProvinceName_default = France
localityName_default = Lille
0.organizationName_default = Inserm Lille
organizationalUnitName_default  = DRSI
emailAddress_default = drsi.lille@inserm.fr

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

Création de la clé racine

Cette clé est très importante et il est indispensable de la chiffrer avec une phrase de passe.

cd /root/ca
openssl genrsa -aes256 -out private/ca.key.pem 4096
chmod 400 private/ca.key.pem

Création du certificat racine

Il faut donner au certificat racine une date de validité importante car une fois cette date atteinte, les certificats en découlant deviennent invalides.

cd /root/ca
openssl req -config openssl.cnf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem
chmod 444 certs/ca.cert.pem

Vérification du certificat racine

openssl x509 -noout -text -in certs/ca.cert.pem

Création d’une paire de clés intermédiaires

Une autorité de certification intermédiaire permet de signer des certificats serveurs en adoptant le comportement de l’autorité de certification racine.

Le certificat intermédiaire est signé avec le certificat racine permettant ainsi de former une chaîne de confiance.

L’utilisation d’un certificat intermédiaire a un objectif de sécurité. Si la sécurité de la clé du certificat intermédiaire est compromise, il est toujours possible de révoquer la clé du certificat intermédiare à l’aide du certificat racine et de créer un nouveau certificat intermédiaire.

Préparation du dossier de travail

mkdir /root/ca/intermediate
# cd /root/ca/intermediate
mkdir certs crl csr newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial

On ajoute un fichier crlnumber pour garder une trace des certificats révoqués.

echo 1000 > /root/ca/intermediate/crlnumber

Préparation du fichier de configuration

On crée un fichier /root/ca/intermediate/openssl.cnf dont voici le contenu :

# OpenSSL intermediate CA configuration file.
# Copy to `/root/ca/intermediate/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir = /root/ca/intermediate
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand

# The root key and root certificate.
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem

# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl.pem
crl_extensions = crl_ext
default_crl_days = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256

name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256

# Extension to add when the -x509 option is used.
x509_extensions = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address

# Optionally, specify some defaults.
countryName_default = FR
stateOrProvinceName_default = France
localityName_default = Lille
0.organizationName_default = Inserm Lille
organizationalUnitName_default = DRSI
emailAddress_default = drsi.lille@inserm.fr

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

Création de la clé intermédiaire

Attention durant cette étape à choisir un Common Name différent de celui du certificat racine.

cd /root/ca
openssl req -config intermediate/openssl.cnf -new -sha256 -key intermediate/private/intermediate.key.pem -out intermediate/csr/intermediate.csr.pem

Pour créer le certificat intermédiaire, il faut utiliser le certificat racine avec l’extension v3_intermediate_ca pour signer le CSR intermédiaire.

Le certificat intermédiaire devrait avoir une période de validité plus courte que celle du certificat racine.

cd /root/ca
openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.cert.pem
chmod 444 intermediate/certs/intermediate.cert.pem

Vérification du certificat intermédiaire

openssl x509 -noout -text -in intermediate/certs/intermediate.cert.pem

Et sa correspondance avec le certificat racine :

openssl verify -CAfile certs/ca.cert.pem intermediate/certs/intermediate.cert.pem

Création du fichier de la chaîne de certification

Quand une application essaye de vérifier un certificat signé par le certificat intermédiaire, il doit aussi vérifier la correspondance avec le certificat racine. Pour assurer cette chaîne de confiance, il faut créer un fichier de chaîne de certification.

Pour créer cette chaîne de certificat, il faut concaténer les certificats intermédiaires et racines ensemble.

cat intermediate/certs/intermediate.cert.pem certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem

C’est généralement ce certificat d’autorité que l’on installe sur les navigateurs.

Certificats signés pour serveurs et clients

Nous allons à présent générer des certificats pour des serveurs et clients en nous basant sur le certificat intermédiaire.

Création de la clé

Pour des serveurs comme Apache, Nginx (sans mot de passe) :

cd /root/ca
openssl genrsa -out intermediate/private/intranet.dr-lille.local.key.pem 2048
chmod 400 intermediate/private/intranet.dr-lille.local.key.pem

Pour des clients comme OpenVPN (avec mot de passe) :

cd /root/ca
openssl genrsa -aes256 -out intermediate/private/client1.dr-lille.local.key.pem 2048
chmod 400 intermediate/private/client1.dr-lille.local.key.pem

Création du certificat

Attention, ici le Common Name doit être un nom de domaine pleinement qualifié et doit être différent de ceux choisis pour les certificats racine et intérmédiaire.

On crée d’abord le CSR (Certificate Signing Request) :

cd /root/ca
openssl req -config intermediate/openssl.cnf -key intermediate/private/intranet.dr-lille.local.key.pem -new -sha256 -out intermediate/csr/intranet.dr-lille.local.csr.pem

Puis on crée le certificat.

Pour un serveur, on utilise l’extension server_cert et pour un client usr_cert. On donne une validité d’un an au certificat du serveur.

cd /root/ca
openssl ca -config intermediate/openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in intermediate/csr/intranet.dr-lille.local.csr.pem -out intermediate/certs/intranet.dr-lille.local.cert.pem
chmod 444 intermediate/certs/intranet.dr-lille.local.cert.pem

Vérification du certificat

openssl x509 -noout -text -in intermediate/certs/intranet.dr-lille.local.cert.pem

On vérifie aussi le certificat et sa correspondance avec la chaîne de certification :

openssl verify -CAfile intermediate/certs/ca-chain.cert.pem intermediate/certs/intranet.dr-lille.local.cert.pem

Déploiement du certificat

Pour déployer les certificats sur un serveur, les fichiers suivants sont né&cessaires :

  • ca-chain.cert.pem
  • intranet.dr-lille.local.key.pem
  • intranet.dr-lille.local.cert.pem

Liste de révocation des certificats

Une liste des certificats révoqués (CRL) doit être accessible par une url telle que :

http://example.com/intermediate.crl.pem

Préparation du fichier de configuration

On ajoute dans la section du fichier openssl.cnf (CA intermédiaire) précédent la directive :

[ server_cert ]
# ... snipped ...
crlDistributionPoints = URI:http://example.com/intermediate.crl.pem

On crée la CRL

cd /root/ca
openssl ca -config intermediate/openssl.cnf -gencrl -out intermediate/crl/intermediate.crl.pem

Vérification de la CRL

openssl crl -in intermediate/crl/intermediate.crl.pem -noout -text

Révoquer le certificat

cd /root/ca
openssl ca -config intermediate/openssl.cnf -revoke intermediate/certs/intranet.dr-lille.local.cert.pem

https://jamielinux.com/docs/openssl-certificate-authority/index.html