Mutual TLS and operations
Convert certificate formats
Convert between PEM and PKCS#12 when a platform requires a bundle, without losing track of private-key handling.
Sooner or later a platform refuses your neat pile of .crt and .key files and asks for “a PKCS#12 file” or “a .pfx”. Nothing about the cryptography changes. It’s the same key and the same certificates in a different box. Knowing the two main boxes saves you a panicked search at deploy time.
PEM is what we’ve used all course. Text files with -----BEGIN CERTIFICATE----- markers, one thing per file. That’s why nginx and Node take separate cert and key paths.
PKCS#12 (extensions .p12 or .pfx) is a binary bundle. It packs a private key, its certificate, and the chain into one password-protected file. Browsers importing a client certificate, Java keystores, and Windows services usually want this one.
Let’s build a bundle from our mTLS client files:
openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt -certfile lab-ca.crt
-export switches pkcs12 into bundle-creation mode. -inkey and -in take the private key and its certificate. -certfile adds the CA certificate, so the receiving system gets the chain context too.
You’re prompted for an export password. Choose a real one. This file contains the private key, and it will probably travel to another machine. That’s exactly when files get copied around carelessly.
Now let’s check what landed inside, without decrypting the secrets to the terminal:
openssl pkcs12 -in client.p12 -info -noout
# MAC: sha256, Iteration 2048
# 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 client certificate and the CA. One shrouded key bag: the encrypted private key. The -noout flag is what keeps the contents off your screen. Without it, the command also writes both certificates and the key to standard output.
Going the other way, from .p12 back to PEM, uses openssl pkcs12 -in client.p12 -out client.pem -nodes. Be careful with it: the output includes the decrypted private key. Send it to a file with 600 permissions, never to a shared screen or a log.
The failure mode here isn’t technical. It’s operational. The bundle works, so it gets emailed around “because it’s just one file”. Now the private key lives in several inboxes, with the password sitting two messages up in the same thread. Format conversion doesn’t fix a weak password or loose permissions. Treat a .p12 with the same care as the raw key, because that’s what it contains.
Lesson completed