PEM vs DER — Certificate & Key Encoding Compared

Every X.509 certificate, RSA key, and CSR is ultimately ASN.1 DER-encoded binary data. But how you store and transmit that data depends on the encoding format: DER (binary) or PEM (Base64 ASCII). They contain the same data — the difference is purely in the encoding wrapper. Choosing the wrong format causes "invalid certificate" errors, failed TLS handshakes, and smart card personalization failures. This guide covers everything you need to know.

Try it now: Use our X.509 Certificate Parser to decode both PEM and DER certificates, or the Base64 Encoder to convert between formats.

Specs at a Glance

PropertyPEMDER
Full namePrivacy-Enhanced MailDistinguished Encoding Rules
EncodingBase64-encoded ASCII textRaw binary
Line length64 chars per line (RFC 1421)N/A (binary)
HeadersYes: -----BEGIN ...----- / -----END ...-----No headers
Human-readablePartially (headers visible, content is Base64)No (binary)
Typical file size~33% larger than DERSmallest possible
File extensions.pem, .crt, .cer, .key, .csr.der, .cer, .crt, .key
Multi-object supportYes (concatenate multiple PEM blocks)No (one object per file)
StandardRFC 7468 (originally RFC 1421)ITU-T X.690

1. DER — The Binary Format

DER (Distinguished Encoding Rules) is the actual encoding of ASN.1 data. It produces a single canonical binary representation. Every X.509 certificate, RSA key, and CSR is DER-encoded at its core.

DER Structure

DER = Tag || Length || Value (TLV encoding)

Example: An X.509 certificate in DER starts with:
  30 82 03 E7   → SEQUENCE, length 0x03E7 (999 bytes)
    30 82 03 A3 → SEQUENCE (tbsCertificate)
      A0 03     → [0] (version = v3)
        02 01 02 → INTEGER 2
      02 08     → INTEGER (serial number)
        4A 3B C8 ...
    ...

DER is used by:

2. PEM — The Text Format

PEM wraps DER data in Base64 encoding with text headers. This makes it safe for email, copy-paste, configuration files, and any text-based protocol.

PEM Structure

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKQb8v3m5JUmMA0GCSqGSIb3DQEBCwUAMFUxCzAJ
BgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4g
RnJhbmNpc2NvMQ8wDQYDVQQKDAZDYXJkV2lzZT...
-----END CERTIFICATE-----

The Base64 content between the headers is the exact same DER data, just encoded in Base64 (per RFC 4648). No data is added or lost in conversion.

Common PEM Header Types

