PKCS#12 (.p12, also called .pfx) is the standard container that merges a certificate and private key into one password-protected file. Java keytool, Oracle middleware, IBM products, and many enterprise installers expect PKCS12—not separate PEM files. OpenSSL creates it with the same pkcs12 -export command whether you call the output .p12 or .pfx.
This guide focuses on PKCS12 terminology and workflows: CA-signed and self-signed CRT + KEY, Java keystore aliases, intermediate chains, legacy options for older Java versions, certificate-only bundles, and verification with keytool. I ran every command on Ubuntu 25.04 with OpenSSL 3.4.1 and Java 17. For Windows IIS-focused export (TripleDES, -legacy details), see Create PFX from CRT and KEY—the commands are the same; only the target platform docs differ.
Tested on: Ubuntu 25.04 (Plucky Puffin); kernel 6.14.0-37-generic; OpenSSL 3.4.1; OpenJDK 17.
Quick answer: create PKCS12 from CRT and KEY
openssl pkcs12 -export \
-in certificate.crt \
-inkey private.key \
-out keystore.p12 \
-passout pass:YourStorePassword \
-name myaliasVerify structure:
openssl pkcs12 -in keystore.p12 -passin pass:YourStorePassword -info -nooutCertificate bag
Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC, Iteration 2048List with Java keytool:
keytool -list -storetype PKCS12 -keystore keystore.p12 -storepass YourStorePasswordKeystore type: PKCS12
Keystore provider: SUN
Your keystore contains 1 entry
myalias, Jul 2, 2026, PrivateKeyEntry,PKCS12 vs PFX vs P12
| Term | Meaning |
|---|---|
| PKCS#12 | Standard name (RFC 7292) |
| PKCS12 | Same standard, common in Java/Oracle/IBM docs |
.p12 |
File extension for Java keystores |
.pfx |
Same format; common on Windows/IIS |
One OpenSSL subcommand handles all of them: openssl pkcs12 -export. The PFX guide covers IIS import quirks; this page emphasizes Java and enterprise keystore usage.
Files required and key/cert match check
| Input | Purpose |
|---|---|
Leaf .crt / .pem |
End-entity certificate in -in |
private.key |
Matching private key in -inkey |
intermediate.crt / bundle |
Optional chain via -certfile |
Confirm the CRT and KEY belong together before export:
openssl x509 -noout -modulus -in certificate.crt | openssl md5
openssl rsa -noout -modulus -in private.key | openssl md5If the hashes differ, OpenSSL fails with No cert in -in file matches private key.
Create PKCS12 from CA-signed CRT and KEY
openssl pkcs12 -export \
-in certificate.crt \
-inkey private.key \
-out keystore.p12 \
-passout pass:StorePass123 \
-name servercert-name sets the keystore alias Java and many apps display (similar to keytool -alias).
Include intermediate CAs:
cat intermediate.crt root.crt > chain.pem
openssl pkcs12 -export \
-in certificate.crt \
-inkey private.key \
-certfile chain.pem \
-out keystore.p12 \
-passout pass:StorePass123 \
-name servercertTwo Certificate bag lines in -info output mean the leaf plus at least one chain certificate were embedded.
Create PKCS12 from a self-signed certificate
Self-signed deployments use the same export after you generate CRT and KEY. Example one-year self-signed cert:
openssl req -x509 -newkey rsa:2048 -noenc \
-keyout selfsigned.key -out selfsigned.crt -days 365 \
-subj "/CN=dev.example.test" \
-addext "subjectAltName=DNS:dev.example.test"
openssl pkcs12 -export \
-in selfsigned.crt \
-inkey selfsigned.key \
-out selfsigned.p12 \
-passout pass:StorePass123 \
-name devcertClients must still trust the self-signed certificate—PKCS12 packaging does not change trust. See Generate self-signed certificate for SAN and validity options.
Combined PEM file method (Oracle / legacy docs)
Some Oracle and enterprise guides concatenate key and certificate into one PEM, then export:
cat private.key certificate.crt > combined.pem
openssl pkcs12 -export \
-in combined.pem \
-out keystore.p12 \
-passout pass:StorePass123 \
-name myAliasSeparate -in and -inkey files are clearer and less error-prone; both approaches produce a valid PKCS12 when the key and cert match.
Export password and encrypted input keys
Set the PKCS12 store password (required for most Java apps):
-passout pass:YourStorePasswordWhen the input .key is passphrase-protected:
openssl pkcs12 -export \
-in certificate.crt \
-inkey encrypted.key \
-passin pass:KeyUnlockPass \
-out keystore.p12 \
-passout pass:StorePass123 \
-name servercertUse a non-empty store password—empty PKCS12 passwords break many Java JSSE configurations.
Java keytool: import and convert to JKS
Keep the keytool cheat sheet handy for -importcert, alias changes, and cacerts; this section covers PKCS12 inspection and JKS conversion after OpenSSL export.
After creating keystore.p12, inspect it:
keytool -list -storetype PKCS12 -keystore keystore.p12 -storepass StorePass123Convert PKCS12 to legacy JKS if an old app requires JKS:
keytool -importkeystore \
-srckeystore keystore.p12 \
-srcstoretype PKCS12 \
-srcstorepass StorePass123 \
-destkeystore app.jks \
-deststoretype JKS \
-deststorepass JksPass456Point your Java app at keystore.p12 directly when the framework supports PKCS12 (Spring Boot, modern Tomcat, etc.)—conversion to JKS is optional.
Legacy PKCS12 for older Java and JSSE
OpenSSL 3.x defaults to AES-256 + PBKDF2. Some older Java versions report keystore password was incorrect even with the right password—the MAC or encryption algorithm is incompatible.
Re-export with legacy algorithms:
openssl pkcs12 -export -legacy \
-in certificate.crt \
-inkey private.key \
-out keystore.p12 \
-passout pass:StorePass123 \
-name servercertOracle JSSE documentation also recommends -nomaciter -noiter for very old stacks:
openssl pkcs12 -export -legacy -nomaciter -noiter \
-in certificate.crt \
-inkey private.key \
-out keystore.p12 \
-passout pass:StorePass123 \
-name servercertOn Ubuntu 25.04, both the default and -legacy -nomaciter -noiter exports loaded in Java 17 keytool. If import fails on your JDK version, try -legacy first, then the explicit TripleDES flags in the PFX guide.
Certificate-only PKCS12 (no private key)
Import trust anchors without a private key—useful for truststores, not server TLS identity:
openssl pkcs12 -export \
-in ca.crt \
-nokeys \
-out trust.p12 \
-passout pass:TrustPass123 \
-name ca-trust-info shows certificate bags only—no Shrouded Keybag.
Verify and extract after export
Inspect bags and algorithms:
openssl pkcs12 -in keystore.p12 -passin pass:StorePass123 -info -nooutExtract PEM files on Linux:
openssl pkcs12 -in keystore.p12 -passin pass:StorePass123 -nocerts -nodes -out extracted.key
openssl pkcs12 -in keystore.p12 -passin pass:StorePass123 -clcerts -nokeys -out extracted.crtFull walkthrough: Extract private key from PFX.
Troubleshooting
| Symptom | Fix |
|---|---|
No cert in -in file matches private key |
CRT/KEY mismatch—compare modulus MD5 |
keytool: keystore password was incorrect |
Re-export with -legacy; confirm -passout password |
| JSSE fails with old Oracle adapter | Add -nomaciter -noiter on export |
| Missing chain in Java trust path | Re-export with -certfile chain.pem |
unable to load private key |
Add -passin for encrypted input key |
| Empty password rejected | Use -passout pass:NonEmptyPassword |
References
- openssl-pkcs12 manual
- (Windows/IIS focus)
Summary
Create PKCS12 from CRT and KEY with openssl pkcs12 -export -in cert.crt -inkey private.key -out keystore.p12 -passout pass:PASSWORD -name alias. PKCS12, PKCS#12, .p12, and .pfx name the same bundle format. Add -certfile chain.pem for intermediates, -passin when the input key is encrypted, and -legacy (or -nomaciter -noiter) when Java keytool rejects OpenSSL 3 defaults. Self-signed certificates export the same way as CA-signed certs. Verify with openssl pkcs12 -info and keytool -list. To split the keystore back into PEM files, use Extract private key from PFX; for IIS-specific import notes, see Create PFX from CRT and KEY.

