Skip to content
ecdsa.com

PEM vs DER: the same certificate in text or binary

DER is the binary ASN.1 encoding that certificates and keys are defined in. PEM is that same DER, base64-encoded between BEGIN and END lines. Converting changes nothing inside.

PEM vs DER is not a choice of different data: a certificate, key, CSR or CRL is always defined as DER-encoded ASN.1, and PEM is a text wrapper around those exact bytes. The question is which representation a tool, protocol or platform expects, and how to recognize and convert each one.

At a glance

DERPEM
What it isDistinguished Encoding Rules of ASN.1 (ITU-T X.690): binary tag-length-valueRFC 7468 text: base64 of DER between labels
Starts withByte 0x30 (SEQUENCE) for certificates and keys-----BEGIN CERTIFICATE-----, -----BEGIN PRIVATE KEY-----, etc.
Size (P-256 certificate, measured)389 bytes583 bytes (about 4/3 plus line breaks and labels)
Objects per fileOneAny number of blocks (chains, key plus certificate)
Self-describingNo label; type known from contextLabel names the structure
Common extensions.der, .cer, .crt (ambiguous).pem, .crt, .cer, .key, .csr (ambiguous)
FingerprintSHA-256 of these bytesSame value: fingerprints are computed over the DER inside
Safe in email, YAML, environment variablesNoYes

What each one is

DER is the canonical binary encoding of ASN.1 data: every value is a tag, a length and contents, with exactly one valid encoding per value. That canonical property is why signatures work: a certificate's signature covers the DER bytes of its tbsCertificate, and verifiers re-encode nothing.

PEM (named after the 1993 Privacy-Enhanced Mail standard and specified for PKIX objects in RFC 7468) wraps those bytes in standard base64, conventionally 64 characters per line, between a BEGIN and an END line that name the structure: CERTIFICATE, X509 CRL, CERTIFICATE REQUEST, PUBLIC KEY, PRIVATE KEY, ENCRYPTED PRIVATE KEY, plus OpenSSL's legacy RSA PRIVATE KEY and EC PRIVATE KEY. Text before, between or after blocks is ignored, which is how bundles with comments and openssl x509 -text output work.

Converting and checking

The script below, run with OpenSSL 3.6.5, creates a throwaway certificate and shows that both encodings carry the same object.

OpenSSL: one certificate in PEM and 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"
Output
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:

The same pattern applies to keys (openssl pkey -in key.pem -outform DER), CSRs (openssl req -outform DER) and CRLs (openssl crl -outform DER). To tell an unknown file apart: if it starts with -----BEGIN, it is PEM; if xxd file | head -1 shows 3082 near the start, it is almost certainly DER.

Typical errors

  • no start line / Expecting: TRUSTED CERTIFICATE from OpenSSL: the tool expected PEM and got DER, or a PEM block with a different label. Add -inform DER or check the label.
  • header too long / wrong tag: the tool expected DER and got PEM text, or a truncated file.
  • Windows line endings or stray spaces inside a PEM block pasted into a web form or YAML; strict parsers reject them. Re-encode rather than editing by hand.
  • A PEM bundle where one certificate was expected: many tools read only the first block, so the order matters (leaf first for servers).
  • Base64url instead of base64: PEM uses the standard alphabet with +, / and padding; JOSE and WebAuthn use base64url. A certificate copied out of a JWK x5c member is standard base64 DER, and wrapping it in PEM lines makes it a valid PEM file.

The ASN.1 explorer accepts either encoding and shows the structure, and the PEM bundle splitter separates multi-certificate files.

Bundles and chains

Because DER holds exactly one object, anything that needs several objects in one file uses PEM concatenation or a container format. A server's fullchain.pem is the leaf certificate followed by intermediates; a CA bundle such as /etc/ssl/certs/ca-certificates.crt is hundreds of root certificates in one PEM file. The DER-based alternatives are PKCS #7 certificate bundles (.p7b, a CMS SignedData with no content and only certificates, common on Windows) and PKCS #12 (.pfx) when a private key travels with the chain. Converting a .p7b to PEM is openssl pkcs7 -print_certs -in bundle.p7b, which writes each certificate as its own PEM block.

Order and completeness matter more than encoding: a server must send its leaf first and every intermediate needed to reach a root that clients trust, and a missing intermediate breaks clients that do not fetch it themselves, whatever the file format.

When to choose which

  • Web servers, reverse proxies, ACME clients: PEM (fullchain.pem, privkey.pem).
  • Java (keytool -importcert, CertificateFactory): either, but DER is the canonical input; keystores use PKCS #12 for key plus chain.
  • Windows certificate import: DER .cer or PEM-encoded .cer; key plus certificate goes into .pfx.
  • Embedding in source code, environment variables, Kubernetes secrets: PEM text (or base64 DER, if a field demands it).
  • Wire protocols and binary containers: DER, always; TLS, CMS, OCSP and X.509 extensions never carry PEM.
  • Archival and audit: DER for byte-exact storage; PEM if humans need to inspect files.

Migration notes

There is nothing to migrate in the cryptographic sense; switching encodings is a deployment detail.

  1. Standardize file naming: .pem for PEM, .der for DER, and avoid ambiguous .crt and .cer in your own tooling.
  2. Convert at deployment time, keeping one source of truth (usually PEM) in your repository or secret store.
  3. Check fingerprints after conversion with openssl x509 -noout -fingerprint -sha256; they must match.
  4. For private keys, keep encryption on: openssl pkey -outform DER writes an unencrypted key unless you pass a cipher, and DER keys are often handled by tools with fewer warnings.
  5. Document expected formats in configuration (ssl_certificate expects PEM; Java truststores expect DER or PKCS #12), since most format errors come from guessing.

References

All comparisons