Formats PKCS, pem, der, key, crt,...

À chaque fois qu’on configure une application avec SSL/TLS, on se retrouve toujours à jongler avec des fichiers aux extensions spécifiques. Pour ne rien arranger, ces extensions changent d’une documentation à l’autre... Histoire de vous y retrouver, voici ce qu’elles cachent.

La cryptographie, c’est l’art du secret. Normalement, on ne devrait l’appliquer que sur des correspondances mais on dirait presque qu’elle s’applique à elle même tant certains de ses concepts peuvent paraître obscurs.

Par exemple, lorsqu’on configure une application pour utiliser des communications sécurisées, on utilise « SSL/TLS ». En fait, initialement, il n’y avait que « SSL ». On en était content mais il a eu quelques petites maladies qu’il a fallu soigner. Dans l’euphorie du moment, l’IETF en a profité pour le renommer « TLS ».

Techniquement, SSL est donc considéré comme obsolète et remplacé par TLS mais, sûrement par amour d’Eris, certaines applications et documentations continuent quand même d'utiliser le terme SSL (i.e. LDAPs), alors même qu’elles sont à jours et utilisent TLS...

Pexels @ pixabay
Pexels @ pixabay

Et c’est encore pire lorsque vous cherchez à configurer ces applications car elles utilisent des fichiers spécifiques dont les extensions semblent tirées au sort d’une documentation à l’autre : p7, p10, p12, der, pem, key, crt, cer pour citer les plus courants.

Heureusement, les concepts derrières toutes ces extensions sont plutôt simples et une fois compris, ces formats ne sont plus si aléatoires que ça.

