SSL certificate formats explained: PEM, DER, P7B, PFX and JKS

Every certificate mess starts the same way: a certificate authority hands you files in one format, and the thing you are configuring demands another. The certificate inside never changes — the same public key, the same signature, the same validity dates — but the packaging differs, and servers are fussy about packaging. This guide explains each format you will meet, how to identify a mystery file from its first four bytes, which servers want which, and the shortest path between any two of them — with every conversion done in your browser, so a private key never has to leave your machine.

First, what is actually in these files?

Three kinds of material travel together in the TLS world: the certificate itself (public, sent to every visitor), the intermediate chain that links your certificate to a trusted root, and the private key (secret, never to be shared). Formats differ mainly in which of these they can carry and how they are encoded. Everything below is detail on those two axes.

FormatEncodingCan holdFirst bytesUsual extensions
PEMBase64 text (RFC 7468)Certificates, keys and CSRs — one per BEGIN/END block, any number of blocks-----BEGIN .pem .crt .cer .key
DERBinary ASN.1One certificate (or one key)30 82.der .cer .crt
P7B / PKCS#7Binary, or PEM-armouredCertificates only — never a private key30 82 … OID 2A 86 48 86 F7 0D 01 07 02, or -----BEGIN PKCS7-----.p7b .p7c
PFX / PKCS#12Binary, password-protectedCertificate, chain and private key together30 8202 01 03 (version 3).pfx .p12
JKSJava-proprietary binaryKey entries and trusted certificates, by aliasFE ED FE ED.jks .keystore

PEM — the universal text format

