<!-- https://pkizerotohero.com/guides/convert-pfx-pem/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> Convert a PFX (PKCS #12) file to PEM certificate, chain and key files with OpenSSL, and back, including OpenSSL 3's legacy RC2 error and older systems.

Source: https://pkizerotohero.com/guides/convert-pfx-pem/ · Last reviewed: 2026-10-20

How-to guide · Convert file formats

# How to convert PFX (PKCS #12) to PEM and back

**In one sentence:**

You will have split a PFX into PEM files for the certificate, the chain and the key, or packed PEM files into a PFX that Windows and Java can import.

Task

[Convert file formats](https://pkizerotohero.com/guides/#task-convert)

Platforms

- Linux
- macOS
- Windows
- IIS
- Java

Who it is for

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

Level

Practitioner · 6 steps

## Before you start

- **OpenSSL 3** (Linux, macOS with Homebrew, or Git Bash on Windows). OpenSSL 1.1.1 works too; where it differs, this guide says so.
- **The PFX file and its password**, or the PEM files you want to combine: private key, certificate and chain.
- **A private place to work**, such as the server itself. A PFX holds a [private key](https://pkizerotohero.com/handbook/glossary/#private-key), so treat every copy as a secret.

A [PKCS #12](https://pkizerotohero.com/handbook/glossary/#pkcs12) file (`.pfx` or `.p12`, the same format) packs a key, its certificate and usually the chain into one password-protected file. Windows and Java like that. nginx, Apache, HAProxy and most Linux tools want separate PEM files instead.

## Steps

### 1. Look inside the PFX

```bash
openssl pkcs12 -in www.pfx -info -noout
```

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

Two certificate bags (the server certificate and one intermediate) and one shrouded keybag (the encrypted private key). The algorithms tell you how the file is protected, which matters in step 5.

### 2. Extract the server certificate

```bash
openssl pkcs12 -in www.pfx -clcerts -nokeys | openssl x509 -out www.crt
```

`-clcerts` selects the certificate that belongs to the key, and `-nokeys` leaves the key out. Without the pipe through `openssl x509`, the file starts with `Bag Attributes` lines:

```text
Bag Attributes
    localKeyID: B6 74 1B 8F 01 65 71 BA CC 01 D4 CF 05 26 B4 EF E7 8B CE 00 
    friendlyName: www.example.com
subject=C=BE, O=Example Shop, CN=www.example.com
issuer=C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1
-----BEGIN CERTIFICATE-----
```

Most software ignores those lines, but the pipe gives you a clean file that starts with `-----BEGIN CERTIFICATE-----`.

### 3. Extract the chain

```bash
openssl pkcs12 -in www.pfx -cacerts -nokeys -out chain.crt
grep -E 'subject|issuer' chain.crt
```

```text
subject=C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1
issuer=C=BE, O=Keystone Demo, CN=Keystone Demo Root CA
```

`-cacerts` writes only the CA certificates. For nginx and similar servers, join them after your certificate: [How to build the full chain file](https://pkizerotohero.com/guides/build-fullchain/).

### 4. Extract the private key

```bash
(umask 077; openssl pkcs12 -in www.pfx -nocerts -noenc | openssl pkey -out www.key)
head -1 www.key
```

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

`-noenc` writes the key without a password, which servers usually need. On OpenSSL 1.1.1 the option is called `-nodes` (still accepted, but deprecated in OpenSSL 3). To keep the key encrypted, leave `-noenc` out: OpenSSL then asks for a new PEM pass phrase.

Warning

An unencrypted key is a secret in plain text

Anyone who reads `www.key` can impersonate your server. Keep it readable only by the service that needs it, never commit it to a repository or paste it into a website, and delete working copies when you are done.

### 5. If OpenSSL 3 says “unsupported”

PFX files exported by older Windows and Java versions often protect the certificates with 40-bit RC2, which OpenSSL 3 keeps in its separate legacy provider. (Windows 11 exports use triple DES by default, which OpenSSL 3 reads without help.)

```text
Error outputting keys and certificates
...:digital envelope routines:inner_evp_generic_fetch:unsupported:...:Global default library context, Algorithm (RC2-40-CBC : 0), Properties ()
```

Add `-legacy` to the same command:

```bash
openssl pkcs12 -in legacy.pfx -info -noout -legacy
```

```text
MAC: sha1, Iteration 2048
MAC length: 20, salt length: 8
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048
...
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048
```

If OpenSSL says it cannot load the legacy provider, your build does not include it; use a full OpenSSL 3 package, or OpenSSL 1.1.1.

### 6. Pack PEM files into a PFX

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

- `-inkey` is the private key, `-in` the server certificate, and `-certfile` the intermediates. Leave the root out.
- `-name` sets the friendly name that Windows shows.
- OpenSSL asks for an export password. Use a strong one, and send it through a different channel from the file.

OpenSSL 3 protects the result with AES-256 and a SHA-256 MAC. Some older systems cannot open that: in our tests, Java 8 builds up to update 332 refused it with `parseAlgParameters failed` or a misleading `keystore password was incorrect`, while 8u342 opened it; older Windows versions may reject it too. For them, use triple DES with a SHA-1 MAC. In our tests, OpenSSL 3.0 and 3.2 read it without `-legacy`, and Windows 11 and Java 8u292 opened it:

```bash
openssl pkcs12 -export -certpbe PBE-SHA1-3DES -keypbe PBE-SHA1-3DES -macalg sha1 \
  -inkey www.key -in www.crt -certfile chain.crt -name "www.example.com" -out www-compat.pfx
```

Prefer that to `-legacy` for export, which protects the certificates with 40-bit RC2.

## Check it worked

For a new PFX, list its contents and check that the key matches the certificate:

```bash
openssl pkcs12 -in www.pfx -info -noout
```

You should see one certificate bag per certificate and one shrouded keybag. On Windows, `certutil` tests the key against the certificate without importing anything:

```powershell
certutil -dump www.pfx
```

```text
Enter PFX password:
...
Encryption test passed
CertUtil: -dump command completed successfully.
```

For PEM files, compare the public keys as in [How to check that a private key matches a certificate](https://pkizerotohero.com/guides/check-key-matches-certificate/), and paste `www.crt` (never the key) into the decoder:

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

## If something goes wrong

- **`Mac verify error: invalid password?`:** the password is wrong, or the file was damaged in transfer (for example, copied as text). Ask for the password again or copy the file in binary mode.
- **`unsupported` with `RC2-40-CBC`:** the PFX uses legacy algorithms. Add `-legacy` (step 5).
- **`No cert in -in file 'www.crt' matches private key`** when exporting: the key and certificate do not belong together. Find the right pair with [the key-match guide](https://pkizerotohero.com/guides/check-key-matches-certificate/).
- **Windows or Java on an older system cannot import the PFX, or reports a wrong password** (old Java 8: `parseAlgParameters failed: ObjectIdentifier() -- data isn't an object ID (tag = 48)` or `keystore password was incorrect`): re-create it with the triple DES command in step 6.
- **Clients fail with [`unable to get local issuer certificate`](https://pkizerotohero.com/errors/curl-unable-to-get-local-issuer-certificate/) or [`PKIX path building failed`](https://pkizerotohero.com/errors/java-pkix-path-building-failed/)** after you deploy: the PFX or PEM files lack the intermediate. Add it with `-certfile`, or build the full chain file.
- **IIS shows the certificate without a key:** see [How to install a certificate in IIS](https://pkizerotohero.com/guides/install-certificate-iis/).

## Why this works

PKCS #12 ([RFC 7292](https://www.rfc-editor.org/rfc/rfc7292)) is a container: “bags” holding certificates and a key, encrypted with keys derived from your password and protected by a MAC that also depends on it. PEM ([RFC 7468](https://www.rfc-editor.org/rfc/rfc7468)) holds one object per `BEGIN`/`END` block. Converting between them changes the packaging, never the certificate or the key, so the result proves exactly what the original did. The [file formats appendix](https://pkizerotohero.com/handbook/file-formats/) compares all the formats, [Key pairs](https://pkizerotohero.com/handbook/key-pairs/) explains why only the key needs protecting, and [Certificate chains](https://pkizerotohero.com/handbook/certificate-chains/) explains why the intermediate must travel with your certificate.

## Go deeper

- [OpenSSL `pkcs12` manual](https://docs.openssl.org/master/man1/openssl-pkcs12/): every option, including `-legacy`, `-certpbe`, `-keypbe` and `-macalg`.
- [OpenSSL 3.0 migration guide](https://docs.openssl.org/3.0/man7/migration_guide/): why the PKCS #12 defaults changed and what `-legacy` restores.
- [RFC 7292](https://www.rfc-editor.org/rfc/rfc7292): the PKCS #12 format.
- [RFC 7468](https://www.rfc-editor.org/rfc/rfc7468): PEM encodings and labels.
- [Microsoft Learn: Import-PfxCertificate](https://learn.microsoft.com/en-us/powershell/module/pki/import-pfxcertificate): importing a PFX into a Windows store.
- [Microsoft Learn: certutil](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certutil): checking a PFX with `-dump`.

**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=/guides/convert-pfx-pem/).

Last reviewed 20 October 2026Edition 0.9

## Keep going

### Learn why it works

- [File formats: PEM, DER, PKCS #12 and friends](https://pkizerotohero.com/handbook/file-formats/)
- [Chapter 3: Key pairs: public and private keys](https://pkizerotohero.com/handbook/key-pairs/)
- [Chapter 13: Certificate chains and path validation](https://pkizerotohero.com/handbook/certificate-chains/)

### Error pages

- [SSL certificate problem: unable to get local issuer certificate](https://pkizerotohero.com/errors/curl-unable-to-get-local-issuer-certificate/)
- [PKIX path building failed … unable to find valid certification path to requested target](https://pkizerotohero.com/errors/java-pkix-path-building-failed/)

### 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/)

## More guides: Convert file formats

- [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/)
