Concepts généraux
Les certificats sont basés sur le principe de la cryptographie asymétrique.
Généralement, lorsqu’on parle de certificat, on parle de certificat x509. Mais il existe d’autre technologie de certificat, e.g. une clé gpg publique peut être considéré comme un certificat. Dans la suite de cette article je ne parle que de certificat x509.
Un certificat est composé d’une clé publique, de données et d’une signature portant sur les deux éléments précédent (un hash des éléments en vérité). À chaque certificat est donc associé une clé privé. Attention, la clé privé n’est pas inclue dans le certificat, c’est un fichier séparé et secret qui est conservé par l’entité ayant émit le « Certificat Signing Request » (CSR) à l’origine du certificat. Seul la clé publique correspondant à cette clé privé est inclue dans le certificat.
Les données contenu dans le certificat inclue les informations généralement indiquées à la création d’un certificat :
- Subject
- Common Name
- Organisation
- Country
- …
- Subject Alt Name
- …
Il existe plusieurs type de certificats, pour serveurs web, pour serveur xmpp, des certificats clients pour s’authentifier. Ce qui différenti ces certificat c’est le type de données (attributs) qu’il contient. Le « Subject » est un attribut définissant l’élément validé par le certificat, le « Issuer » définit l’entité ayant délivré (signé) le certificat, il correspond au « Subject » du certificat dont la clé privé à servit à signer le certificat courant. Subject et Issuer sont des chaines caractère appelée « Distinguished Name » (DN) formé d’un ou plusieurs éléments, « Common Name » (CN), « Organisation » (O), « Country » (C), « Locality » (L)… Pour un certificat utilisateur, le CN contiendra souvant une adresse mail, alors que pour un certificat de serveur web le CN contiendra le nom de domaine (vhost) à la charge de celui-ci.
Une PKI est un outil/un système permettant de gérer le cycle de vie des certificats (création, révoquation…). Le tutorial PKI sur readthedocs est très bien fait et je vous encourage à le lire.
- EJBCA
- est une PKI libre écrite ne Java.
- easyrsa
- est une PKI libre et très simple fournie avec openvpn.
Les certificat les plus courant servent à authentifier des serveur web. Cela permet à l’utilisateur de vérifier que le site web sur lequel il surf est bien celui qu’il prétend être.
Les navigateur web possède une liste de certificat « racine » considérés comme digne de confiance. Lorsque le navigateur arrive sur une page web en HTTPS il reçoit le certificat du serveur web de la page en question (et potentiellement des certificats intermédiaires, mais j’en parlerais plus tard). Le navigateur vérifie s’il possède dans sa liste de certificat de confiance, un certificat dont l’attribut « Subject » correspond l’attribut « Issuer » du certificat envoyé par le serveur web (en fait il fait une comparaisont du hash de ces éléments). S’il n’en trouve aucune, le site est considéré comme douteux et alerte l’utilisateur.
Si un certificat racine correspondant est trouvé. Le navigateur fait un hash des données du certificat de serveur web et déchiffre la signature du certificat du serveur web grace à la clé publique du certificat de confiance. Si ces deux opérations donnent le même résultat c’est que le certificat du serveur web à bien été signé par la clé privé de l’autorité de certification ayant émit le certificat racine (la clé privé dont la clé publique est contenu dans le certificat racine). Le site web est donc considéré comme « de confiance ».
Une autorité de certification (CA) est une entité qui délivre des certificats. Si une personne veut un certificat, elle créé une clé privé et un CSR et l’envoie à l’autorité de certification. Un CSR et une demande de signature de certificat, il s’agit en gros du certificat non encore signé. L’autorité de certification vérifie que la personne qui demande le certificat est bien celui qu’il prétent être, si ce qu’elle demande est cohérent (e.g. est-ce qu’il possède bien le nom de domaine qu’il souhaite valider) et si les éléments demandé dans le CSR sont en accord avec la politique de l’autorité (e.g. Basic Constraints = CA:FALSE, certaines autorité interdisent certains attributs). Si toutes les conditions sont réunis l’autorité supprime la signature du CSR et ajoute sa signature, le transfomant en certificat. Souvant l’autorité ajoute certains attributs au CSR, comme un liens vers sa « Certificat Révoquation List » (CRL), des attributs de limitations, un liens vers un descriptif de sa politique de gestion de PKI… Une Authorité de certification vend (ou donne parfois) donc de la confiance. Tout est basé sur le fait que l’autorité vérifie méticuleusement l’identité et les droits des demandeurs de certificats avant de leurs accorder. Et c’est après avoir passé des audits de sécurité et pas mal de vérifications que le(s) certificat racine d’une autorité est ajoutée au différente liste de certificats racine de confiance (GNU/Linux distros, Windows, navigateurs…).
Une CRL est un fichier contenant une liste de certificat qui n’ont pas atteint leur date limite de validité et qui ne sont plus considéré comme fiable. Le protocole OCSP qui permet d’obtenir le status (révoké/non révoké) d’un certificat est aujourd’hui préféré au fichier CRL.
Un certificat racine est un certificat autosigné (ou parfois non signé… mais j’ai jamais vue ce cas). C’est à dire que la clé qui à servie à générer la signature contenu dans le certificat est la clé privé correspondant à la clé publique aussi contenu dans le certificat. Un certificat racine de confiance est parfois appelé « trust anchor ».
Comme dit plus haut, le serveur web peut envoyer des certificats intermédiaires en plus de son propre certificat. En effet, comme à chaque certificat correspond une clé privé, on peut créer des chaînes de certificat ; la clé privé associé à chaque certificat servant à signer le(s) certificat fils. La clé privé du certificat racine servant à signé le certificat racine lui-même en plus du/des certificat fils. Le navigateur possède uniquement une liste de certificat racine. Si des certificats intermédiaires se trouve entre celui du serveur web et la racine, le serveur web est obligé de les envoyer pour que le navigateur dispose de la chaine de certificat complète. Cette chaine de certificat est parfois appelé la chaine de confiance.
En théorie donc il est possible de générer des certificat dès que l’on possède un couple clé privé/certificat. En réalité certains attribut contenu dans les certificat en restreigne l’usage. Par exemple, si un certificat possède un attribut « Basic Constraints » contenant « CA:FALSE », les certificats signés via sa clé privé ne seront pas reconnue comme de confiance.
Il existe beaucoup d’autorités de certification, je ne parlerais ici que de quatres d’entre elles.
- Let’s Encrypt
- est une autorité délivrant des certificats gratuit pour les serveurs web. Voir la section Let’s Encrypt.
- CAcert
- est une autorité communautaire (une association) délivrant des certificats gratuit. Les nouveaux membres peuvent, après validation automatique (ou semi-automatique… je ne sais plus), obtenir un certificat de classe 1 (je décrit plus loin la notion de classe de certificat) valide six mois. Pour obtenir des certificats de classe supérieur et valide plus longtemps, ces membres doivent rencontrer physiquement des autres membres « assurer » qui vérifie leur identité. Chaque rencontre donne droit à un nombre de points relatif au niveau d’accréditation du membre « assurer ». Au bout d’un certain nombre de point le nouveau membre acquière le status de membre validé et peut demander des certificats de classe supérieur. Les membres validé peuvent devenir membre acréditeur en obtenant encore plus de point et en passant un examen. Sur le principe cette autorité est très intéressante mais ses certificats racine ne sont présent que dans très peu de liste. Par exemple, les certificat émis par cette autorité ne sont pas considéré comme de confiance par Firefox et il semble qu’ils ne soit pas prèt d’être inclue. Sous ArchLinux vous pouvez installer les certificats racine de cette autorité via le paquet ca-certificates-cacert.
- StartSSL
- délivre des certificats gratuit. La révocation de certificat est payante. Selon leur policy (voir section 7.3.2 page 37) elle permet de demander des certificat incluant dans le « Subject Alt Name » (SAN) un SRV-ID (ici appelé « SRV Name ») utilisé notament pour les certificat XMPP. J’ai généré deux certificats en essayant d’inclure un SRV-ID, sans succès. J’ai envoyé un email au support. (up 30/01/2016, pas de réponse depuis une semaine… je relance)
- WoSign
- Je n’ai jamais testé cette CA. Elle délivre des certificats gratuit. La révocation est aussi gratuite. Selon leur policy (voir section 7.2 pages 56-57) elle ne permet pas de demander de certificat incluant un SRV-ID.
Les classes de certificat ne font pas partie de la norme mais on été inventé par les autorité de certifications. Elles indique uniquement le niveau de validation qui a été effectué lors de la délivrance du certification. On distigue généralement les différente classe de certificat suivant leur Issuer, c’est à dire qu’un certificat parent différent est utilisé par l’autorité pour chaque type de certificat.
max@laptop % openssl x509 -in startcom-craoc.crt -noout -text
…
Issuer: C=IL, O=StartCom Ltd., OU=StartCom Certification Authority, CN=StartCom Class 1 DV Server CA
…
Il existe deux format d’encodage de certificat (il en existe peut-être d’autre mais je ne les ai jamais rencontré et ne les connais pas)
Le format PKCS #12 généralement utilisé avec l’extension de fichier « .p12 » ou « .pfx » est un conteneur permettant de stoquer plusieurs object comme un certificat et sa clé privé correspondante. En gros on peut le voir comme une archive chiffré (un genre de zip avec mot de passe ultra complex). Il est utile lorsque l’entité qui demande le certificat ne sais pas générer un clé privé ou un CSR. La PKI lui génère le tout et lui envoie le certificat et sa clé privée sous forme d’une fichier au format PKCS #12 protégé par mot de passe.
Pour extraire le certificat et la clé d’un pkcs (sans chiffré la clé : -nodes) :
max@laptop % # certif & clé dans output.pem
max@laptop % openssl pkcs12 -in fichier.pfx -out output.pem -nodes
max@laptop % # uniquement le certif
max@laptop % openssl pkcs12 -in fichier.pfx -out cert.pem -nokeys
max@laptop % # uniquement la clé
max@laptop % openssl pkcs12 -in fichier.pfx -out key.pem -nocerts -nodes
Pour créé une archive pkcs (on ne sais jamais) :
max@laptop % openssl pkcs12 -export -out archive.pfx -inkey key.pem -in cert.pem -certfile CA-chain.pem
Nous avons vu plus haut que chaque certificat contient des données. Parmi ces données deux attributs figure parmis les plus important pour l’utilisateur : Subject et SubjectAltName. En sécurité le « Subject » correspond à la chose qui est validée/sécurisée. Cette élément contient un attribut « Common Name » (CN) qui désigne le nom de l’élément validée, pour un serveur web il s’agit du nom de domaine, pour email il s’agit de l’adresse email…
Le problème et qu’il ne peut y avoir qu’un seul « Subject » dans un certificat et que celui-ci ne peut contenir qu’un seul CN. Il y a longtemps il n’était donc pas possible de valider plusieurs nom de domaine avec un seul certificat. Aujourd’hui il existe l’extension « SubjectAltName » qui permet d’indiquer plusieurs équivalent du CN. Il faut toujours re-indiquer dans le « SubjectAltName » le nom indiqué dans le CN du « Subject ». Si le « SubjectAltName » et présent le CN n’est pas utilisé (dans la plupart des logiciels). « SubjectAltName » est parfois abrégé SAN.
Schéma récapitulatif
Génération d’un certificat
Communication TLS entre un client et un serveur (eg. HTTPS)
openssl
openssl est l’outil que nous allons le plus manipuler pour géré les certificats.
Il s’utilise toujours avec une « commande », e.g. pour les commandes x509 et genrsa : openssl x509 …, openssl genrsa ….
Une des particularité d’openssl est que les page de manuel des commande sont accessible sans préfix « openssl ».
Par exemple pour voir les options que l’on peut passer après openssl x509 il faut faire man x509.
principales commandes
Les principales commandes :
- x509
- permet de manipuler les certificats (généralement les fichier « .crt » mais il existe d’autres extension pour désigner un certificat). Attention, seul le premier certificat est pris en compte. Par exemple si le fichier passé en paramètre de l’option « -in » est un bundle (agrégat de plusieurs certificat), seul le premier sera pris en compte. De la même façon, si on passe cette commande à la suite de s_client les certificats intermédiaires ne seront pas pris en compte.
- genrsa
- créé une paire de clé rsa (clé privée + clé publique)
- rsa
- manipule les clé rsa
- req
- créé et manipule les CSR
- s_client
- effectue une connection TLS avec un serveur et affiche les informations relatifs au certificats échangé. Lors de la vérification du certificat du serveur s_client prend en comptes les certificats intermédiaires envoyé par le serveur web.
- verify
- permet de vérifié la chain de confiance d’un certificat.
openssl utilise la liste de certificat de confiance présent dans le dossier
/etc/ssl/certs(utiliser-CApathou-CAfilesi le certificat racine n’est pas dans/etc/ssl/certs).% openssl verify -untrusted certificats-intermédiaires.pem certificat.crt
La plupart de ces commandes permettent d’afficher des informations sur les fichiers gérés via les options « -in fichier -noout -text ». « -noout » permet de ne pas afficher le fichier au format PEM (ce qui nous intéresses c’est la description textuelle).
création d’un certificat
Pour nous créer un certificat nous allons d’abort devoir créé un CSR et une clé paire de clés privée/publique.
Pour créé la paire de clé de 4096bits :
max@laptop % openssl genrsa -out craoc.key 4096
Pour créer le CSR nous allons utilisé un fichier de configuration openssl. Beaucoup de tutorial sur le web utilise le fichier de configuration par défault proposé par openssl. Je trouve que ce n’est pas forcément une bonne pratique car ça masque une grande partie de la compléxité du procédé et surtout ça empèche m’empèche de comprendre exactement ce que j’inclue/exclue dans mes CSR.
Je me suis inspiré des fichiers de configuration proposé dans la section Simple PKI pour créé les miens. Je vous encourage fortement à parcourir le site pki-tutorial.readthedocs.io. Les fichiers de configuration sont bien commenté.
openssl fourni la commande ca permettant signer des CSR, c’est une CA minimaliste. Elle permet de comprendre à peu près comment fonctionne les autres CA comme « Let’s Encrypt », « startssl » ou « CAcert ». Voici un exemple de configuration openssl d’une autorité de certification simple de signature de CSR (et donc génération de certificat). Les options interressantes sont :
copy_extensions = copy # Copy extensions from CSR
x509_extensions = email_ext # Default cert extensions
Ces options sont détaillée dans la page man de ca. Elle nous indique que des extensions (attributs) sont utilisées par défaut et qu’ensuite sont ajouté les extensions contenu dans le CSR si celle-ci ne sont pas déjà présente dans les extensions par défaut. On peut supposer que les autres CA fonctionne à peu près de la même manière. C’est à dire qu’il n’est necessaire de renseigné les extensions par défaut. Pour avoir la liste des extensions « par défaut » et « autorisé » il faut aller voir les « policy » des autorité de certification (section 10.3 pour letsencrypt, section 7.3.2 pour startssl).
Pour mon certificat Let’s Encrypt, utilisé sur mon serveur web, j’ai utilisé la configuration suivante (letsencrypt-craoc.conf) :
[ req ]
default_md = sha256 # MD to use
utf8 = yes # Input is UTF-8
string_mask = utf8only # Emit UTF-8 strings
prompt = no # Doesn't prompt
distinguished_name = distinguished_name
req_extensions = v3_extensions # Desired extensions
[ v3_extensions ]
subjectAltName = @subject_alternative_name
[ distinguished_name ]
commonName = craoc.fr
[ subject_alternative_name ]
DNS.1 = craoc.fr
DNS.2 = www.craoc.fr
DNS.3 = davical.craoc.fr
DNS.4 = dokuwiki.craoc.fr
DNS.5 = ftp.craoc.fr
Pour générer le CSR :
max@laptop % openssl req -new -config letsencrypt-craoc.conf -out craoc.csr -key craoc.key
Après envoie du CSR et signature par la CA voici le certificat obtenu :
root@server # openssl x509 -in letsencrypt-craoc.crt -noout -text
…
Subject: CN=craoc.fr
…
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
4A:6B:61:7B:06:13:88:BF:08:45:D3:7A:8B:A3:C9:EE:D9:96:BE:32
X509v3 Authority Key Identifier:
keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1
Authority Information Access:
OCSP - URI:http://ocsp.int-x1.letsencrypt.org/
CA Issuers - URI:http://cert.int-x1.letsencrypt.org/
X509v3 Subject Alternative Name:
DNS:davical.craoc.fr, DNS:dokuwiki.craoc.fr, DNS:ftp.craoc.fr, DNS:craoc.fr, DNS:www.craoc.fr
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.1
Policy: 1.3.6.1.4.1.44947.1.1.1
CPS: http://cps.letsencrypt.org
User Notice:
Explicit Text: This Certificate may only be relied upon by Relying Parties and only in accordance with the Certificate Policy found at https://letsencrypt.org/repository/
Pour mon certificat StartSSL, que je voulais utiliser sur mon serveur XMPP, j’ai utilisé la configuration suivante mais je n’ai pas obtenu le certificat escompté :
oid_section = new_oids
[ new_oids ]
# RFC 6120 section 13.7.1.4. (SRVName dans le RFC 4985, SRV-ID dans le RFC 6120)
# XMPP service providers SHOULD include the SRV-ID identifier type in
# certificate requests
SRVName = 1.3.6.1.5.5.7.8.7
# RFC 6120 : XMPPAddress : longer encouraged in certificates issued by certification
# authorities or requested by XMPP service providers
# XMPPAddr = 1.3.6.1.5.5.7.8.5
[ req ]
default_md = sha256 # MD to use
utf8 = yes # Input is UTF-8
string_mask = utf8only # Emit UTF-8 strings
prompt = no # Doesn't prompt
req_extensions = v3_extensions # Desired extensions
distinguished_name = distinguished_name
[ v3_extensions ]
subjectAltName = @subject_alternative_name
[ distinguished_name ]
commonName = craoc.fr
[ subject_alternative_name ]
# See https://tools.ietf.org/html/rfc6120#section-13.7.1.2 for more info.
# _xmpp-client: for client-to-server connections
# _xmpp-server: for server-to-server connections
DNS.0 = craoc.fr
otherName.0 = SRVName;IA5STRING:_xmpp-client.craoc.fr
otherName.1 = SRVName;IA5STRING:_xmpp-server.craoc.fr
Après envoie du CSR et signature par la CA voici le certificat obtenu, il ne contient pas les otherName (ce qui n’est pas normal selon moi) :
root@server # openssl x509 -in startssl-craoc.crt -noout -text
…
Subject: CN=craoc.fr
…
X509v3 extensions:
X509v3 Key Usage:
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Client Authentication, TLS Web Server Authentication
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
BB:F6:D4:30:BF:18:65:1E:C6:5A:CF:7B:84:5E:44:37:F5:04:88:EE
X509v3 Authority Key Identifier:
keyid:D7:91:4E:01:C4:B0:BF:F8:C8:67:93:44:9C:E7:33:FA:AD:93:0C:AF
Authority Information Access:
OCSP - URI:http://ocsp.startssl.com
CA Issuers - URI:http://aia.startssl.com/certs/sca.server1.crt
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.startssl.com/sca-server1.crl
X509v3 Subject Alternative Name:
DNS:craoc.fr, DNS:www.craoc.fr
X509v3 Issuer Alternative Name:
URI:http://www.startssl.com/
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.1
Policy: 1.3.6.1.4.1.23223.1.2.4
CPS: http://www.startssl.com/policy
récupérer le certificat d’un serveur
Vous voulez accéder à une page web ou télécharger un élément en https mais le certificat du serveur n’est pas reconnue comme certificat de confiance. Les certificats racine qui on servie à signer le certificat du serveur n’est pas enregistré dans votre système comme certificats de confiances.
Si l’administrateur du serveur à bien fait les choses, lors d’une demande de connexion https celui-ci doit envoyer le certificat d’authentification du serveur mais aussi toutes la chaine de certificat servant à vérifier son authenticité.
Pour optenir des informations sur ce que retourne le serveur lors d’une connection vous pouvez utiliser openssl s_client.
max@laptop % openssl s_client -showcerts -servername example.net -connect example.net:443 < /dev/null 2> /dev/null | less
Pour récupérer les certificat racine pour pouvoir ensuite les ajouter aux certificats racine de confiance vous pouvez utiliser la commande suivante :
max@laptop % server=example.net ; openssl s_client -showcerts -servername ${server} -connect ${server}:443 < /dev/null 2> /dev/null | awk '/BEGIN CERTIFICATE/{i++}; /BEGIN CERTIFICATE/,/END CERTIFICATE/{if(i>1){print}}'
max@laptop % server=example.net ; openssl s_client -showcerts -servername ${server} -connect ${server}:443 < /dev/null 2> /dev/null | perl -ne '$i++ if /BEGIN CERTIFICATE/; print if (/BEGIN CERTIFICATE/.../END CERTIFICATE/) && $i > 1'
Cette commande permet d’afficher au format PEM les certificats renvoyés par le serveur, excepté le premier (qui est le certificat du serveur).
- showcerts
- Permet d’afficher toute la chaine de certificat. Sans cette option seul le certificat du serveur est affiché.
- connect
- L’IP et le port sur lequel faire la connection TLS.
- servername
- Le vhost sur lequel récupérer le certificat. Les vhost de « connect » et « servername » peuvent être différent mais il doivent avoir la même IP. Sans cette option on récupère le certificat du vhost par défaut d’nginx/apache. La connection TLS s’effectue avant la connection HTTP. Avant l’apparition du TLS SNI (Server Name Indication) le serveur web ne connaissait le vhost à utiliser qu’une fois la connection TLS établie. Il ne pouvez y avoir qu’une certificat par serveur web et non pas un certificat par vhost.
Certains tutoriels vous conseille d’utiliser openssl x509 pour formater la sortie de openssl s_client.
Je vous encourage à NE PAS LE FAIRE car openssl x509 ne considère que le premier certificat qu’il trouve.
De la même manière si vous utilisez cette commande sur un bundle de certificat seul le premier sera pris en compte.
Si vous obtenez l’erreur suivante, essayé avec les l’option -CApath ou -CAfile root-ca.crt.
max@laptop % openssl s_client -servername www.craoc.fr -connect www.craoc.fr:443 > /dev/null < /dev/null
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify error:num=20:unable to get local issuer certificate
verify return:0
DONE
max@laptop % openssl s_client -CApath '/etc/ssl/certs' -servername www.craoc.fr -connect www.craoc.fr:443 < /dev/null > /dev/null
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X1
verify return:1
depth=0 CN = craoc.fr
verify return:1
DONE
max@laptop % openssl s_client -CAfile /etc/ssl/certs/DST_Root_CA_X3.pem -servername www.craoc.fr -connect www.craoc.fr:443 < /dev/null > /dev/null
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X1
verify return:1
depth=0 CN = craoc.fr
verify return:1
DONE
Signature S/MIME
Pour signer un text en ligne de commande.
max@laptop % cat > test
toto
tata
max@laptop % openssl smime -sign -text -in test -out test.signed -signer craoc.fr.pem.crt -inkey craoc.fr.pem.key -certfile craoc.fr-intermediaire.pem.crt
max@laptop % cat test.signed
MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha1"; boundary="----A8AB1EED8BAA34A4F61BF39E95FA9966"
This is an S/MIME signed message
------A8AB1EED8BAA34A4F61BF39E95FA9966
Content-Type: text/plain
toto
tata
------A8AB1EED8BAA34A4F61BF39E95FA9966
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
MIIUTgYJKoZIhvcNAQcCoIIUPzCCFDsCAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3
DQEHAaCCEWgwggYOMIID9qADAgECAhA2gl5/taSBk3720XNruTymMA0GCSqGSIb3
DQEBDAUAMIGFMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVz
dGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRl
…
------A8AB1EED8BAA34A4F61BF39E95FA9966--
max@laptop % openssl smime -verify -text -in test.signed -signer craoc.fr.pem.crt -purpose any
toto
tata
Verification successful
craoc.fr-intermediaire.pem.crt doit contenir uniquement les certificats intermédiaire.
Déchiffrement matériel
Sources :
- OpenSSL Intel AES-NI Engine
- Enable OpenSSL hardware acceleration
- Does Nginx use the hardware AES support of Intel Core i7 or other similar architectures?
Les outils/services qui utilise le TLS utilise généralement les bibliothèques fournie par openssl/libressl. Si openssl est capable d’utiliser l’accélération matériel pour déchiffrer du TLS alors vos outils/services profite de cette accélération.
Pour savoir si votre machine dispose d’un module d’accélération matériel vous pouvez vérifier la présence du flag « aes » sur vos CPU :
max@laptop % grep -m 1 aes /proc/cpuinfo
flags : … aes …
Vous aussi tester la vitesse des algorithm que vous utilisez.
Test de vitesse
openssl speed permet de tester la vitesse de chiffrement/déchiffrement des différent cypher disponibles :
max@server % openssl speed -h
Error: bad option or value
Available values:
md4 md5 hmac sha1 sha256 sha512 whirlpoolrmd160
idea-cbc rc2-cbc bf-cbc des-cbc des-ede3
aes-128-cbc aes-192-cbc aes-256-cbc aes-128-ige aes-192-ige aes-256-ige
aes-128-gcm aes-256-gcm
camellia-128-cbc camellia-192-cbc camellia-256-cbc rc4 chacha20-poly1305
rsa512 rsa1024 rsa2048 rsa4096
dsa512 dsa1024 dsa2048
ecdsap160 ecdsap192 ecdsap224 ecdsap256 ecdsap384 ecdsap521
ecdsak163 ecdsak233 ecdsak283 ecdsak409 ecdsak571
ecdsab163 ecdsab233 ecdsab283 ecdsab409 ecdsab571 ecdsa
ecdhp160 ecdhp192 ecdhp224 ecdhp256 ecdhp384 ecdhp521
ecdhk163 ecdhk233 ecdhk283 ecdhk409 ecdhk571
ecdhb163 ecdhb233 ecdhb283 ecdhb409 ecdhb571 ecdh
idea rc2 des aes camellia rsa blowfish
Available options:
-elapsed measure time in real time instead of CPU user time.
-evp e use EVP e.
-decrypt time decryption instead of encryption (only EVP).
-mr produce machine readable output.
-multi n run n benchmarks in parallel.
Par défault, la commande openssl n’utilise pas l’accélération matériel (c’est l’inverse pour les bibliothèque ssl). Pour activer le support de l’accélération matériel il faut utiliser l’option evp. Ici ça ne change rien car mon server ne supporte pas l’AES-NI.
max@server % openssl speed aes-128-gcm
Doing aes-128 gcm for 3s on 16 size blocks: 1194663 aes-128 gcm's in 2.92s
Doing aes-128 gcm for 3s on 64 size blocks: 562348 aes-128 gcm's in 2.92s
Doing aes-128 gcm for 3s on 256 size blocks: 273534 aes-128 gcm's in 2.91s
Doing aes-128 gcm for 3s on 1024 size blocks: 82490 aes-128 gcm's in 2.94s
Doing aes-128 gcm for 3s on 8192 size blocks: 10830 aes-128 gcm's in 2.93s
LibreSSL 2.5.3
built on: date not available
options:bn(64,64) rc4(8x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx)
compiler: information not available
The 'numbers' are in 1000s of bytes per second processed.
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
aes-128 gcm 6546.10k 12325.44k 24063.47k 28731.21k 30279.65k
max@server % openssl speed -evp aes-128-gcm
Doing aes-128-gcm for 3s on 16 size blocks: 2539804 aes-128-gcm's in 2.95s
Doing aes-128-gcm for 3s on 64 size blocks: 756601 aes-128-gcm's in 2.96s
Doing aes-128-gcm for 3s on 256 size blocks: 313274 aes-128-gcm's in 2.95s
Doing aes-128-gcm for 3s on 1024 size blocks: 86835 aes-128-gcm's in 2.98s
Doing aes-128-gcm for 3s on 8192 size blocks: 11123 aes-128-gcm's in 3.00s
LibreSSL 2.5.3
built on: date not available
options:bn(64,64) rc4(8x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx)
compiler: information not available
The 'numbers' are in 1000s of bytes per second processed.
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
aes-128-gcm 13775.21k 16358.94k 27185.81k 29838.60k 30373.21k
Même tests sur chacha20-poly1305 :
max@server % openssl speed chacha20-poly1305
Doing chacha20 poly1305 for 3s on 16 size blocks: 968670 chacha20 poly1305's in 2.83s
Doing chacha20 poly1305 for 3s on 64 size blocks: 940011 chacha20 poly1305's in 2.93s
Doing chacha20 poly1305 for 3s on 256 size blocks: 434745 chacha20 poly1305's in 3.00s
Doing chacha20 poly1305 for 3s on 1024 size blocks: 136924 chacha20 poly1305's in 3.00s
Doing chacha20 poly1305 for 3s on 8192 size blocks: 18474 chacha20 poly1305's in 2.98s
LibreSSL 2.5.3
built on: date not available
options:bn(64,64) rc4(8x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx)
compiler: information not available
The 'numbers' are in 1000s of bytes per second processed.
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
chacha20 poly1305 5476.58k 20532.66k 37098.24k 46736.73k 50784.90k
max@server % openssl speed -evp chacha20-poly1305
chacha20-poly1305 is an unknown cipher or digest
J’utilise donc chacha20-poly1305 sur mon serveur.
Autres
Autres exemples qui m’ont déjà été utiles :
-
vérifier qu’un serveur web fait bien du OCSP response stapling :
max@laptop % openssl s_client -status -servername www.craoc.fr -connect www.craoc.fr:443 < /dev/null 2> /dev/null | grep 'OCSP Response Status' OCSP Response Status: successful (0x0) -
vérifier qu’une clé privée RSA correspond à un certificat :
max@server % diff <(openssl x509 -in nginx.pem -noout -modulus) <(openssl rsa -in nginx.key -noout -modulus) max@server % echo $? 0Le modulus est un élément utilisé et partagé par les clés publique et privée du système RSA.
-
vérifier qu’une paire de clés privées ECDSA correspond à un certificat :
max@server % diff <(openssl ec -in privkey.pem -pubout) <(openssl x509 -in chain.pem -noout -pubkey) read EC key writing EC key max@server % echo $? 0 -
vérifier la validité d’un certificat avec CRL (source) :
% openssl verify -crl_check -CAfile "chain+crl.pem" cert.pemL’URI de la CRL se trouve dans le certificat.
chain+crl.pemest la concaténation du fichier de la chain des certificats CA et de la CRL.
certificat de confiance
Archlinux
Sur une installation ArchLinux les certificats de confiance sont installé par les paquets core/ca-certificates-mozilla et core/ca-certificates-cacert (et le métapaquet ca-certificates qui ne fait rien sinon dépendre des deux précédent paquets).
max@laptop % yaourt -Ql ca-certificates-cacert
…
ca-certificates-cacert /usr/share/ca-certificates/trust-source/anchors/CAcert.org_class3.crt
ca-certificates-cacert /usr/share/ca-certificates/trust-source/anchors/CAcert.org_root.crt
…
max@laptop % yaourt -Ql ca-certificates-mozilla
…
ca-certificates-mozilla /usr/share/ca-certificates/trust-source/mozilla.neutral-trust.crt
ca-certificates-mozilla /usr/share/ca-certificates/trust-source/mozilla.supplement.p11-kit
ca-certificates-mozilla /usr/share/ca-certificates/trust-source/mozilla.trust.crt
…
Les certificat sont installé dans dans /usr/share/ca-certificates/trust-source.
Les certificats racine utilisés par les applications sont stocké dans les dossier /etc/ssl/certs et /etc/ca-certificates/extracted.
C’est la commande update-ca-trust extract (lire en particulier le paragraphe Extracted Configuration) qui peuple ces dossiers une fois les « pack » de certificats installé dans /usr/share/ca-certificates.
En fait, sous ArchLinux, update-ca-trust est un script bash appelant la commandes trust de p11-kit (une dépendance du paquet).
Je vous encourage à lire ce script car il n’est pas compliqué et il permet de se rendre compte facilement de ce qui ce passe.
La documentation de trust se trouve dans le fichier /usr/share/gtk-doc/html/p11-kit/trust.html.
En fait les « pack » de certificats sont extrait dans /etc/ca-certificates/extracted :
- le fichier
tls-ca-bundle.pemrassemble tous les certificat permettant l’authentification de server https - le fichier
email-ca-bundle.pemrassemble tous les certificat permettant l’authentification de server mail - le fichier
objsign-ca-bundle.pemrassemble tous les certificat permettant l’authentification de code signé - le fichier
ca-bundle.trust.crtcontient tous les certificats - le dossier
cadircontient tous les certificats permettant l’authentification de server https (un fichier par certificat), ainsi que, pour chacun d’eux :-
un lien symbolic dont le nom correspond au hash du « Subject » suffixé de « .0 »
-
un lien symbolic dont le nom correspond au hash du « Subject » calculé avec l’ancien algorithme utilisé dans les versions d’openssl inférieur à 1.0.0, suffixé de « .0 ». Le « Suject » et les deux hashs peuvent respectivement être récupérés avec les commandes suivantes :
% openssl x509 -in moncertificat -noout -subject % openssl x509 -in moncertificat -noout -subject_hash % openssl x509 -in moncertificat -noout -subject_hash_old
-
Des certificats sont aussi stocké dans des structures compréhensible par Java.
Tous les lien symbolic contenu dans /etc/ca-certificates/extracted/cadir, et uniquement les liens symbolique (excepté pour le truc Java) sont copié dans le répertoire /etc/ssl/certs.
Gentoo
Sur une installation Gentoo les certificats de confiance sont installés par les paquets app-misc/ca-certificates.
root@server # equery f app-misc/ca-certificates
* Searching for ca-certificates in app-misc ...
* Contents of app-misc/ca-certificates-20140927.3.17.2:
…
/etc/ca-certificates.conf
…
/etc/ca-certificates/update.d
…
/etc/env.d/98ca-certificates
…
/etc/ssl/certs/…
…
/usr/sbin/update-ca-certificates
…
/usr/share/ca-certificates/cacert.org/cacert.org_root.crt
…
/usr/share/ca-certificates/mozilla/…
…
/usr/share/ca-certificates/spi-inc.org/spi-cacert-2008.crt
…
Les certificat sont installé dans dans /usr/share/ca-certificates.
Les certificats racine utilisés par les applications sont stocké dans les dossier /etc/ssl/certs.
La commande update-ca-certificates (c’est un script bash) peuple ce dossier.
Elle prend en compte tous les certificats listés dans le fichier /etc/ca-certificates.conf (mettre un « ! » devant un certificat pour le supprimer), et les certificats placé dans le dossier /usr/local/share/ca-certificates (il faut que les fichier est une extention en .crt).
Le fichier /etc/ssl/certs/ca-certificates.crt est un bundle de tous les certificats traité par update-ca-certificates.
installer ses propre certificats
Archlinux
Il suffit de placer ses certificats racine dans le dossier /etc/ca-certificates/trust-source/anchors et de lancer la commande trust extract-compat (anciennement on utilisé update-ca-trust mais cette méthode est dépréciée).
La commande trust extract-compat va générer les bundle et les liens symboliques.
Je ne sais pas quelle est la différence entre update-ca-trust et trust extract-compat.
Gentoo
Il faut placer ses certificats dans le dossier /usr/local/share/ca-certificates (il faut que les fichier est une extention .crt) et lancer la commande update-ca-certificates (ou emerge -1 app-misc/ca-certificates).
Debian
Comme pour Gentoo.
Testé sur Wheezy (7) et Stretch (9).
Alternative
Source : Installing CA Certificates into the OpenSSL framework
Si vous n’êtes pas sous ArchLinux et que la commande trust n’existe pas, utiliser update-ca-trust.
Si le dossier /etc/ca-certificates/trust-source/anchors n’existe pas essayé le dossier /usr/local/share/ca-certificates/.
Sous OpenSuse il faut utiliser le dossier /etc/pki/trust/anchors.
Si vraiment vous avez tout essayé mais que vous ne trouvez pas, ou simplement si vous voulez faire un truc de porc à la vas-vite et que vous vous en fouté.
Placer le certificat dans le dossier /etc/ssl/certs et générer son lien symbolique via la commande suivante.
max@laptop % i=moncertificat ; ln -s $i `openssl x509 -noout -hash -in $i`.0
certificate with distrust
Lorsque j’essayé d’installer des certificats comme certificats de confiance j’ai obtenu l’erreur suivante :
root@laptop # trust extract-compat
…
p11-kit: certificate with distrust in location for anchors: moncertificat.pem
…
Cette erreur/warning indique que l’entité qui a signé le certificat n’accorde sa confiance à ce certificat que pour certains usages.
Le certificat moncertificat.pem au format PEM commance par « BEGIN TRUST CERTIFICAT ».
Par défaut un certificat est signé avec toute la confiance du signataire mais il peut arrivé que cette confiance soit restrainte à certains usage. Par example uniquement la signature de mail et non l’authentification de serveur web. Dans ce cas le certificat est de type « BEGIN TRUST ».
Je vous encourage à lire l’article « OpenSSL: trust and purpose » pour bien comprendre ce qu’est un certificat « BEGIN TRUST » et la différence entre « trust » et « purpose ».
max@laptop % openssl x509 -in in.pem
-----BEGIN CERTIFICATE-----
…
max@laptop % openssl x509 -in in.pem -addtrust serverAuth -addreject clientAuth
-----BEGIN TRUSTED CERTIFICATE-----
…
max@laptop % openssl x509 -in in.pem -addtrust serverAuth -addreject clientAuth -out out.pem
max@laptop % openssl x509 -in in.pem -text > in.txt
max@laptop % openssl x509 -in test.pem -text > out.txt
max@laptop % diff in.txt out.txt
107a108,111
> Trusted Uses:
> TLS Web Server Authentication
> Rejected Uses:
> TLS Web Client Authentication
serveur
Lorsque vous utilisez un certificat pour authentifier un serveur il faut que vous fournissiez tous les certificat de la chaine de confiance excepté le(s) certificat racine (celui ou ceux qui sont inclus sur les postes clients).
Avec nginx, dans le fichier qui sera désigné par la directive ssl_certificate vous devrez concaténé votre certificat avec les autres certificats de la chaine. Attention à mettre votre certificat en premier.
max@laptop % cat moncertificat.pem intermediaires.pem > monbundle.pem
Avec apache, la chaine de certificat doit être placée dans un fichier séparé et désigné par la directive SSLCertificateChainFile.
wildcard
Un certificat « wildcard » est un certificat couvrant tous les sous-domaine de premier niveau d’un domaine. Par exemple, si le CN contient « *.craoc.fr » alors www.craoc.fr et ftp.craoc.fr sont validé, mais test.www.craoc.fr ne l’est pas. On ne peut pas créer un certificat avec plusieurs asterisque/wildcard sur un même domaine ; « *test.*.craoc.fr » n’est pas valide. Il est possible d’avoir un ou plusieurs domaine avec wildcard dans le « SubjectAltName ».
Pour résumer, dans le « SubjectAltName » :
DNS:*.craoc.fr: possible, match www.craoc.fr mais pas test.www.craoc.frDNS:pel*.craoc.fr: possibleDNS:test.*.craoc.fr: possible (TODO à vérifier)DNS:*.truc.fr, DNS:*.much.fr: possible
Bien sur, les CA peuvent appliquer des restriction. Par exemple, Let’s Encrypt refuse les wildcard.
XMPP
TODO
- http://prosody.im/doc/dns
- http://prosody.im/doc/certificates
- https://tools.ietf.org/html/rfc6120#section-13.7.1.2
- https://tools.ietf.org/html/rfc3920
- https://tools.ietf.org/html/rfc6120#section-13.7.1.2
- https://fr.wikipedia.org/wiki/Demande_de_signature_de_certificat
- http://mail.jabber.org/pipermail/members/2014-December/007954.html
- http://serverfault.com/questions/591844/are-xmpp-certificates-different-than-regular-ones/591872#591872
Les certificat server XMPP n’ont pas besoins de : Client Authentication (1.3.6.1.5.5.7.3.2)
Let’s Encrypt
Let’s Encrypt est une autorité délivrant des certificats gratuit pour les serveurs web. Sa particularité est d’être entièrement automatisée. Elle utilise le protocole ACME pour vérifier la validité des CSR et délivrer les certificats.
Les certificats qu’elle délivre sont valide trois mois et les policy est très restrictive (la liste des extentions X509 inclue dans les certificat est fixe). Il n’est par exemple pas possible d’obtenir un certificat incluant un SRV-ID dans le SubjectAltName comme le recommande vivement la norme XMPP. Il n’est pas non plus possible d’obtenir des certificat « wildcard ».
Voici une description rapide de mon infrastructure de gestion et renouvellement de certificat pour ce CA.
certbot
certbot (anciennement letsencrypt) est le client letsencrypt officiel.
Il permet d’obtenir des certificats avec clé ECDSA.
Sources :
- page de blog non officiel sur comment créer un certificat utilisant une clé ECDSA avec letsencrypt
- page de blog non officiel sur comment configurer https sous nginx
- documentation officiel sur comment utiliser certbot
- incompatibilité de chromium avec secp521r1
Création de l’utilisateur letsencrypt et du dossier /var/log/letsencrypt.
letsencrypt@server % grep letsencrypt /etc/passwd
letsencrypt:x:999:232::/etc/letsencrypt:/sbin/nologin
letsencrypt@server % cd ~letsencrypt
letsencrypt@server % stat /var/log/letsencrypt
File: ‘/var/log/letsencrypt’
Size: 372 Blocks: 0 IO Block: 4096 directory
Device: 13h/19d Inode: 2730803 Links: 1
Access: (0755/drwxr-xr-x) Uid: ( 999/letsencrypt) Gid: ( 232/letsencrypt)
…
Pour pouvoir générer un certificat avec une clé ECDSA il faut utiliser le mode « –csr ». J’ai donc créé un fichier de configuration openssl.
letsencrypt@server % cat craoc.conf
[ req ]
default_md = sha256 # digest (fonction de hashage) utiliser pour générer
# le hash sur lequel s'appliquera le chiffrement
# asymétrique de la clé privé (génération de la signature du csr)
utf8 = yes # Input is UTF-8
string_mask = utf8only # Emit UTF-8 strings
prompt = no # Doesn't prompt
distinguished_name = distinguished_name
req_extensions = v3_extensions # Desired extensions
[ v3_extensions ]
subjectAltName = @subject_alternative_name
[ distinguished_name ]
commonName = craoc.fr
[ subject_alternative_name ]
DNS.1 = craoc.fr
DNS.2 = www.craoc.fr
DNS.3 = davical.craoc.fr
DNS.4 = dokuwiki.craoc.fr
DNS.5 = ftp.craoc.fr
Il existe beaucoup de « courbe » permettant de paramétrer notre paire de clés privé/publique ECDSA, la liste complète peux être obtenu via openssl ecparam -list_curves.
- 2016/04/14 :
secp384r1semble être actuellement la courbe la plus sécuritaire parmis celles supportée par Firefox et Chrome. Chrome ne supportant pas secp512r1. - 2017/08/29 : seul la courbe
prim256v1est maintenant supporté par android 7.0, cela est dû à un bug. Lorsque ce bug sera corrigé je pense que je passerai à curve25519, supportée par Firefox et Chrome.
Génération de la paire :
letsencrypt@server % openssl ecparam -genkey -name prime256v1 -out privkey.pem
Letsencrypt ne permet de n’utiliser que le format DER pour le CSR.
letsencrypt@server % openssl req -new -config craoc.conf -outform der -out csr.der -key privkey.pem
J’utilise la méthode « –webroot » du client officiel. Cela permet de l’utiliser sans droit root mais nécéssite la création d’un répertoire accessible en écriture et en HTTP via « http://mon-domaine/.well-known/acme-challenge/ ».
letsencrypt@server % cat /etc/nginx/default-vhost.conf
server {
listen 80 default_server;
server_name _;
root /var/www/localhost/;
# pour letsencrypt
location /.well-known/acme-challenge/ {
try_files $uri =404;
}
# on redirige tout vers https
location / {
return 301 https://$host$request_uri;
}
}
letsencrypt@server % namei /var/www/localhost/.well-known/acme-challenge
f: /var/www/localhost/.well-known/acme-challenge
d /
d var
d www
d localhost
d .well-known
d acme-challenge
Génération d’un certificat avec certbot.
Lors des tests il est recommendé d’utiliser l’option --staging qui permet de faire ses requêtes sur un serveur dédié, sans limitation.
Le client garde 10 fichiers (ligne logging.handlers.RotatingFileHandler(…, backupCount=10)) de logs dans /var/log/letsencrypt, il n’est pas nécessaire d’utiliser logrotate.
letsencrypt@server % certbot certonly --webroot --webroot-path /var/www/localhost --non-interactive --email 'maxime.deroucy@gmail.com' --agree-tos --work-dir /var/log/letsencrypt --csr csr.der
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/0001_chain.pem. Your cert will expire on
2016-07-23. To obtain a new version of the certificate in the
future, simply run Let's Encrypt again.
letsencrypt@server % ls
0000_cert.pem 0000_chain.pem 0001_chain.pem accounts/ craoc.conf csr.der logs/ privkey.pem
letsencrypt@server % mv 0001_chain.pem chain.pem
letsencrypt@server % rm 0000_chain.pem 0000_cert.pem
letsencrypt@server % openssl x509 -in chain.pem -noout -text
…
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
…
Subject: CN=craoc.fr
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
…
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
…
X509v3 Subject Alternative Name:
DNS:craoc.fr, DNS:davical.craoc.fr, DNS:dokuwiki.craoc.fr, DNS:ftp.craoc.fr, DNS:www.craoc.fr
…
Configuration de nginx.
root@server # grep ssl_ /etc/nginx/pelican.conf
ssl_certificate /etc/letsencrypt/chain.pem;
ssl_certificate_key /etc/letsencrypt/privkey.pem;
root@server # cat /etc/nginx/nginx.conf
…
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+AESGCM:EECDH+AES;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve X25519:secp521r1:secp384r1:prime256v1;
…
Avec le mode « –csr » il n’est pour l’instant (24/04/2016) pas possible d’utiliser la commande « certbot renew » (et donc --renew-hook).
Je suis obligé de relancer exactement la même commande pour obtenir un nouveau certificat.
Et celle-ci m’en génère un nouveau même si l’ancien est encore bon (plus de 30 jours avant expiration).
J’ai donc utilisé un script bash pour tester et renouveler périodiquement mon certificat.
root@server # systemctl cat letsencrypt.timer
# /etc/systemd/system/letsencrypt.timer
[Unit]
Description=renew letsencrypt certificats
[Timer]
OnCalendar=weekly
Persistent=true
#RandomizedDelaySec=5h
[Install]
WantedBy=timers.target
root@server # systemctl cat letsencrypt.service
# /etc/systemd/system/letsencrypt.service
[Unit]
Description=renew letsencrypt certificats
Requisite=nginx.service
OnFailure=cron-failure@%p.service
[Service]
Type=oneshot
User=letsencrypt
WorkingDirectory=/etc/letsencrypt/
ExecStart=/usr/bin/chronic /etc/letsencrypt/renew.sh
root@server # cat /etc/letsencrypt/renew.sh
#!/bin/bash
set -e -o pipefail -u -x
cd /etc/letsencrypt
enddate_full_format=`openssl x509 -in chain.pem -noout -enddate | cut -d= -f2`
enddate_short_format=`date --date="$enddate_full_format" '+%s'`
date_in_thirty_days=`date --date='now + 30 days' '+%s'`
if test $enddate_short_format -gt $date_in_thirty_days
then
exit 0
fi
certbot certonly --webroot --webroot-path /var/www/localhost --non-interactive --email 'maxime.deroucy@gmail.com' --agree-tos --work-dir /var/log/letsencrypt --csr csr.der
rm 0000_cert.pem 0000_chain.pem
mv 0001_chain.pem chain.pem
sudo nginx -s reload
renew
Une petite note concernant l’option « renew » de certbot (même si je ne l’utilise pas pour l’instant).
La commande certbot -h all nous indique que « renew » renouvelle les certificat proche de leur date d’expiration… c’est cool mais « proche » ça correspond à combient de temps ?
En fait « proche » peu se configurer via la directive renew_before_expiry, qui est par défaut fixé à 30 jours.
simp_le
J’utilisait précédemment le client simp_le pour obtenir et renouveller mes certificats.
root@server # pwd
/etc/ssl/letsencrypt
root@server # ls -l
total 12K
-rw-r--r-- 1 letsencrypt letsencrypt 3,1K 2 mars 00:32 account_key.json
-rw-r--r-- 1 letsencrypt letsencrypt 3,9K 2 mars 00:32 fullchain.pem
-rw------- 1 letsencrypt letsencrypt 3,2K 2 mars 00:32 key.pem
drwxr-xr-x 1 root root 234 2 mars 23:34 old/
root@server # cat /etc/systemd/system/letsencrypt.service
[Unit]
Description=renew letsencrypt certificats
Requisite=nginx.service
OnFailure=cron-failure@%p.service
[Service]
Type=oneshot
User=letsencrypt
WorkingDirectory=/etc/ssl/letsencrypt/
# exit status:
# 0 if certificate data was created or updated
# 1 if renewal not necessary
# 2 in case of errors.
#
# OK if 0 or 1
SuccessExitStatus=1
ExecStart=/bin/sh -c '\
/usr/bin/simp_le \
--default_root /var/www/acme-challenge \
--vhost craoc.fr \
--vhost www.craoc.fr \
--vhost davical.craoc.fr \
--vhost dokuwiki.craoc.fr \
--vhost ftp.craoc.fr \
-f account_key.json \
-f key.pem \
-f fullchain.pem \
--reuse_key \
--email maxime.deroucy@gmail.com \
&& \
/usr/bin/sudo nginx -s reload'
ExecStart=/usr/bin/find /var/www/acme-challenge -type f -delete
root@server # cat /etc/systemd/system/letsencrypt.timer
[Unit]
Description=renew letsencrypt certificats
[Timer]
OnCalendar=*-*-01 04:00
Persistent=true
[Install]
WantedBy=timers.target
root@server # cat /etc/nginx/pelican.conf
# pour letsencrypt
server {
listen 80;
server_name www.craoc.fr;
access_log /var/log/nginx/www.craoc.fr.access_log main;
error_log /var/log/nginx/www.craoc.fr.error_log info;
root /var/www/git/www.craoc.fr;
location /.well-known/acme-challenge/ {
root /var/www/acme-challenge/;
try_files $uri =404;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2 default_server;
server_name www.craoc.fr;
ssl_certificate /etc/ssl/letsencrypt/fullchain.pem;
ssl_certificate_key /etc/ssl/letsencrypt/key.pem;
…
Tests
Let’s Encrypt limite la fréquence des requêtes (enregistrement, authentification, demande de certificat) qu’il est possible de passer à l’API. Lorsque j’ai monter ma plate-forme de renouvellement de certificat j’ai fait plusieurs tests avant d’avoir une configuration fonctionnelle et qui me plaise.
Let’s Encrypt fourni une API dédiée au test qui n’est pas limitée.
letsencrypt@server # simp_le --server 'https://acme-staging.api.letsencrypt.org/directory' --default_root /var/www/acme-challenge --vhost craoc.fr … --vhost ftp.craoc.fr -f account_key.json -f key.pem -f fullchain.pem --reuse_key --email maxime.deroucy@gmail.com
2016-03-03 21:02:13,950:INFO:simp_le:1202: Generating new account key
2016-03-03 21:02:21,430:INFO:requests.packages.urllib3.connectionpool:756: Starting new HTTPS connection (1): acme-staging.api.letsencrypt.org
…
2016-03-03 21:02:28,562:INFO:simp_le:1294: davical.craoc.fr was successfully self-verified
…
2016-03-03 21:02:29,071:INFO:simp_le:1294: ftp.craoc.fr was successfully self-verified
2016-03-03 21:02:29,590:INFO:simp_le:1294: craoc.fr was successfully self-verified
…
2016-03-03 21:02:30,086:INFO:simp_le:1294: dokuwiki.craoc.fr was successfully self-verified
…
2016-03-03 21:02:30,591:INFO:simp_le:1294: www.craoc.fr was successfully self-verified
…
2016-03-03 21:02:31,092:INFO:simp_le:1302: Generating new certificate private key
…
2016-03-03 21:02:41,545:INFO:simp_le:385: Saving account_key.json
2016-03-03 21:02:41,546:INFO:simp_le:385: Saving key.pem
2016-03-03 21:02:41,548:INFO:simp_le:385: Saving fullchain.pem
letsencrypt@server # ls -l
total 12K
-rw-r--r-- 1 letsencrypt letsencrypt 3,1K 3 mars 22:02 account_key.json
-rw-r--r-- 1 letsencrypt letsencrypt 3,3K 3 mars 22:02 fullchain.pem
-rw-r--r-- 1 letsencrypt letsencrypt 3,2K 3 mars 22:02 key.pem
letsencrypt@server # openssl x509 -in fullchain.pem -noout -text
…
Issuer: CN=happy hacker fake CA
…
Subject: serialNumber=fa956f497abe51b9182da212a01e31a1e761
…
X509v3 Subject Alternative Name:
DNS:craoc.fr, DNS:davical.craoc.fr, DNS:dokuwiki.craoc.fr, DNS:ftp.craoc.fr, DNS:www.craoc.fr
…
acme-tiny
Avant d’utiliser simp_le j’utilisait acme-tiny pour « dialoguer » avec la CA. J’ai arrété d’utiliser ce script car je me suis apperçut que le développeur principal du projet voulait conserver le nombre de ligne de code de son script sous la barre de 200 ; potentiellement au prix de sa lisibilité. Peut-être cela a-t-il changé aujourd’hui. Aussi, le client simp_le est mentionné dans le README du client officiel. Et son développeur principal est aussi le développeur principal du client officiel (le 02/03/2016).
Je donne ici la configuration que j’utilisai avec acme-tiny.
root@server # pwd
/etc/ssl/letsencrypt
root@server # ls -l
total 36K
-r-------- 1 letsencrypt letsencrypt 3,2K 10 janv. 14:57 account.key
drwxr-xr-x 1 letsencrypt letsencrypt 116 10 janv. 15:58 acme-tiny/
-rw-r--r-- 1 letsencrypt letsencrypt 3,9K 10 janv. 16:32 craoc.chained.crt
-r-------- 1 root root 506 24 janv. 18:04 craoc.conf
-rw-r--r-- 1 letsencrypt letsencrypt 2,2K 10 janv. 16:25 craoc.crt
-rw-r--r-- 1 letsencrypt letsencrypt 1,8K 14 janv. 23:49 craoc.csr
-r-------- 1 letsencrypt letsencrypt 3,2K 10 janv. 15:25 craoc.key
-rw-r--r-- 1 letsencrypt letsencrypt 1,7K 10 janv. 16:26 intermediate.pem
-rwxr-xr-x 1 letsencrypt letsencrypt 233 10 janv. 16:39 renew_cert.sh*
root@server # cat renew_cert.sh
#!/bin/sh
set -e
cd /etc/ssl/letsencrypt
python acme-tiny/acme_tiny.py --account-key account.key --csr craoc.csr --acme-dir /var/www/acme-challenge > craoc.crt
cat craoc.crt intermediate.pem > craoc.chained.crt
sudo nginx -s reload
root@server # ls /etc/systemd/system/letsencrypt.*
/etc/systemd/system/letsencrypt.service /etc/systemd/system/letsencrypt.timer
root@server # cat /etc/systemd/system/letsencrypt.service
[Unit]
Description=renew letsencrypt certificats
Requisite=nginx.service
OnFailure=cron-failure@%p.service
[Service]
Type=oneshot
ExecStart=/etc/ssl/letsencrypt/renew_cert.sh
WorkingDirectory=/etc/ssl/letsencrypt/
User=letsencrypt
root@server # cat /etc/systemd/system/letsencrypt.timer
[Unit]
Description=renew letsencrypt certificats
[Timer]
OnCalendar=*-01/3-01 04:00
Persistent=true
[Install]
WantedBy=timers.target
DNS CAA
Source :
- Comment avoir une excellente configuration HTTPS en 2017 ?
- DNS Certification Authority Authorization
Les enregistrement DNS CAA permettent de spécifier au client TLS, via le DNS, quels CA sont autorisé à emmetre des certificats pour votre domaine :
CAA 0 issue "letsencrypt.org"
CAA 0 iodef "mailto:admin@craoc.fr"
Chez OVH il n’est pas possible de renseigné ce type d’enregistrement DNS (forum OVH).
Non répudiation
Qu’est ce que la non répudiation :
The non-repudiation value in the keyUsage attribute relates to the whole certificate, not any purpose in particular. The presence of the non-repudiation flag indicates that the private key has sufficient protections in place that the entity named in the certificate cannot later repudiate—deny—actions they take with the certificate. The presence of the flag doesn’t prevent repudiation, rather it indicates that repudiation isn’t likely to survive reasonable scrutiny.
So in this specific case, the CA is giving the user the option of a certificate that does or does not include the non-repudiation element. If you want to assert to those verifying the signature that you can’t easily deny it was you who signed it (the USB token is the key enabler here), use the non-repudiation certificate. Otherwise, use the certificate marked for digital signatures. (Depending on the other attributes in the certificate, you may or may not be able to sign documents with either or both certificates.)
Extended Validation Certificates
Les Extended Validation (EV) certificates sont, comme les classes de certificat, une notion inventé par les CA. Il s’agit en fait de la classe ultime de certificat. Pour obtenir un certificat EV il faut subir un processus de vérification standardisée par le CA/B Forum. Il ont la particularité être indiqué par les navigateur web par un encart vert dans la barre d’URL.

liens
Quelques liens intéressant :