Open a PEM file in any text editor and you will recognise it instantly: -----BEGIN CERTIFICATE----- followed by a wall of Base64 in 64-character lines. PEM is just a binary structure wrapped in text armour, which makes it copy-pasteable into terminals, config files and web forms — the reason it became the lingua franca. Extensions vary wildly (.pem, .crt, .cer, .key) but the BEGIN line tells you what is inside: CERTIFICATE, PRIVATE KEY (PKCS#8), RSA PRIVATE KEY (the older PKCS#1 form), EC PRIVATE KEY (SEC1), ENCRYPTED PRIVATE KEY, CERTIFICATE REQUEST or PKCS7. Nginx, Apache, HAProxy and virtually every load balancer and programming language accept PEM. A fullchain.pem is simply several certificate blocks concatenated in one file, leaf first.

Tools: decode and check any certificate, and build a correctly ordered fullchain.pem from loose certificates.

DER — the same thing, in binary

DER is the raw binary encoding that PEM wraps. Strip the BEGIN/END lines, decode the Base64, and you have DER. Java tooling and some appliances ask for .der or binary .cer files. Because it is binary, opening it in a text editor shows gibberish, but the first byte is always 0x30 — the ASN.1 tag for SEQUENCE — and for any real certificate the second is 0x82, meaning “the length takes two more bytes”. Converting is a pure re-encoding with zero risk: PEM → DER parses each block and downloads one .der named after the subject (several become a ZIP), and DER → PEM wraps any number of binary files into one concatenated certificate.pem. The OpenSSL equivalents are openssl x509 -in cert.pem -outform DER -out cert.der and openssl x509 -inform DER -in cert.der -out cert.pem.

P7B / PKCS#7 — a bag of certificates, never a key

A .p7b (or .p7c) file is a container that holds one or more certificates — typically your certificate plus its intermediates — and, by design, never a private key. Technically it is a PKCS#7 SignedData structure with no content and no signers, used purely for its certificate list. Windows CAs and some enterprise portals love handing these out. Windows/IIS and Java tooling consume them directly; everything else wants the certificates unpacked to PEM first. It comes in both binary and -----BEGIN PKCS7----- flavours, and the site’s tools accept either: P7B → PEM lists the subject of every certificate inside and downloads them as one certificates.pem, PEM → P7B packs pasted certificates into a certificate.p7b, and P7B + your key → PFX finds which certificate in the bundle your key matches, puts it first and packs the rest as the chain.

PFX / P12 — the whole identity in one encrypted file

PKCS#12 (.pfx or .p12 — same thing, two extensions) is the only mainstream format that carries the certificate, the chain and the private key together, protected by a password. That makes it the import/export format of the Microsoft world — IIS, Windows certificate stores, Azure — and of Java keystores since Java 9. It is also why PFX files deserve care: whoever has the file and its password has your identity. The password derives both the key that encrypts the private-key bag and the MAC an importer checks before decrypting anything, so a lost password means a lost file.

Tools: bundle PEM + key into a PFX (it checks that the key matches the first certificate before packing, and accepts RSA and P-256/P-384/P-521 EC keys), unpack a PFX to PEM (separate certificate.pem, ca-chain.pem and private-key.pem downloads), and change or remove a PFX password — all in the browser, so the key never travels. When we built the PFX packers we chose 3DES for the key bag rather than AES on purpose: it is the one cipher every importer, including older Windows and Java versions, still accepts. The PFX guide goes deeper into what the archive holds.

JKS — Java’s own keystore

The Java KeyStore (.jks, sometimes .keystore) predates PKCS#12 support in Java and is proprietary to the JVM: nothing outside the Java ecosystem reads it natively. A genuine JKS starts with the magic bytes FE ED FE ED; its cousin JCEKS starts with CE CE CE CE. Two useful facts: first, since Java 9 keytool creates PKCS#12 files by default even when they are named .jks, so many “JKS” files actually begin with 0x30; second, escaping a real JKS normally requires installing a JDK just to run keytool -importkeystore -deststoretype PKCS12. Our JKS → PFX / PEM converter implements the JKS format natively in the browser, checks the first bytes to tell the two variants apart, lists every alias in the store, and repacks a key entry into a .pfx/.p12 or exports it as alias-chain.pem plus alias-key.pem. JCEKS is the one it cannot open; it prints the keytool command to convert it first. See the Java keystore guide for aliases and the two-password problem.

How to tell which case you are in

Text starting with -----BEGIN? PEM — the BEGIN line names the content. Binary? Do not trust the extension; look at the bytes. Two commands settle it on any Mac or Linux box:

# first four bytes, as hex
head -c 4 mystery.file | xxd
#   2d2d 2d2d  ("----")  -> PEM text: read the BEGIN line
#   3082 ....            -> ASN.1: a DER certificate, a P7B or a PFX
#   feed feed            -> JKS keystore
#   cece cece            -> JCEKS keystore (convert with keytool first)

# for the ASN.1 case, the first object identifier tells the containers apart
openssl asn1parse -inform DER -in mystery.file | head -5
#   OBJECT :pkcs7-signedData        -> P7B
#   INTEGER :03 then :pkcs7-data    -> PFX / PKCS#12
#   INTEGER (serial), then a signature OID such as sha256WithRSAEncryption -> a bare DER certificate

No terminal handy? Drop the file on the certificate checker. It ingests PEM, DER, P7B and PFX, tries a blank password on a PFX before asking for one, reads only the certificate content (the key inside a PFX stays sealed), and reports issuer, covered hostnames, key and signature algorithms and days remaining. Feed it a JKS — neither text nor ASN.1 — and it answers No "BEGIN CERTIFICATE" blocks found., which is itself the diagnosis: use the JKS converter instead.

The error messages, and what each one is telling you

Expecting: TRUSTED CERTIFICATE — OpenSSL’s PEM routines … no start line error, and Nginx’s cannot load certificate … PEM_read_bio_X509_AUX() failed wrap the same thing. A PEM reader was handed a file with no BEGIN line: a DER, a PFX, or a P7B renamed to .pem. Convert it; renaming does nothing.

key values mismatch — from Nginx or Apache at start-up (error:05800074:x509 certificate routines::key values mismatch on OpenSSL 3; 0B080074 on older builds). The certificate and key files are both readable but belong to different key pairs. The certificate ↔ key matcher derives the public key from each and compares the bytes; if the CSR you sent the CA matches the certificate but not the key, you are holding an older key file.

Invalid keystore format — Java’s java.io.IOExceptionwhen the loader’s expected type and the file’s magic bytes disagree: a PEM passed as -keystore, or a real JKS opened with -storetype PKCS12. Check the first four bytes and pass the matching store type. A PEM file fed to the PKCS#12 loader instead fails with DerInputStream.getLength(): lengthTag=109, too big.

ASN1 bad tag value met. 0x8009310b — the IIS Complete Certificate Request dialog rejecting a file in an encoding it does not expect (a PEM with text before the BEGIN line, or a PFX). Its sibling Cannot find the certificate request that is associated with this certificate file means the pending request — and so the private key — lives on another machine; no conversion fixes that, you need a PFX exported from wherever the CSR was made.

The password you entered is incorrect. — the Windows import wizard on a PFX. PKCS#12 verifies its MAC before decrypting, so one wrong character fails cleanly; suspect a keyboard-layout difference or a trailing space. If you inherited the file with a throwaway password, re-password it once you are in.

Which format does my server want?

Nginx / Apache / HAProxy

PEM. Nginx takes ssl_certificate fullchain.pem; and ssl_certificate_key privkey.pem;; Apache 2.4.8 and later accepts the whole chain in SSLCertificateFile (the separate SSLCertificateChainFile is deprecated); HAProxy’s crt option wants certificate, chain and key concatenated into one file. If the CA gave you PFX, unpack it first; if it gave you P7B, unpack that and pair the result with the key you generated alongside the CSR.

Windows / IIS / Azure

PFX. If you hold loose PEM files, bundle them; if you hold a P7B plus a key, combine those. The one exception is completing a pending request on the machine that made it — that dialog takes the CA’s P7B or certificate directly, no key needed.

Java applications

Modern Java accepts PKCS#12 directly — make a PFX and point the keystore config at it (-storetype PKCS12, or the .p12extension). Only legacy setups still insist on true JKS, and for those the JDK’s own keytool -importkeystore can import your PKCS#12.

Common mistakes

  • Renaming instead of converting. site.pfx renamed to site.pem is still binary PKCS#12; Nginx will reject it with the no start line error above. Only PEM can be produced by a text-level change, and only from PEM.
  • Trusting .cer. Windows uses that extension for both encodings, so a .cer from one machine may be DER and from the next may be PEM. The DER → PEM tool passes a file that is already PEM straight through, so it is safe to feed it either.
  • Wrong chain order, or the root included.Servers must send the leaf first, then intermediates. A wrong order or a missing intermediate “works on my machine” because desktop browsers cache intermediates, and fails on phones and in curl. The chain builder sorts by issuer link, verifies every signature and leaves the self-signed root out of fullchain.pem by default (a separate chain-with-root.pem exists for appliances that ask). The incomplete-chain guide covers the client-side errors this produces.
  • Pasting the key where the certificate goes. The PFX and matcher tools route dropped files by their BEGIN line, and the checker ignores anything that is not a CERTIFICATE block; elsewhere a key in a certificate field produces the same no start line error.
  • An encrypted EC PRIVATE KEY. A SEC1 EC key with a Proc-Type: 4,ENCRYPTED header is the one key form the packers cannot read; they stop with Encrypted SEC1 EC keys are not supported — decrypt it first: openssl ec -in key.pem -out key-plain.pem. Encrypted PKCS#8 (BEGIN ENCRYPTED PRIVATE KEY) and encrypted RSA keys open fine with their passphrase.
  • A PFX exported without its key. Windows lets you untick “export the private key”; the result is really a P7B in PFX clothing. PFX → PEM will show no private-key.pem button, and the password changer refuses with This file holds certificates but no private key — nothing to re-password. Re-export from the original machine with the key included.
  • Two Java passwords. A JKS has a store password and, per key entry, a key password. The converter tries the password you type for both roles; if they differ, run keytool -keypasswd first so they match, then convert.

Three rules that prevent most disasters

1. Order matters in chains. Leaf first, then intermediates, root omitted — verify with the checker after every change, not just after the first install. 2. The key must match. After any renewal, confirm certificate and key belong together with the matcher before restarting the server; a mismatch turns a five-second reload into an outage. 3. Never paste a private key into a website that uploads it. Every tool linked in this guide runs entirely in your browser — you can load the page, go offline, and convert — but the rule applies everywhere else too.

Do this

  • Identify a mystery file by its first four bytes (----, 30 82, FE ED FE ED) or by dropping it on the certificate checker — never by its extension.
  • Convert with the tool that matches the pair: PEM ↔ DER for encoding only, P7B ↔ PEM for certificate bundles, PEM/P7B → PFX when a key must travel with the certificate, JKS → PFX/PEM to leave Java.
  • Before packing a PFX or restarting a server, run certificate and key through the matcher.
  • Build fullchain.pem with the chain builder rather than by hand, and re-check the chain on the checker after every renewal.
  • Keep PFX files and their passwords apart, re-password any PFX that arrived with a throwaway password, and delete loose PEM key files you no longer need.

Frequently asked questions

Is a .crt file PEM or DER?

Either — the extension does not tell you. Open it in a text editor: if it starts with -----BEGIN CERTIFICATE----- it is PEM; if it is binary and the first byte is 0x30 it is DER. The same applies to .cer, which Windows uses for both encodings.

What is the difference between PFX and P12?

None. Both are PKCS#12 archives. .pfx is the extension Microsoft tooling favours and .p12 the one Java and macOS favour — you can rename one to the other freely.

Does a P7B file contain the private key?

No, never. PKCS#7 carries certificates only, which is why a CA can email you one. To get a PFX out of a P7B you have to supply the private key yourself, from the machine where the CSR was generated.

How do I convert a PFX to PEM without OpenSSL?

Open the .pfx in the PFX to PEM tool on this site. It decodes the archive in your browser and gives you certificate.pem, ca-chain.pem and private-key.pem as separate downloads — nothing is uploaded.

Why does my .jks file open as PKCS#12?

Since Java 9, keytool creates PKCS#12 keystores by default even when the filename ends in .jks. A real JKS begins with the bytes FE ED FE ED; a PKCS#12 begins with 0x30. The JKS converter checks the first bytes and handles both.

Tools used in this guide

Every one of these runs in your browser — the files you work on never leave your device.

More certificates & keys guides