PEM vs DER n’est pas un choix entre des données différentes : un certificat, une clé, une CSR ou une CRL est toujours défini comme de l’ASN.1 encodé en DER, et PEM est une enveloppe texte autour de ces mêmes octets. La question est de savoir quelle représentation attend un outil, un protocole ou une plateforme, et comment reconnaître et convertir chacune d’elles.
Vue d’ensemble
| DER | PEM | |
|---|---|---|
| Nature | Distinguished Encoding Rules d’ASN.1 (ITU-T X.690) : tag-longueur-valeur en binaire | Texte RFC 7468 : base64 du DER entre des libellés |
| Commence par | L’octet 0x30 (SEQUENCE) pour les certificats et les clés | -----BEGIN CERTIFICATE-----, -----BEGIN PRIVATE KEY-----, etc. |
| Taille (certificat P-256, mesurée) | 389 octets | 583 octets (environ 4/3, plus les sauts de ligne et les libellés) |
| Objets par fichier | Un seul | Un nombre quelconque de blocs (chaînes, clé plus certificat) |
| Autodescriptif | Aucun libellé ; type déduit du contexte | Le libellé nomme la structure |
| Extensions courantes | .der, .cer, .crt (ambiguës) | .pem, .crt, .cer, .key, .csr (ambiguës) |
| Empreinte | SHA-256 de ces octets | Même valeur : les empreintes sont calculées sur le DER contenu |
| Transportable dans un e-mail, du YAML, des variables d’environnement | Non | Oui |
Ce qu’est chacun
DER est l’encodage binaire canonique des données ASN.1 : chaque valeur est un tag, une longueur et un contenu, avec exactement un encodage valide par valeur. C’est cette propriété canonique qui fait fonctionner les signatures : la signature d’un certificat porte sur les octets DER de son tbsCertificate, et les vérificateurs ne réencodent rien.
PEM (son nom vient de la norme Privacy-Enhanced Mail de 1993, une messagerie à confidentialité renforcée, et la RFC 7468 le spécifie pour les objets PKIX) enveloppe ces octets en base64 standard, par convention à raison de 64 caractères par ligne, entre une ligne BEGIN et une ligne END qui nomment la structure : CERTIFICATE, X509 CRL, CERTIFICATE REQUEST, PUBLIC KEY, PRIVATE KEY, ENCRYPTED PRIVATE KEY, ainsi que les anciens libellés d’OpenSSL RSA PRIVATE KEY et EC PRIVATE KEY. Le texte placé avant, entre ou après les blocs est ignoré : c’est ce qui permet les bundles commentés et la sortie de openssl x509 -text.
Conversion et vérification
Le script ci-dessous, exécuté avec OpenSSL 3.6.5, crée un certificat jetable et montre que les deux encodages transportent le même objet.
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
openssl req -new -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout key.pem \
-subj "/CN=example.com" -days 30 -out cert.pem 2>/dev/null
openssl x509 -in cert.pem -outform DER -out cert.der
printf 'cert.pem %s bytes, cert.der %s bytes\n' "$(wc -c < cert.pem | tr -d ' ')" "$(wc -c < cert.der | tr -d ' ')"
head -1 cert.pem
openssl x509 -in cert.der -inform DER -noout -fingerprint -sha256 | cut -c1-40
openssl x509 -in cert.pem -noout -fingerprint -sha256 | cut -c1-40
cd / && rm -rf "$dir"
cert.pem 583 bytes, cert.der 389 bytes
-----BEGIN CERTIFICATE-----
sha256 Fingerprint=FE:8B:DC:19:30:EE:A8:
sha256 Fingerprint=FE:8B:DC:19:30:EE:A8:
Le même procédé s’applique aux clés (openssl pkey -in key.pem -outform DER), aux CSR (openssl req -outform DER) et aux CRL (openssl crl -outform DER). Pour identifier un fichier inconnu : s’il commence par -----BEGIN, c’est du PEM ; si xxd file | head -1 affiche 3082 près du début, c’est presque certainement du DER.
Erreurs typiques
no start line/Expecting: TRUSTED CERTIFICATErenvoyés par OpenSSL : l’outil attendait du PEM et a reçu du DER, ou un bloc PEM portant un autre libellé. Ajoutez-inform DERou vérifiez le libellé.header too long/wrong tag: l’outil attendait du DER et a reçu du texte PEM, ou un fichier tronqué.- Fins de ligne Windows ou espaces parasites dans un bloc PEM collé dans un formulaire web ou dans du YAML ; les analyseurs stricts les rejettent. Réencodez plutôt que de corriger à la main.
- Un bundle PEM là où un seul certificat était attendu : de nombreux outils ne lisent que le premier bloc, l’ordre compte donc (le certificat feuille en premier pour les serveurs).
- Base64url au lieu de base64 : PEM utilise l’alphabet standard avec
+,/et le remplissage ; JOSE et WebAuthn utilisent base64url. Un certificat copié depuis le membrex5cd’une JWK est du DER en base64 standard, et l’envelopper dans des lignes PEM en fait un fichier PEM valide.
L’explorateur ASN.1 accepte les deux encodages et affiche la structure, et le séparateur de bundles PEM découpe les fichiers qui contiennent plusieurs certificats.
Bundles et chaînes
Comme le DER contient exactement un objet, tout ce qui exige plusieurs objets dans un même fichier passe par la concaténation PEM ou par un format conteneur. Le fullchain.pem d’un serveur est le certificat feuille suivi des intermédiaires ; un bundle d’AC tel que /etc/ssl/certs/ca-certificates.crt réunit des centaines de certificats racines dans un seul fichier PEM. Les alternatives fondées sur DER sont les bundles de certificats PKCS #7 (.p7b, une structure CMS SignedData sans contenu qui ne porte que des certificats, courante sous Windows) et PKCS #12 (.pfx) lorsqu’une clé privée voyage avec la chaîne. Pour convertir un .p7b en PEM, utilisez openssl pkcs7 -print_certs -in bundle.p7b, qui écrit chaque certificat dans son propre bloc PEM.
L’ordre et l’exhaustivité comptent plus que l’encodage : un serveur doit envoyer d’abord son certificat feuille, puis chaque intermédiaire nécessaire pour remonter jusqu’à une racine à laquelle les clients font confiance, et un intermédiaire manquant fait échouer les clients qui ne le récupèrent pas eux-mêmes, quel que soit le format de fichier.
Quand choisir l’un ou l’autre
- Serveurs web, proxys inverses, clients ACME : PEM (
fullchain.pem,privkey.pem). - Java (
keytool -importcert,CertificateFactory) : l’un ou l’autre, mais DER est l’entrée canonique ; les keystores utilisent PKCS #12 pour une clé accompagnée de sa chaîne. - Import de certificats sous Windows :
.ceren DER ou.cerencodé en PEM ; une clé accompagnée de son certificat va dans un.pfx. - Intégration dans du code source, des variables d’environnement, des secrets Kubernetes : texte PEM (ou DER en base64, si un champ l’exige).
- Protocoles réseau et conteneurs binaires : DER, toujours ; TLS, CMS, OCSP et les extensions X.509 ne transportent jamais de PEM.
- Archivage et audit : DER pour un stockage exact à l’octet près ; PEM si des personnes doivent examiner les fichiers.
Notes de migration
Il n’y a rien à migrer au sens cryptographique : changer d’encodage est un détail de déploiement.
- Normalisez le nommage des fichiers :
.pempour PEM,.derpour DER, et évitez les extensions ambiguës.crtet.cerdans votre propre outillage. - Convertissez au moment du déploiement, en gardant une seule source de vérité (en général PEM) dans votre dépôt ou votre magasin de secrets.
- Vérifiez les empreintes après la conversion avec
openssl x509 -noout -fingerprint -sha256; elles doivent correspondre. - Pour les clés privées, conservez le chiffrement :
openssl pkey -outform DERécrit une clé non chiffrée à moins que vous ne précisiez un algorithme de chiffrement, et les clés DER sont souvent manipulées par des outils qui affichent moins d’avertissements. - Documentez les formats attendus dans la configuration (
ssl_certificateattend du PEM ; les truststores Java attendent du DER ou du PKCS #12), car la plupart des erreurs de format viennent de suppositions.