Extract the private key from a PFX / P12
To extract just the private key from a PFX, run `openssl pkcs12 -in certificate.pfx -nocerts -nodes -out private.key`. `-nocerts` suppresses the certificates and `-nodes` writes the key unencrypted, which is what a web server needs. The output contains PKCS#12 bag attributes above the key; they are harmless, but `openssl pkey -in private.key -out private-clean.key` re-emits just the key if you want a tidy file. If OpenSSL 3 refuses the archive, add `-legacy`.
Check the archive first #
openssl pkcs12 -in certificate.pfx -info -noout Expected output
MAC: sha256, Iteration 2048 Certificate bag Certificate bag Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC
A Shrouded Keybag line means there is a private key to extract. If there is none, the archive was
exported certificates-only and there is nothing to get.
Extract the key #
openssl pkcs12 -in certificate.pfx -nocerts -nodes -out private.key chmod 600 private.key Replace these values
| Placeholder | What to put there |
|---|---|
-nocerts | Suppress the certificates, leaving only the key. |
-nodes | Write the key unencrypted. Spelled -noenc in OpenSSL 3. |
private.key | Output. Contains bag attributes above the PEM block. |
Keeping the key encrypted #
openssl pkcs12 -in certificate.pfx -nocerts -out private.key Stripping the bag attributes #
The extracted file looks like this:
Bag Attributes
friendlyName: example.com
localKeyID: A1 B2 C3 D4 ...
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcw...
-----END PRIVATE KEY----- Every parser ignores what is outside the markers, so this works. To normalise it anyway:
openssl pkey -in private.key -out private-clean.key Non-interactive extraction #
openssl pkcs12 -in certificate.pfx -nocerts -nodes \
-passin file:/run/secrets/pfx-password \
-out private.key If OpenSSL 3 refuses the file #
openssl pkcs12 -legacy -in certificate.pfx -nocerts -nodes -out private.key Older tools wrote archives using RC2 or 3DES, which OpenSSL 3 moved into a provider that is not loaded by default. The resulting error usually mentions the MAC or reads like a wrong password.
Confirm the key matches the certificate #
Extract the certificate too and check they belong together before deploying:
openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out certificate.crt openssl pkey -in private.key -pubout | openssl sha256
openssl x509 -in certificate.crt -noout -pubkey | openssl sha256 They came from the same archive so they should match — but checking costs a second and catches the case where you extracted from the wrong file.
Frequently asked questions
- Why does the output have "Bag Attributes" text above the key?
- OpenSSL writes the PKCS#12 metadata — friendly name and local key ID — alongside the extracted object. Every parser ignores anything outside the BEGIN/END markers, so the file works as-is. Re-emit through
openssl pkeyif you want it clean. - Can I extract without the password?
- No. The key inside the archive is encrypted with a key derived from the import password, and there is no way around it.
- How do I get an encrypted key out instead?
- Omit
-nodes. OpenSSL then prompts for a new passphrase and writes an encrypted PKCS#8 key. Useful when the key is going somewhere a person will handle it rather than a service. - Is there a Shrouded Keybag but extraction still fails?
- The archive probably uses legacy algorithms OpenSSL 3 does not load by default. Add
-legacy. See that error explained.
References
- openssl-pkcs12(1) — -nocerts and -noenc
- RFC 7292: PKCS #12 — the archive format, including the MAC OpenSSL 3 rejects on legacy files