À l’origine du problème, il y a deux types de contenu : des clés (PKCS #8) et des certificats (PKCS #12). Pour les encoder, on utilise une syntaxe spécifique (ASN.1) qui produit des fichiers binaires (DER) qu’on peut ensuite encoder en base64, plus facile à manipuler (PEM). Enfin, pour avoir plus facile à savoir quel fichier contient quoi, on utilise des extensions plus explicites pour les clés (KEY) et les certificats (CRT et parfois CER).

Types de fichiers

Tous les fichiers du jour concernent un champ très spécifique de la cryptographie appliquée : le stockage des certificats et des clés privées.

Les certificats

Lorsqu’on utilise des algorithmes asymétriques, ceux avec une clé privée (à garder secrète) et une clé publique (à diffuser), il est souvent bien pratique d’ajouter, à la clé publique, des informations sur son propriétaire. Ces informations et la clé constituent un certificat qu’on peut ensuite signer pour créer une PKI.

Pour que tous les logiciels puissent se comprendre, il a bien fallu établir un format pour organiser ces données, le fameux X.509 (créé en 1988 par l’Union Internationale des Télécommunications). Comme toujours en informatique, ce format a bénéficié de quelques améliorations successives, finalement formalisées et adaptée à Internet par l’IETF dans des RFC successives.

En parallèle des normalisation publiques, l’entreprise RSA (détentrice du brevet sur l’algorithme RSA) a également définit ses propres formats pour ses applications, les fameux Public Key Cryptographic Standards. Sans surprise, les plus utilisés ont ensuite fait l’objet d’une normalisation par l’IETF via des RFC spécifiques.

RSA Security @wikipedia
RSA Security @wikipedia

Lorsque vous manipulez des certificats, vous pouvez donc rencontrer, dans la très grande majorité des cas, les trois formats suivants :

En termes d’extensions de fichiers, vous pouvez donc trouver des certificats dans des fichiers .p7b (plus rarement .p7 et .p7c) ou des demandes de signatures de certificats dans des fichiers .p10.

Les clés privées

Qui dit certificat dit cryptographie asymétrique et donc clé privée, qu’il faut sécuriser mais pour ça, encore faut-il la stocker.

Et pour ça, le format proposé par RSA (l’entreprise) s’est imposé naturellement. Enfin, pour être complet, l’IETF n’a pas pu s’empêcher de normaliser ça en RFC mais ça ne change rien au format.

Techniquement, vous pourriez rencontrer des clés dans des fichiers .pk8 mais c’est plutôt rare.

Les deux

Parfois, on préfère inclure le certificat et sa clé privée dans un seul fichier (i.e. lorsqu’on configure LDAP et TLS sur un Active Directory).

Cette fois, c’est encore RSA qui s’est imposé mais l’IETF n’a pas (encore?) pris le temps de le normaliser dans une RFC (sans doute car le cas d’usage est bien plus spécifique).

Dès que vous avez besoin d’intégrer le certificat et sa clé privée en une seule fois, vous rencontrez donc des fichiers .p12. Généralement, ces fichiers sont chiffrés par un mot de passe.

Encodages

Les normes précédentes (PKCS et RFC) définissent les informations qu’il faut mettre dans tous ces fichiers pour être considérés comme valides et utilisables par les outils compatibles. Elles définissent aussi quelles informations sont obligatoires et lesquelles sont optionnelles, ainsi que l’ordre pour tout ranger.

Formats binaires

Mais que ce soit pour les stocker ou les transmettre, à un moment, il faut sérialiser tout ça ; transformer ces structures parfois complexes en suite de bits, de 0 et de 1. Et plus important, il faut pouvoir exprimer comment s’effectue cette sérialisation pour que des développeurs puissent produire des outils compatibles.

geralt @ pixabay
geralt @ pixabay

Et pour ça, on utilise une autre norme, « ASN.1 » (pour Abstract Syntax Notation One). Conçue par divers organismes, dont l’UIT à qui on doit le format X.509. Cette norme contient à la fois une manière d’exprimer nos structures complexes et des méthodes pour les traduire en binaire.

Pour les développeurs qui veulent gérer facilement des fichiers suivant ces formats, la bibliothèque libtasn1 est faite pour vous.

Lorsqu’il s’agit de sérialiser (et de désérialiser), la norme ASN.1 définit plusieurs façons de faire (adaptées à des situations différentes) :

Même si on peut stocker ou transmettre les données cryptographiques avec ces trois encodages, c’est le format DER qui est systématiquement utilisé. Ainsi, un fichier stocké dans un des formats PKCS contient en fait des données encodées en DER.

C’est plutôt rare mais si vous ne voulez pas utiliser les extensions PKCS habituelles, vous pourriez directement exporter vos données en DER, vous rencontreriez alors des fichiers .der. Pour ne pas confondre clés et certificats, certains ont choisi d’utiliser l’extension .cer pour les certificats.

L’extension .cer est ici un faux amis car il ne désigne pas l’encodage CER mais le fait qu’il s’agisse d’un certificat car il reste encodé en DER (j’insiste mais c’est pour la bonne cause).

Format texte

Bien sûr, les formats binaires précédents (DER et donc les PKCS) sont très bien adaptés au stockage et aux transmissions réseau, mais ils deviennent complètements inutilisables si vous ne pouvez utiliser que du texte lisible (i.e. dans un terminal ou un formulaire web).

Comfreak @ pixabay
Comfreak @ pixabay

Pour ces cas là, plutôt que d’inventer un nouveau format, les ingénieurs ont été au plus court en réutilisant la méthode déjà mise au point pour s’échanger des mails chiffrés, la RFC 1421 « Privacy Enhanced Mail » (PEM) : encoder le binaire en base64 et encadrer le contenu par une première ligne d’en-tête (e.g. -----BEGIN CERTIFICATE-----) et une dernière ligne de clôture (e.g. -----END CERTIFICATE-----).

Notez qu’il s’agissait à l’époque de la récupération complètement anarchique d’un truc qui marche. Les applications ont chacune défini leur « format PEM » en s’inspirant du PEM original (qui ne prévoyait pas de stocker des clés et certificats). L’idée à fait son chemin et face à tant de succès, l’IETF a normalisé tout ça en 2015 (RFC 7468).

Lorsque les certificats et les clés sont exportées après encodage en base64, on les rencontre donc dans des fichiers .pem. Pour éviter de confondre les fichiers, on préfère généralement enregistrer les certificats dans des fichiers .crt. Et, plus rarement mais c’est ce qu’on préfère chez les arsouyes, sauvegarder les clés dans des fichiers .key.

Ce sont ces fichiers que vous rencontrerez le plus souvent car ce sont ceux utilisés par la plupart des serveurs. Que ce soit en téléversant les fichiers directement (i.e. Matomo, GitLab ou ESXi), ou en copiant leur contenu dans leur interface web (i.e. pfSense et VitalPBX).

Pour ne rien arranger, lorsque vous ajoutez un certificat racine sur une machine ubuntu, vous pouvez téléverser un fichier .crt (dans /usr/local/share/ca-certificates), puis demander à ca-certificates de l’intégrer (avec update-ca-certificates). Ils créera alors un lien symbolique (dans /etc/ssl/certs) dont l’extension est .pem (mais pointe bien vers votre .crt).

Et après ?

Techniquement, il ne s’agit que de stocker deux type de données : des certificats et des clés privées. Et de les stocker de deux manières : en binaire ou sous forme de texte. Ensuite, toutes les combinaisons sont possibles :

Format Binaire Format Texte
Contenu générique .der .pem
Certificats .p7b, .p10, .cer (X.509) .crt (X.509)
Clés .p8 (rare), .p12 (clé + certificat) .key

Si vous rencontrez du .der ou du .pem, ça vous dit comment c’est stocké (en binaire ou en texte). C’est plus souvent des clés mais comme ça peut parfois contenir un certificat... Pour en être sûr, regardez autour, si vous trouvez mention de fichier .cer ou .crt, ces nouveaux sont des certificat et les premiers fichiers étaient vraisemblablement des clés.

Si vous avez le fichier sous la main, vous pouvez aussi utiliser la commande file qui vous dira si votre fichier contient un certificat ou une clé et comment il est encodé.

Notre conseil, si vous devez sauvegarder vos propres fichiers, préférez-leur les extensions spécifiques. Si vous stockez en binaire, préférez la série des PKCS (.p7, .p8, .p10 et .p12). Et si vous stockez sous forme de texte, préférez .crt et .key. Comme ça, vos collègues ou lecteurs auront plus facile à s’y retrouver.