Converting and Bundling
Certificates travel between toolchains that disagree about formats. This chapter is the passport office: same objects, different paper. Everything here is a lossless re-wrapping — the cryptography inside never changes, and the fingerprint proves it.
PEM and DER
Chapter 2's two forms: PEM, base64 text
between -----BEGIN----- lines, is OpenSSL's
home format; DER, the raw binary, is what
much Windows and Java tooling expects. The
-outform / -inform flags do the moving,
for certificates and keys alike:
$ openssl x509 -in server.cert.pem -out server.cert.der -outform DER
$ file server.cert.der
server.cert.der: Certificate, Version=3
$ openssl x509 -in server.cert.der -inform DER -out server-back.pem
And the proof nothing was lost — fingerprint the original and the round-trip:
$ cmp <(openssl x509 -in server.cert.pem -noout -fingerprint -sha256) \
<(openssl x509 -in server-back.pem -noout -fingerprint -sha256) && echo SAME-CERT
SAME-CERT
Keys convert the same way with pkey
(-outform DER), and a key's PKCS#8 form
— the generic BEGIN PRIVATE KEY you met in
chapter 5 — is already the cross-algorithm
standard; the older per-algorithm wrappers
(BEGIN RSA PRIVATE KEY) are read everywhere
and written only for compatibility. The most
common format error in the wild is not exotic:
a DER file handed to a tool expecting PEM
fails with some version of "no start line",
and vice versa a PEM fed with -inform DER
fails as garbage. The fix is always to match
-inform to the file you actually have —
file and the first line of the file tell
you which that is.
Bundles: several certificates, one file
PEM's stackability is a feature: a chain file is just certificates concatenated, leaf first, each issuer after its subject:
$ cat server.cert.pem inter/inter.cert.pem > server-chain.pem
$ grep "^-----BEGIN" server-chain.pem
-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----
Two BEGIN lines, two certificates. Order
matters to some tools and not others — the
safe convention is leaf, intermediate(s),
root last (or omitted: a root in a bundle a
server sends is dead weight, as chapter 8
noted). The lab's chain.pem is the
mirror-image bundle — intermediate then
root — built for handing to things that need
the issuers: s_server -cert_chain,
pkcs12 -certfile, and verify -untrusted
in spirit. Most "wrong certificate" mysteries
that survive chapter 11 are, in the end, a
bundle file assembled in an order or with a
member nobody checked — and openssl
verify against a candidate bundle remains
the way to check it.
PKCS#12: the suitcase
When a key and its certificate (and usually
its chain) must travel together — into a
browser, a Java keystore, a Windows store —
they go as one password-protected binary, a
.p12 / .pfx file. Packing the lab server:
$ openssl pkcs12 -export -name "Example Server" -inkey server.key.pem -in server.cert.pem -certfile chain.pem -out server.p12 -passout pass:correct-horse
-name is the friendly label stores display;
-certfile adds the chain. The inspection
report shows the armour — note that, unlike
enc in chapter 9, this format uses a
proper iterated derivation and encrypts the
key bag with AES by default in OpenSSL 3:
$ openssl pkcs12 -in server.p12 -passin pass:correct-horse -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
Certificate bag
PKCS7 Data
Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256
Three certificate bags (leaf, intermediate,
root) and one shrouded key. Unpacking is the
same command with intent flags: -clcerts
-nokeys prints only the leaf certificate,
-nocerts -nodes would print the key. Two
traps live here. Old stores may demand the
legacy algorithms — OpenSSL 3 packs modern
defaults, and a .p12 an elderly Java can't
open wants -legacy on export. And the
export password is the whole protection:
an empty-password .p12 (some tools'
silent default on import) is a key in a
clear envelope, however official the
extension looks.
PKCS#7: certificates without keys
The chain alone, in a binary envelope, is
PKCS#7 — the .p7b file Windows tooling
likes. crl2pkcs7 (its name advertises its
other job, wrapping revocation lists) builds
one from a bundle with -nocrl:
$ openssl crl2pkcs7 -nocrl -certfile server-chain.pem -out bundle.p7b -outform DER
$ openssl pkcs7 -inform DER -in bundle.p7b -print_certs -noout
subject=CN = server.example.test, O = Example Lab
issuer=CN = Mere Mortals Intermediate CA, O = Example Lab
subject=CN = Mere Mortals Intermediate CA, O = Example Lab
issuer=CN = Mere Mortals Root CA, O = Example Lab
No keys can ride in a PKCS#7 — that is its virtue. It is the chain, certified as a set, for handing to anything that needs the issuers and must never see a private key.