Aller au contenu
ecdsa.com

PEM vs DER : le même certificat en texte ou en binaire

DER est l’encodage binaire ASN.1 dans lequel sont définis les certificats et les clés. PEM est ce même DER, encodé en base64 entre des lignes BEGIN et END. La conversion ne change rien au contenu.

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

DERPEM
NatureDistinguished Encoding Rules d’ASN.1 (ITU-T X.690) : tag-longueur-valeur en binaireTexte RFC 7468 : base64 du DER entre des libellés
Commence parL’octet 0x30 (SEQUENCE) pour les certificats et les clés-----BEGIN CERTIFICATE-----, -----BEGIN PRIVATE KEY-----, etc.
Taille (certificat P-256, mesurée)389 octets583 octets (environ 4/3, plus les sauts de ligne et les libellés)
Objets par fichierUn seulUn nombre quelconque de blocs (chaînes, clé plus certificat)
AutodescriptifAucun libellé ; type déduit du contexteLe libellé nomme la structure
Extensions courantes.der, .cer, .crt (ambiguës).pem, .crt, .cer, .key, .csr (ambiguës)
EmpreinteSHA-256 de ces octetsMême valeur : les empreintes sont calculées sur le DER contenu
Transportable dans un e-mail, du YAML, des variables d’environnementNonOui

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.

OpenSSL : un même certificat en PEM et en DER
#!/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"
Sortie
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 CERTIFICATE renvoyés par OpenSSL : l’outil attendait du PEM et a reçu du DER, ou un bloc PEM portant un autre libellé. Ajoutez -inform DER ou 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 membre x5c d’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 : .cer en DER ou .cer encodé 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.

  1. Normalisez le nommage des fichiers : .pem pour PEM, .der pour DER, et évitez les extensions ambiguës .crt et .cer dans votre propre outillage.
  2. 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.
  3. Vérifiez les empreintes après la conversion avec openssl x509 -noout -fingerprint -sha256 ; elles doivent correspondre.
  4. 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.
  5. Documentez les formats attendus dans la configuration (ssl_certificate attend du PEM ; les truststores Java attendent du DER ou du PKCS #12), car la plupart des erreurs de format viennent de suppositions.

Références

Tous les comparatifs