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.
- Platforms
- Linux
- macOS
- Windows
- IIS
- Java
- Level
- Practitioner · 6 steps
On this page
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, so treat every copy as a secret.
A PKCS #12 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
openssl pkcs12 -in www.pfx -info -noout
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
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:
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
openssl pkcs12 -in www.pfx -cacerts -nokeys -out chain.crt
grep -E 'subject|issuer' chain.crt
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.
4. Extract the private key
(umask 077; openssl pkcs12 -in www.pfx -nocerts -noenc | openssl pkey -out www.key)
head -1 www.key
-----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.
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.)
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:
openssl pkcs12 -in legacy.pfx -info -noout -legacy
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
openssl pkcs12 -export -inkey www.key -in www.crt -certfile chain.crt \
-name "www.example.com" -out www.pfx
-inkeyis the private key,-inthe server certificate, and-certfilethe intermediates. Leave the root out.-namesets 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:
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:
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:
certutil -dump www.pfx
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, and paste www.crt (never the key) into the 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.unsupportedwithRC2-40-CBC: the PFX uses legacy algorithms. Add-legacy(step 5).No cert in -in file 'www.crt' matches private keywhen exporting: the key and certificate do not belong together. Find the right pair with the key-match guide.- 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)orkeystore password was incorrect): re-create it with the triple DES command in step 6. - Clients fail with
unable to get local issuer certificateorPKIX path building failedafter 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.
Why this works
PKCS #12 (RFC 7292) 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) 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 compares all the formats, Key pairs explains why only the key needs protecting, and Certificate chains explains why the intermediate must travel with your certificate.
Go deeper
- OpenSSL
pkcs12manual: every option, including-legacy,-certpbe,-keypbeand-macalg. - OpenSSL 3.0 migration guide: why the PKCS #12 defaults changed and what
-legacyrestores. - RFC 7292: the PKCS #12 format.
- RFC 7468: PEM encodings and labels.
- Microsoft Learn: Import-PfxCertificate: importing a PFX into a Windows store.
- Microsoft Learn: certutil: checking a PFX with
-dump.
Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.