A certificate and private key in separate PEM files cannot be imported directly into Windows certificate stores, IIS, many appliances, and vendor portals that ask for a PFX or PKCS#12 archive. The archive must contain the certificate, the matching key, and the required issuing chain, or the import may succeed while TLS, client authentication, or application startup fails later.
OpenSSL creates the archive with pkcs12 -export. The certificate is read with -in, the private key with -inkey, extra chain certificates with -certfile, and the archive password through -passout. OpenSSL 3.x defaults use AES-256-CBC with PBKDF2 for PKCS#12 export encryption unless compatibility options change that behavior.
Use a protected working directory and a password file from controlled secret storage so the PFX password does not appear in shell history or saved terminal output. Confirm the certificate/key pair before export, inspect the finished archive without dumping its private key, and keep both the source key and the PFX file restricted after the handoff.
$ install -d -m 700 "$HOME/pfx-export" $ install -m 644 "$HOME/certs/www.example.net.crt.pem" "$HOME/pfx-export/www.example.net.crt.pem" $ install -m 600 "$HOME/certs/www.example.net.key.pem" "$HOME/pfx-export/www.example.net.key.pem" $ install -m 644 "$HOME/certs/www.example.net.chain.pem" "$HOME/pfx-export/www.example.net.chain.pem" $ install -m 600 /run/secrets/pfx-password "$HOME/pfx-export/pfx-password.txt" $ cd "$HOME/pfx-export" $ ls -l www.example.net.crt.pem www.example.net.key.pem www.example.net.chain.pem pfx-password.txt -rw------- 1 deploy deploy 21 Jun 5 20:37 pfx-password.txt -rw-r--r-- 1 deploy deploy 1245 Jun 5 20:37 www.example.net.chain.pem -rw-r--r-- 1 deploy deploy 1294 Jun 5 20:37 www.example.net.crt.pem -rw------- 1 deploy deploy 1708 Jun 5 20:37 www.example.net.key.pem
Replace /run/secrets/pfx-password with the protected source that holds the archive password. Omit -passout file:pfx-password.txt in the export step to let OpenSSL prompt interactively instead.
$ openssl x509 -in www.example.net.crt.pem -noout -subject -issuer -enddate subject=CN=www.example.net, O=Example Web issuer=CN=Example Issuing CA, O=Example Internal PKI notAfter=Sep 7 20:37:05 2028 GMT
Stop here if the subject, issuer, or expiry date belongs to a different certificate than the system or portal should receive.
$ openssl x509 -in www.example.net.crt.pem -pubkey -noout -out www.example.net.crt.pub.pem $ openssl pkey -in www.example.net.key.pem -pubout -out www.example.net.key.pub.pem $ openssl dgst -sha256 www.example.net.crt.pub.pem www.example.net.key.pub.pem SHA2-256(www.example.net.crt.pub.pem)= 49dd8dc476faa9edaa41b22d576ecc0fc09ceac5ee81aada8e961e5eeeda7e8b SHA2-256(www.example.net.key.pub.pem)= 49dd8dc476faa9edaa41b22d576ecc0fc09ceac5ee81aada8e961e5eeeda7e8b
Matching digests show that the certificate and private key belong to the same key pair.
$ openssl verify -CAfile www.example.net.chain.pem www.example.net.crt.pem www.example.net.crt.pem: OK
If the chain file contains only intermediates, verify against the organization CA bundle or system trust store instead of treating a local openssl verify failure as proof that the certificate is wrong.
$ openssl pkcs12 -export -out www.example.net.pfx -inkey www.example.net.key.pem -in www.example.net.crt.pem -certfile www.example.net.chain.pem -name "www.example.net" -passout file:pfx-password.txt
Omit -certfile www.example.net.chain.pem only when the target system already has the required issuing chain. Use -legacy only for older importers that reject the default OpenSSL 3.x PKCS#12 encryption.
Avoid -twopass unless the target explicitly requires separate integrity and encryption passwords. Many importers expect one archive password.
$ chmod 600 www.example.net.pfx $ ls -l www.example.net.pfx -rw------- 1 deploy deploy 3698 Jun 5 20:37 www.example.net.pfx
The PFX archive contains the private key. Store it with the same controls used for the original private key.
$ openssl pkcs12 -in www.example.net.pfx -passin file:pfx-password.txt -info -noout 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
The output should include certificate bags and a shrouded keybag. A password error or missing keybag means the archive is not ready for import.
$ openssl pkcs12 -in www.example.net.pfx -passin file:pfx-password.txt -clcerts -nokeys -out pfx-leaf.crt.pem $ openssl x509 -in pfx-leaf.crt.pem -noout -subject -issuer -enddate subject=CN=www.example.net, O=Example Web issuer=CN=Example Issuing CA, O=Example Internal PKI notAfter=Sep 7 20:37:05 2028 GMT
-clcerts -nokeys writes the client or leaf certificate and skips private keys and CA certificates.
$ rm -f pfx-password.txt www.example.net.crt.pub.pem www.example.net.key.pub.pem pfx-leaf.crt.pem
Do not attach the private key, PFX archive, or password file to tickets, chat messages, screenshots, or saved troubleshooting logs.