<!-- https://pkizerotohero.com/handbook/file-formats/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> What PEM, DER, PKCS #12 (PFX), PKCS #7 (P7B), PKCS #8 and Java keystores contain, what file extensions really mean, and how to convert between them.

Source: https://pkizerotohero.com/handbook/file-formats/ · Last reviewed: 2026-10-20

Appendix

# File formats: PEM, DER, PKCS #12 and friends

**In one sentence:**

The formats are wrappings of the same data: DER is binary, PEM is DER in Base64, PKCS #12 bundles a key with its certificates, and PKCS #7 carries certificates only.

## Who is this for

- [Developer](https://pkizerotohero.com/start/#developer)
- [IT ops](https://pkizerotohero.com/start/#itops)
- [Expert](https://pkizerotohero.com/start/#expert)
- [Beginner](https://pkizerotohero.com/start/#beginner)

Level: **Practitioner**

A certificate is one fixed structure defined in [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280). The file formats below are only different ways of storing or packing it, sometimes together with a private key or other certificates. Once you know which wrapping you have, converting is one command.

## What is the actual data inside?

Certificates, CSRs, CRLs and keys are described in [ASN.1](https://pkizerotohero.com/handbook/glossary/#asn1) and stored as bytes using DER, the Distinguished Encoding Rules. DER always gives exactly one byte sequence for a given value, which matters because a signature is computed over those exact bytes. A DER certificate usually starts with the bytes `30 82`: an ASN.1 SEQUENCE followed by a two-byte length.

```bash
od -An -tx1 -N4 cert.der
```

```text
 30 82 01 b2
```

## What are the main formats?

| Format | Encoding | What it holds | Typical extensions | Where you meet it |
| --- | --- | --- | --- | --- |
| [DER](https://pkizerotohero.com/handbook/glossary/#der) | Binary | One certificate, CSR, CRL or key | `.der`, `.cer`, `.crt` | Windows, Java, embedded devices |
| [PEM](https://pkizerotohero.com/handbook/glossary/#pem) | Text: Base64 of DER between `-----BEGIN …-----` and `-----END …-----` lines | One or more objects, each with a label | `.pem`, `.crt`, `.cer`, `.key`, `.csr` | OpenSSL, nginx, Apache, Linux, Kubernetes secrets |
| [PKCS #12](https://pkizerotohero.com/handbook/glossary/#pkcs12) (PFX) | Binary, password-protected | A private key plus its certificate and chain | `.p12`, `.pfx` | Windows and IIS import and export, Java keystores, cloud services |
| [PKCS #7](https://pkizerotohero.com/handbook/glossary/#pkcs7) (P7B) | Binary or PEM | Certificates (and CRLs) only, no private key | `.p7b`, `.p7c` | Windows chain exports, some CAs’ downloads |
| [PKCS #8](https://pkizerotohero.com/handbook/glossary/#pkcs8) | Usually PEM | One private key, optionally encrypted | `.key`, `.pem` | Any modern library |
| PKCS #10 | Usually PEM | A certificate signing request | `.csr`, `.req` | Requests sent to a CA |
| JKS | Binary, Java only | Keys and trusted certificates | `.jks`, `.keystore` | Older Java applications |

### PEM: DER with a label

[RFC 7468](https://www.rfc-editor.org/rfc/rfc7468) standardises the PEM labels. The label tells you what is inside:

| PEM label | What it contains | Defined in |
| --- | --- | --- |
| `CERTIFICATE` | An X.509 certificate | RFC 5280 |
| `X509 CRL` | A certificate revocation list | RFC 5280 |
| `CERTIFICATE REQUEST` | A PKCS #10 CSR | RFC 2986 |
| `PKCS7` and `CMS` | A PKCS #7 or CMS structure, such as a certificate bundle | RFC 2315, RFC 5652 |
| `PRIVATE KEY` | An unencrypted PKCS #8 private key | RFC 5208, RFC 5958 |
| `ENCRYPTED PRIVATE KEY` | A password-protected PKCS #8 private key | RFC 5958 |
| `PUBLIC KEY` | A public key on its own (SubjectPublicKeyInfo) | RFC 5280 |

You will also see labels outside that list. `RSA PRIVATE KEY` and `EC PRIVATE KEY` are older “traditional” key formats (PKCS #1 for RSA, SEC 1 for elliptic curves) that OpenSSL still reads and can still write:

```bash
openssl genrsa -out rsa.key 2048 && head -1 rsa.key
openssl genrsa -traditional -out rsa-old.key 2048 && head -1 rsa-old.key
```

```text
-----BEGIN PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
```

A PEM file can hold several objects one after another. A “full chain” file is the server certificate first, then each intermediate in order. Leave the root out: the client must already have it. RFC 7468 also allows text before the `BEGIN` line, which is why some tools write “Bag Attributes” lines there; most software ignores them.

### PKCS #12 and PFX: the identity in one file

[RFC 7292](https://www.rfc-editor.org/rfc/rfc7292) defines PKCS #12. PFX is the older name for the same format; Windows still uses the `.pfx` extension. A PKCS #12 file can hold a private key, its certificate, the chain and a friendly name, all protected by a password. That makes it the usual way to move a server identity between systems, and also the file to guard most carefully.

```bash
openssl pkcs12 -in bundle.p12 -info -noout -passin pass:changeit
```

```text
MAC: sha256, Iteration 2048
MAC length: 32, salt length: 8
PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256
Certificate bag
PKCS7 Data
Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256
```

“Certificate bag” and “Shrouded Keybag” are the certificate and the encrypted private key. OpenSSL 3 protects both with AES-256 by default. Some older systems only open the legacy format, which `-legacy` produces; it protects the certificates with 40-bit RC2, which is weak, so use it only when you have no choice.

### PKCS #7 and P7B: certificates without a key

A `.p7b` file is a PKCS #7 (or CMS, [RFC 5652](https://www.rfc-editor.org/rfc/rfc5652)) `SignedData` structure that carries certificates but no signature and no key. It is a convenient way to ship a whole chain. To use it with OpenSSL-based software, unpack it into PEM certificates:

```bash
openssl pkcs7 -in bundle.p7b -print_certs -noout
```

```text
subject=CN=www.example.com
issuer=CN=www.example.com
```

Add `-inform DER` if the file is binary, and replace `-noout` with `-out certs.pem` to write the certificates out.

### Java keystores: JKS and PKCS #12

Java stores keys and trusted certificates in a keystore. The old Java-only format is JKS. Since JDK 9 the default keystore type is PKCS #12, the same standard format as above, so a `.p12` file from OpenSSL can be used directly as a Java keystore. Each entry has an alias and is either a `PrivateKeyEntry` (a key with its certificate chain) or a `trustedCertEntry` (a CA certificate to trust). keytool itself recommends moving away from JKS; the [cheat sheet](https://pkizerotohero.com/handbook/cheat-sheet/#how-do-i-look-inside-a-java-keystore) has the conversion command and its warning text.

## What do the file extensions mean?

Less than you would hope. An extension is a convention, not a promise:

- **`.crt` and `.cer`** usually hold one certificate, but it can be PEM or DER. Windows’ certificate export offers both “DER encoded binary” and “Base-64 encoded” under the same `.cer` extension.
- **`.pem`** says the file is text with `BEGIN` lines. It can hold certificates, keys or both.
- **`.key`** usually holds a PEM private key, encrypted or not.
- **`.p12` and `.pfx`** are the same format.
- **`.p7b` and `.p7c`** hold certificate bundles without keys.

So look inside instead. If the first line starts with `-----BEGIN`, it is PEM, and the label tells you the rest. If not, it is binary: try `openssl x509 -inform DER`, then `openssl pkcs12 -info`, then `openssl pkcs7 -inform DER`. On Linux and in Git Bash, `file` often recognises certificates:

```bash
file -b cert.pem cert.der req.csr
```

```text
PEM certificate
Certificate, Version=3
PEM certificate request
```

Do not trust `file` blindly for keys: it can mislabel a PEM private key. The `BEGIN` line is more reliable.

## How do I convert between them?

| From | To | Command |
| --- | --- | --- |
| PEM certificate | DER | `openssl x509 -in cert.pem -outform DER -out cert.der` |
| DER certificate | PEM | `openssl x509 -in cert.der -inform DER -out cert.pem` |
| PEM key + certificate + chain | PKCS #12 | `openssl pkcs12 -export -in cert.pem -inkey key.pem -certfile chain.pem -out bundle.p12` |
| PKCS #12 | PEM certificates | `openssl pkcs12 -in bundle.p12 -nokeys -out certs.pem` |
| PKCS #12 | PEM key | `openssl pkcs12 -in bundle.p12 -nocerts -noenc -out key.pem` |
| PKCS #7 / P7B | PEM certificates | `openssl pkcs7 -in bundle.p7b -print_certs -out certs.pem` |
| PEM certificates | PKCS #7 / P7B | `openssl crl2pkcs7 -nocrl -certfile certs.pem -out bundle.p7b` |
| Traditional RSA or EC key | PKCS #8 | `openssl pkey -in old.key -out key.pem` |
| PKCS #8 key | Encrypted PKCS #8 | `openssl pkey -in key.pem -aes256 -out key-enc.pem` |
| Private key | Its public key | `openssl pkey -in key.pem -pubout -out pub.pem` |
| DER | Base64 (Windows) | `certutil -encode cert.der cert-b64.cer` |
| JKS | PKCS #12 | `keytool -importkeystore -srckeystore old.jks -destkeystore new.p12 -deststoretype PKCS12` |

Every command in this table was run for this page. `-noenc` writes an unencrypted key, so protect the result (`chmod 600` on Linux) and delete copies you no longer need.

Common mistake

A format is not a security level

Converting a certificate from PEM to DER, or packing it into a PFX, changes nothing about what it proves. The certificate is public in every format. Only the private key is secret, and only formats that contain a key (PKCS #12, PKCS #8, the traditional key files) need protecting. A PFX password protects the key inside; it does not make the certificate any more trustworthy.

Paste any PEM certificate into the decoder to see the fields inside it:

*Interactive tool: Certificate decoder (runs in the browser at [/tools/decoder/](https://pkizerotohero.com/tools/decoder/))*

## Go deeper

- [RFC 7468](https://www.rfc-editor.org/rfc/rfc7468): the PEM textual encodings and their labels.
- [RFC 7292](https://www.rfc-editor.org/rfc/rfc7292): PKCS #12, the personal information exchange format.
- [RFC 5958](https://www.rfc-editor.org/rfc/rfc5958): asymmetric key packages, the successor to the PKCS #8 definition in [RFC 5208](https://www.rfc-editor.org/rfc/rfc5208).
- [RFC 5652](https://www.rfc-editor.org/rfc/rfc5652): the Cryptographic Message Syntax, the modern form of PKCS #7.
- [OpenSSL `pkcs12` manual](https://docs.openssl.org/3.2/man1/openssl-pkcs12/) and [Java `keytool` documentation](https://docs.oracle.com/en/java/javase/21/docs/specs/man/keytool.html): every option for building and reading keystores.
- [Chapter 8](https://pkizerotohero.com/handbook/x509-certificates/) explains the fields inside every certificate, whatever its wrapping.

**Early edition.** Checked against the standards; an independent expert review is in progress. Found a mistake? [Tell us](https://pkizerotohero.com/contact/?topic=content-error&page=/handbook/file-formats/).

Last reviewed 20 October 2026Edition 0.9

## Keep going

### How-to guides

- [How to inspect a certificate with OpenSSL](https://pkizerotohero.com/guides/inspect-certificate-openssl/)
- [How to create a CSR with Java keytool](https://pkizerotohero.com/guides/create-csr-java-keytool/)
- [How to convert PFX (PKCS #12) to PEM and back](https://pkizerotohero.com/guides/convert-pfx-pem/)
- [How to convert between DER and PEM](https://pkizerotohero.com/guides/convert-der-pem/)
- [How to convert a Java keystore (JKS) to PKCS #12](https://pkizerotohero.com/guides/convert-jks-pkcs12/)
- [How to build the full chain file your server needs](https://pkizerotohero.com/guides/build-fullchain/)
- [How to install a certificate in Tomcat and other Java servers](https://pkizerotohero.com/guides/install-certificate-tomcat/)

### Tools

- [Certificate decoder](https://pkizerotohero.com/tools/decoder/): Paste a PEM certificate and read every field in plain words.

### Topics

- [Certificates](https://pkizerotohero.com/topics/certificates/)
