# OpenSSL certificate conversion: PEM, DER, P7B, PFX and JKS

> OpenSSL 3.x and keytool commands to identify a certificate file's format and convert it between PEM, DER, PKCS#7 (.p7b), PKCS#12 (.pfx) and JKS.

Source: https://ssl.sh/cookbook/convert-formats/
Last updated: 2026-11-10

Every certificate format conversion is a single `openssl` or `keytool` command, and none of them changes the certificate itself. The formats differ only in wrapping: PEM is Base64 text, DER is binary, PKCS#7 bundles certificates, PKCS#12 bundles a key with its certificates, and JKS is Java's keystore. Outputs are from OpenSSL 3.6.1 and typical JDK 17+ keytool.

For background on why there are so many formats, read [certificate formats](https://ssl.sh/learn/certificate-formats/). PKCS#12 has its own page of options and compatibility fixes: [PKCS#12 commands](https://ssl.sh/cookbook/pkcs12/).

## Identify a file's format

Look at the first line, then let `file` or `asn1parse` confirm binary files.

```bash
head -1 server.crt server.key bundle.p7b server.csr
file server.der example.pfx
openssl asn1parse -inform DER -in example.pfx | head -3
```

```text
==> server.crt <==
-----BEGIN CERTIFICATE-----
==> server.key <==
-----BEGIN PRIVATE KEY-----
==> bundle.p7b <==
-----BEGIN PKCS7-----
==> server.csr <==
-----BEGIN CERTIFICATE REQUEST-----
server.der:  Certificate, Version=3
example.pfx: data
    0:d=0  hl=4 l=1723 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :03
    7:d=1  hl=4 l=1641 cons: SEQUENCE
```

| First line or content | Format | Typical extensions |
|---|---|---|
| `-----BEGIN CERTIFICATE-----` | PEM certificate | .pem .crt .cer |
| `-----BEGIN PRIVATE KEY-----` / `RSA PRIVATE KEY` / `EC PRIVATE KEY` | PEM private key (PKCS#8 / PKCS#1 / SEC1) | .key .pem |
| `-----BEGIN ENCRYPTED PRIVATE KEY-----` | Encrypted PKCS#8 key | .key |
| `-----BEGIN PKCS7-----` | PEM PKCS#7 bundle | .p7b .p7c |
| Binary, `file` says "Certificate" | DER certificate | .der .cer |
| Binary, asn1parse shows `INTEGER :03` then `pkcs7-data` | PKCS#12 | .pfx .p12 |

A PKCS#12 file starts with version 3; that is how `asn1parse` tells it apart from a DER certificate.

## Convert PEM to DER

`-outform DER` writes the binary encoding of the same certificate.

```bash
openssl x509 -in server.crt -outform DER -out server.der
ls -l server.crt server.der | awk '{print $5, $NF}'
```

```text
709 server.crt
483 server.der
```

DER is about three quarters the size because Base64 is gone. Windows, Java and many embedded devices accept `.cer` files in DER. A DER file holds exactly one certificate, so convert a chain one certificate at a time or use PKCS#7.

## Convert DER to PEM

`-inform DER` reads binary input; PEM is the default output.

```bash
openssl x509 -in server.der -inform DER -out server.pem
head -1 server.pem
```

```text
-----BEGIN CERTIFICATE-----
```

OpenSSL 3.x often detects DER input without `-inform`, but keep it in scripts for 1.1.1 compatibility. If the conversion fails with `wrong tag` or `not enough data`, the file is probably PKCS#7 or PKCS#12, not a bare DER certificate.

## Convert a private key between PEM and DER

Use `openssl pkey`, which works for every key type.

```bash
openssl pkey -in server.key -outform DER -out server.key.der
openssl pkey -in server.key.der -inform DER -out server.key.pem
head -1 server.key.pem
```

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

The output is PKCS#8. Add `-traditional` if the target needs `BEGIN RSA PRIVATE KEY`. DER keys are mostly used by Java (`PKCS8EncodedKeySpec`) and some hardware; web servers expect PEM.

## Convert PEM to PKCS#7 (.p7b)

`crl2pkcs7 -nocrl` packs one or more PEM certificates into a PKCS#7 bundle.

```bash
openssl crl2pkcs7 -nocrl -certfile server.crt -certfile intermediate.crt -out bundle.p7b
head -1 bundle.p7b
```

```text
-----BEGIN PKCS7-----
```

Add `-outform DER` for a binary `.p7b`, which Windows imports more reliably. PKCS#7 never contains a private key; Windows and IIS use it for "certificate chain" files, and Tomcat accepts it when installing a reply into an existing keystore.

## Convert PKCS#7 (.p7b) to PEM

`pkcs7 -print_certs` unpacks every certificate into a PEM file.

```bash
openssl pkcs7 -in bundle.p7b -print_certs -out chain.pem
# binary .p7b
openssl pkcs7 -in bundle.p7b -inform DER -print_certs -out chain.pem
grep -E "^subject|^issuer" chain.pem
```

```text
subject=CN=example.com
issuer=CN=Example Test Intermediate CA
subject=CN=Example Test Intermediate CA
issuer=CN=Example Test Root CA
```

The `subject=` and `issuer=` lines are comments that Nginx and Apache ignore. Check the order before using the result as a chain: the leaf must come first.

## Convert PEM to PFX (PKCS#12)

`pkcs12 -export` combines a key, its certificate and the chain into one password-protected file.

```bash
openssl pkcs12 -export -inkey server.key -in server.crt -certfile intermediate.crt \
  -name "example.com" -out example.pfx
```

```text
Enter Export Password:
Verifying - Enter Export Password:
```

This is what IIS, Azure, Windows certificate import and many Java servers want. OpenSSL 3.0 and later encrypt with AES-256-CBC and an SHA-256 MAC by default, which Windows Server 2016 and older Java or macOS releases may refuse; add `-legacy` for them. The details are in [PKCS#12 commands](https://ssl.sh/cookbook/pkcs12/).

## Convert PFX to PEM

`pkcs12 -noenc` writes the key and all certificates into one PEM file.

```bash
openssl pkcs12 -in example.pfx -noenc -out example-all.pem
grep -E "BEGIN|friendlyName|subject=" example-all.pem
```

```text
Enter Import Password:
    friendlyName: example.com
subject=CN=example.com
-----BEGIN CERTIFICATE-----
subject=CN=Example Test Intermediate CA
-----BEGIN CERTIFICATE-----
    friendlyName: example.com
-----BEGIN PRIVATE KEY-----
```

`-noenc` (OpenSSL 3.0+, `-nodes` before) leaves the key unencrypted; without it you are asked for a new PEM passphrase. If you get `unsupported` and `RC2-40-CBC` in the error, the PFX was made with legacy algorithms: add `-legacy`.

## Split a PFX into key, certificate and chain

Use `-nocerts`, `-clcerts` and `-cacerts` to get the three files a web server needs.

```bash
openssl pkcs12 -in example.pfx -nocerts -noenc -out example.com.key
openssl pkcs12 -in example.pfx -clcerts -nokeys -out example.com.crt
openssl pkcs12 -in example.pfx -cacerts -nokeys -out chain.crt
```

```text
Enter Import Password:
Enter Import Password:
Enter Import Password:
```

Add `-passin file:pass.txt` to avoid three prompts. The outputs start with `Bag Attributes` lines; they are harmless, but if a control panel rejects them, strip them by rewriting to a new file: `openssl pkey -in example.com.key -out clean.key` and `openssl x509 -in example.com.crt -out clean.crt`.

## Convert PFX to a Java keystore (JKS)

`keytool -importkeystore` copies the entry from a PKCS#12 store into a JKS store.

```bash
keytool -importkeystore \
  -srckeystore example.pfx -srcstoretype PKCS12 \
  -destkeystore example.jks -deststoretype JKS
```

```text
Importing keystore example.pfx to example.jks...
Entry for alias example.com successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or cancelled
```

The alias comes from the PFX friendly name (`-name`). Recent JDKs print a warning that JKS is a proprietary format: since Java 9 the default keystore type is PKCS12, and Tomcat, Spring Boot and Jetty can load the `.pfx` directly (`keystoreType="PKCS12"`), so you often do not need JKS at all.

## Convert JKS to PFX and PEM

Reverse the keytool step, then use OpenSSL on the resulting PKCS#12 file.

```bash
keytool -importkeystore -srckeystore keystore.jks -srcstoretype JKS \
  -destkeystore keystore.p12 -deststoretype PKCS12
openssl pkcs12 -in keystore.p12 -noenc -out keystore.pem
```

```text
Importing keystore keystore.jks to keystore.p12...
Entry for alias tomcat successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or cancelled
```

Use `-srcalias` to export one entry from a keystore with several. If keytool asks for a key password different from the store password, the destination needs the same password for both; PKCS#12 in keytool uses one password for the store and the keys.

## Build a fullchain.pem

Concatenate the leaf certificate and the intermediates, leaf first, without the root.

```bash
cat example.com.crt intermediate.crt > fullchain.pem
openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout
```

```text
subject=CN=example.com
issuer=CN=Example Test Intermediate CA

subject=CN=Example Test Intermediate CA
issuer=CN=Example Test Root CA
```

Nginx's `ssl_certificate` and Apache 2.4.8+ `SSLCertificateFile` take this file. Wrong order causes [key values mismatch](https://ssl.sh/errors/nginx-key-values-mismatch/) in Nginx, and leaving out the intermediate causes [missing intermediate certificate](https://ssl.sh/errors/missing-intermediate-certificate/) errors on Android, curl and Java. If the last line of a certificate has no newline, `cat` glues `-----END CERTIFICATE----------BEGIN CERTIFICATE-----` together; check with `grep -c BEGIN fullchain.pem`.