PEM HeaderContentASN.1 Type
BEGIN CERTIFICATEX.509 certificateCertificate
BEGIN CERTIFICATE REQUESTPKCS#10 CSRCertificationRequest
BEGIN RSA PRIVATE KEYRSA private key (PKCS#1)RSAPrivateKey
BEGIN PRIVATE KEYPrivate key (PKCS#8, algorithm-agnostic)PrivateKeyInfo
BEGIN EC PRIVATE KEYEC private key (SEC 1)ECPrivateKey
BEGIN PUBLIC KEYPublic key (PKCS#1 / X.509 SubjectPublicKeyInfo)SubjectPublicKeyInfo
BEGIN ENCRYPTED PRIVATE KEYEncrypted PKCS#8 private keyEncryptedPrivateKeyInfo
BEGIN PKCS7PKCS#7 / CMS messageSignedData / EnvelopedData
BEGIN X509 CRLCertificate Revocation ListCertificateList
BEGIN TRUSTED CERTIFICATECertificate with trust settings (OpenSSL)Certificate + trust info

3. Key Differences in Practice

Multi-Object Files

PEM supports multiple objects in one file by concatenating PEM blocks. This is how certificate chains work:

-----BEGIN CERTIFICATE-----
... (server certificate) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (intermediate CA) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (root CA) ...
-----END CERTIFICATE-----

DER can only hold one object per file. For certificate chains in DER, you need separate files or a PKCS#7/CMS container.

File Extension Confusion

.crt and .cer are ambiguous! Both extensions are used for both PEM and DER files. There is no standard mapping. You must inspect the file content to determine the format: if it starts with -----BEGIN, it's PEM; if it starts with binary bytes like 30 82, it's DER.
ExtensionUsually PEMUsually DERAmbiguous?
.pemYesNoNo
.derNoYesNo
.crtOftenOftenYes
.cerOftenOften (Windows)Yes
.keyOftenOftenYes
.csrOftenOftenYes
.p7b / .p7cYes (PKCS#7 PEM)Yes (PKCS#7 DER)Yes
.p12 / .pfxNoYes (PKCS#12 binary)No

4. Smart Card and PKI Use Cases

ContextFormatWhy
PIV/CAC card storageDERSmart card file system stores binary DER directly
EMV issuer certificateDERCard chip stores DER in AIP/AFL records
GlobalPlatform secure channelDERSCP02/SCP03 keys and data in DER
Nginx / Apache TLSPEMWeb servers read PEM config files
OpenSSL CLI defaultPEMopenssl x509 outputs PEM by default
Java KeyStore importDERkeytool -import expects DER by default
Windows Certificate StoreDERWindows uses DER internally; double-click .crt imports as DER
Kubernetes secretsPEMK8s TLS secrets expect PEM format
AWS IAM certificatesPEMAWS console and CLI require PEM
Apple iOS provisioning profilesDER.mobileprovision uses DER-encoded CMS

5. OpenSSL Conversion Commands

Certificate: PEM → DER

openssl x509 -in cert.pem -outform DER -out cert.der

Certificate: DER → PEM

openssl x509 -in cert.der -inform DER -outform PEM -out cert.pem

Private Key: PEM → DER (PKCS#8)

openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out key.der -nocrypt

Private Key: DER → PEM (PKCS#8)

openssl pkcs8 -inform DER -outform PEM -in key.der -out key.pem -nocrypt

RSA Key: PEM (PKCS#1) → DER

openssl rsa -in rsa_key.pem -outform DER -out rsa_key.der

CSR: PEM → DER

openssl req -in request.pem -outform DER -out request.der

CSR: DER → PEM

openssl req -in request.der -inform DER -outform PEM -out request.pem

Detect format

# Check if file is PEM (starts with "-----BEGIN")
head -1 cert.pem
# → -----BEGIN CERTIFICATE-----

# Check if file is DER (starts with 0x30 = SEQUENCE)
xxd cert.der | head -1
# → 00000000: 3082 03e7 3082 ...

6. Python: PEM/DER Conversion

import base64

def pem_to_der(pem_text: str) -> bytes:
    """Convert PEM text to DER binary data."""
    lines = pem_text.strip().split('\n')
    # Remove header and footer lines
    b64_lines = [l.strip() for l in lines
                 if not l.startswith('-----')]
    b64_data = ''.join(b64_lines)
    return base64.b64decode(b64_data)

def der_to_pem(der_data: bytes, label: str = "CERTIFICATE") -> str:
    """Convert DER binary data to PEM text."""
    b64 = base64.b64encode(der_data).decode('ascii')
    lines = [b64[i:i+64] for i in range(0, len(b64), 64)]
    result = f"-----BEGIN {label}-----\n"
    result += '\n'.join(lines) + '\n'
    result += f"-----END {label}-----\n"
    return result

# Example
der = pem_to_der(open('cert.pem').read())
pem = der_to_pem(der, 'CERTIFICATE')
print(f"DER length: {len(der)} bytes")
print(pem[:80] + '...')

7. JavaScript: PEM/DER Conversion

// PEM → DER (Uint8Array)
function pemToDer(pem) {
    const b64 = pem
        .replace(/-----BEGIN.*?-----/g, '')
        .replace(/-----END.*?-----/g, '')
        .replace(/\s/g, '');
    const binary = atob(b64);
    const bytes = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
        bytes[i] = binary.charCodeAt(i);
    }
    return bytes;
}

// DER → PEM
function derToPem(der, label = 'CERTIFICATE') {
    let binary = '';
    for (let i = 0; i < der.length; i++) {
        binary += String.fromCharCode(der[i]);
    }
    const b64 = btoa(binary);
    const lines = b64.match(/.{1,64}/g) || [];
    return `-----BEGIN ${label}-----\n` +
           lines.join('\n') + '\n' +
           `-----END ${label}-----\n`;
}

// Usage with Web Crypto API
async function importPemCertificate(pem) {
    const der = pemToDer(pem);
    return await crypto.subtle.importCertificate(
        'x509', der, {}, ['verify']
    );
}

8. Common Errors and Fixes

Error: "PEM routines::no start line" — You're trying to read a DER file as PEM. Solution: add -inform DER to your OpenSSL command, or convert to PEM first.
Error: "wrong tag" — You're trying to read a PEM file as DER. Solution: remove the -inform DER flag, or convert PEM to DER first.
Error: "unable to load certificate" — The file is corrupted or the wrong format. Check: (1) Is it PEM or DER? (2) Are the BEGIN/END headers intact? (3) Is there extra whitespace? (4) Is the file truncated?
Error: "bad base64 decode" — The PEM file has invalid Base64 characters. Common causes: Windows line endings with extra CR bytes, non-ASCII characters mixed in, or the file was edited in a word processor that added smart quotes.

9. Summary — Which to Use?

If you need…UseWhy
Web server TLS config (Nginx/Apache)PEMWeb servers read PEM by default
Smart card certificate storageDERCards store binary, no text parsing needed
Email / copy-paste certificatePEMSafe for text-based transmission
Windows Certificate Store importDERWindows uses DER internally
Kubernetes / Docker TLS secretsPEMK8s expects PEM in secrets
Certificate chain filePEMMultiple PEM blocks in one file
Java KeyStore importDERkeytool defaults to DER
Minimal file sizeDER33% smaller than PEM
Git / version controlPEMText-based, diff-friendly
Rule of thumb: Use PEM for anything that humans touch (config files, emails, Git repos, web servers). Use DER for anything that machines read natively (smart cards, Windows cert store, Java keystores). They're the same data — just different wrappers.

For related tools, see our X.509 Certificate Parser, ASN.1 DER Parser, and Base64 Encoder. For a deeper dive, read our X.509 Certificates Explained guide.