PKCS#12 — .pfx and .p12

PKCS#12 is a password-protected binary archive that bundles a certificate, its private key and the intermediate chain into a single file. `.pfx` and `.p12` are the same format under different extensions — Microsoft tooling writes `.pfx` and most other software writes `.p12`. It is the standard way to move a complete TLS identity between systems, and the format most likely to cause trouble across OpenSSL versions, because OpenSSL 3 changed the default encryption to AES-256-CBC and older importers cannot read it.

Updated August 19, 2026 Verified against OpenSSL 3.5.7

What is inside #

A PKCS#12 archive is a set of “bags”, each holding one object:

Bag type Contents
Certificate bag One certificate. A typical archive has one per chain member.
Shrouded key bag The private key, encrypted with a key derived from the password.
Bag attributes The friendly name and local key ID that associate a key with its certificate.

The whole file is then MAC-protected using the same password, so tampering is detectable.

List the bags without extracting anything
openssl pkcs12 -in certificate.pfx -info -noout
Expected output
MAC: sha256, Iteration 2048
PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC
Certificate bag
Certificate bag
PKCS7 Data
Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC

Two certificate bags plus one shrouded key bag is the shape of a normal server identity with one intermediate. No shrouded key bag means there is no private key in the file.

The OpenSSL 3 problem #

This is the single most common thing to go wrong with PKCS#12 files, and it is worth understanding rather than just memorising the flag.

OpenSSL 3.0 changed the default PKCS#12 encryption from RC2/3DES with a SHA-1 MAC to AES-256-CBC with PBKDF2 and a SHA-256 MAC. That is unambiguously the right default. But implementations written against the original specification — older Windows CryptoAPI, older JDKs, various appliances — do not implement those algorithms, and when decryption fails they report it as an incorrect password rather than an unsupported cipher. So the symptom points at the wrong cause.

Export something an old importer can read
openssl pkcs12 -export -legacy \
-out certificate.pfx -inkey private.key -in certificate.crt
Read an archive an old tool produced
openssl pkcs12 -legacy -in certificate.pfx -info -noout

Creating and unpacking #

PEM files in, one archive out
openssl pkcs12 -export \
-out certificate.pfx \
-inkey private.key \
-in certificate.crt \
-certfile chain.crt \
-name "example.com"
Archive in, PEM files out
openssl pkcs12 -in certificate.pfx -nocerts -nodes -out private.key
openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out certificate.crt
openssl pkcs12 -in certificate.pfx -cacerts -nokeys -out chain.crt

Full detail at PEM to PFX and PFX to PEM.

Where you will meet it #

  • IIS and Windows use PKCS#12 as the native import and export format for TLS identities.
  • Java 9 and later default to PKCS#12 for keystores, replacing JKS.
  • Azure, AWS and most managed platforms accept a PFX upload as the way to supply a certificate with its key.
  • Moving a certificate between machines — it is the one file format that carries the complete identity, which is exactly why it needs a password.

Handling it safely #

Setting a blank password with -passout pass: produces a file with no protection at all. Some import tools require it, most refuse it, and it should never touch a shared filesystem.

Frequently asked questions

What is the difference between .pfx and .p12?
Nothing. The binary format is identical and every tool reads either. .pfx came from Microsoft's earlier PFX specification, which PKCS#12 superseded, and the name stuck in the Windows ecosystem.
Does a PFX always contain the private key?
Almost always, and that is the point of the format — but not necessarily. An archive exported with -nokeys holds certificates only. Run openssl pkcs12 -info -noout and look for a Shrouded Keybag to find out.
Why does Windows say my password is wrong when it is not?
Because OpenSSL 3 encrypted the archive with AES-256-CBC and the older Windows importer cannot decrypt it, reporting the failure as a bad password. Re-export with -legacy. See the full explanation.
Can a PFX hold more than one certificate and key?
Yes. The format is a general bag structure and can hold several identities, each distinguished by a friendly name. In practice almost every PFX holds exactly one identity plus its chain.

References

  • RFC 7292: PKCS #12 — the archive format, including the MAC OpenSSL 3 rejects on legacy files