sebastien-dupire.info

Dev, gribouillages et bidouilleries ...

sam. 14 décembre 2019

L'enfer des certificats

Posted by Sébastien Dupire in Développement   

Je ne sais pas pour vous mais comme j'installe des keystores/trustores/certificats qu'une fois par projet, j'ai tendance à renseigner chaque README.md de chaque projet pour me rappeler les commandes principales afin de créer les clefs et les certificats nécessaires.

Mon cerveau ne retient jamais les commandes quand elles sont espacées de plusieurs mois. C'est un peu l'effet téléphone portable : on sait globalement où trouver l'information, du coup, on ne la mémorise plus.

Je vais tenter via cet article de faire mes derniers copier/coller sur le sujet.

Utilisation de quelques commandes keytool

Commençons par la création d'un keystore.

keytool -genkey \
    -alias <mykeyalias> \ 
    -keyalg RSA \
    -keysize 4096 \ 
    -keystore <mykeystore.extension> \ 
    -dname "CN=www.mydomain.dom, OU=INTERNAL, O=ETAT, L=FRANCE, ST=METZ, C=FR" \ 
    -ext san=dns:site.mydomain.dom,dns:perso.mydomain.dom \ 
    -validity 3600

C'est quoi un keystore ? Un magasin de clef ... oui, c'est un container de clef privée/publique et de certificats. Une sorte de fourre-tout dans lequel vous pouvez associer les types d'objets cités précédemment autour d'un alias. Bien entendu, vous pouvez créer autant d'alias que vous voulez.

La commande ci-dessus vous permet de créer autour d'un alias nommé <mykeyalias> dans un keystore nommé <mykeystore.extension>:

  • une paire de clef privée/publique de type RSA taille 4096,

  • un certificat x509 valide de 10 ans lié à la clef publique.

Ici, je n'ai pas précisé le type de keystore voulu. Généralement, on en trouve de deux types:

  • le JKS (extension .jks) : Java Keystore, propre à Oracle, propriétaire et qui s'utilise très bien avec le langage Java. Par contre, dans d'autres languages, c'est compliqué (je pense aussi d'un point de vue licence).

  • le PKCS12 (extension .p12) : Public-Key Cryptography Standards 12, un format créé par les laboratoires RSA. Ils sont désormais tombés dans le domaine public.

Bien entendu, il existe des outils pour convertir dans les deux formats. Keytool fourni avec le JDK est le plus couramment utilisé.

Si à partir de notre clef privée, on veut faire un certificat signée par une CA (Certificate Authority), quelle soit issue d'un tiers de confiance ou d'une CA interne, on peut utiliser la commande suivante pour créer une CSR (Certificate Signing Request).

keytool -certreq \
    -alias <mykeyalias> \
    -keyalg RSA \
    –keystore <mykeystore.extension> \ 
    -file /tmp/mydomain.csr

Ici, on demande à créer la CSR en allant chercher la clef privée dans l'alias <mykeyalias> du keystore <mykeystore.extension>

Une fois envoyé à la CA de votre choix, elle va vous fournir en échange un certificat x509 signé, bien souvent au format .crt. Il vous suffira alors de le placer dans un nouvel alias de votre keystore.

keytool -importcert \
    -alias <mycertificatalias> \
    -keyalg RSA \
    -keystore <mykeystore> \
    -trustcacerts \
    -file <path_to_pem_cert>

On aurait pu très bien mettre ça dans un truststore. Hein ? Quoi ? C'est quoi ? C'est juste un keystore mais qui ne contient que des certificats afin de truster des clefs publiques dans un container.

Plus simple avec OpenSSL

Il est possible de faire le même type d'opération avec OpenSSL

$ openssl \
    req \
    -nodes \
    -newkey rsa:4096 \
    -keyout mon.putain.de.site.com.key \
    -out mon.putain.de.site.com.csr \
    -subj "/C=DE/ST=NRW/L=Berlin/O=My Inc/OU=DevOps/CN=mon.putain.de.site.com/emailAddress=dev@mon.putain.de.site.com"

La commande vient de créer une clef privée, et la CSR qui va bien.

Si vous avez des sites à créer/publier et que vous voulez gérer la création de CSR et de certificats auto-signés, OpenSSL permet de passer par un fichier de configuration.

Commençons par créer un fichier de configuration mon.putain.de.site.com.conf

[req]
default_bits       = 4096
default_keyfile    = mon.putain.de.site.com.key
distinguished_name = req_distinguished_name
req_extensions     = req_ext
x509_extensions    = v3_ca

[req_distinguished_name]
countryName                 = Country Name (2 letter code)
countryName_default         = FR
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = New York
localityName                = Locality Name (eg, city)
localityName_default        = Rochester
organizationName            = Organization Name (eg, company)
organizationName_default    = mon.putain.de.site.com
organizationalUnitName      = mon.putain.de.site.com
organizationalUnitName_default = Development
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_default          = mon.putain.de.site.com
commonName_max              = 64

[req_ext]
subjectAltName = @alt_names

[v3_ca]
subjectAltName = @alt_names

[alt_names]
DNS.1   = localhost
DNS.2   = 127.0.0.1
DNS.3   = mon.putain.de.site.com

Il suffit donc d'utiliser openssl pour générer la clef privée et une CSR.

$ openssl \
    req \
    -nodes \
    -new \
    -config mon.putain.de.site.com.conf \
    -keyout mon.putain.de.site.com.key \
    -out mon.putain.de.site.com.csr

ou alors directement pour générer la clef privée et le certificat auto-signé

$ openssl \
    req \
    -x509 \
    -nodes \
    -days 365 \ 
    -newkey rsa:4096 \
    -keyout mon.putain.de.site.com.key \
    -out mon.putain.de.site.com.crt \
    -config mon.putain.de.site.com.conf

Du coup, pour configurer un nginx facilement, il n'y a plus qu'à renseigner les bonnes options

server {
    listen 443 ssl;
    server_name mon.putain.de.site.com;

    ssl_certificate mon.putain.de.site.com.crt;
    ssl_certificate_key mon.putain.de.site.com.key;
    ...

Et c'est tout.

Je ne détaille pas le fonctionnement des clefs privées/publiques, les certificats x509 ou les algorithmes à utiliser aujourd'hui. Cela fera l'objet d'un post à part entière.

Références


Vous voulez partager cet article ? Rien de plus facile !
Le copier-coller est votre ami. Il suffit pour cela de copier l'URL de votre browser et de le coller dans votre réseau social préféré.
Vous ne vouliez quand même pas un bouton pour faire une tâche aussi simple, non ?