OpenSSL Cheatsheet
Format Conversion
Use this OpenSSL reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
The formats, at a glance
Everything is the same ASN.1 structure. The differences are the encoding and what else is bundled alongside.
| Format | Extensions | What it is |
|---|---|---|
| PEM | .pem .crt .cer .key | Base64 DER wrapped in -----BEGIN X----- |
| DER | .der .cer .crt | Raw binary ASN.1, one object per file |
| PKCS#1 | .key .pem | RSA key, BEGIN RSA PRIVATE KEY |
| PKCS#8 | .key .p8 | Any key type, BEGIN PRIVATE KEY |
| PKCS#12 | .p12 .pfx | Encrypted bundle: key + cert + chain |
| PKCS#7 | .p7b .p7c | Certificates only, no key |
The PEM header tells you what you actually have:
| Header | Contents |
|---|---|
BEGIN CERTIFICATE | X.509 certificate |
BEGIN CERTIFICATE REQUEST | CSR |
BEGIN PRIVATE KEY | PKCS#8, unencrypted, any algorithm |
BEGIN ENCRYPTED PRIVATE KEY | PKCS#8, passphrase protected |
BEGIN RSA PRIVATE KEY | PKCS#1, RSA only, legacy |
BEGIN EC PRIVATE KEY | SEC1, EC only, legacy |
BEGIN PUBLIC KEY | SubjectPublicKeyInfo |
BEGIN OPENSSH PRIVATE KEY | Not OpenSSL, use ssh-keygen |
PEM and DER
-inform describes the input, -outform the output. Same pair on every
subcommand.
# Certificates openssl x509 -in cert.pem -outform DER -out cert.der openssl x509 -in cert.der -inform DER -out cert.pem # Keys openssl pkey -in key.pem -outform DER -out key.der openssl pkey -in key.der -inform DER -out key.pem # CSRs openssl req -in req.csr -outform DER -out req.der openssl req -in req.der -inform DER -out req.csr
Tell them apart without reading the file:
file cert.der # "data" for DER, "ASCII text" for PEM head -1 cert.pem # PEM starts with -----BEGIN
PKCS#1, SEC1, PKCS#8
PKCS#8 is the modern container and the one OpenSSL 3.x writes by default.
Older Java, some appliances, and Go's x509.ParsePKCS1PrivateKey want the
legacy forms.
# legacy (BEGIN RSA PRIVATE KEY) -> PKCS#8 (BEGIN PRIVATE KEY) openssl pkcs8 -topk8 -nocrypt -in rsa1.key -out pkcs8.key # PKCS#8 -> legacy openssl rsa -in pkcs8.key -traditional -out rsa1.key openssl pkey -in pkcs8.key -traditional -out rsa1.key # PKCS#8, encrypted with a modern PBES2 cipher openssl pkcs8 -topk8 -in key.pem -out enc.key -v2 aes-256-cbc # decrypt an encrypted PKCS#8 openssl pkcs8 -in enc.key -out key.pem
-nocrypt on -topk8 means "write it unencrypted". Leave it off and OpenSSL
prompts for a passphrase and encrypts.
PKCS#12 (.p12 and .pfx)
One password protected file holding the key, the leaf, and the chain. Windows, macOS Keychain, Java keystores, and most load balancers import this.
# Build one openssl pkcs12 -export -out bundle.p12 \ -inkey key.pem -in cert.pem -certfile chain.pem \ -name "example.com" # Build one and let OpenSSL find the chain in the trust store openssl pkcs12 -export -out bundle.p12 -inkey key.pem -in cert.pem -chain
Take it apart:
openssl pkcs12 -in bundle.p12 -out all.pem -noenc # key + all certs openssl pkcs12 -in bundle.p12 -nokeys -out certs.pem # certs only openssl pkcs12 -in bundle.p12 -nocerts -noenc -out key.pem openssl pkcs12 -in bundle.p12 -clcerts -nokeys -out cert.pem # leaf only openssl pkcs12 -in bundle.p12 -cacerts -nokeys -out chain.pem # chain only openssl pkcs12 -in bundle.p12 -info -noout # what is inside
Non-interactive, for scripts:
openssl pkcs12 -export -out bundle.p12 -inkey key.pem -in cert.pem \ -passout pass:changeit openssl pkcs12 -in bundle.p12 -nokeys -out certs.pem -passin pass:changeit
An empty password is -passout pass: with nothing after the colon, which some
Java tools require.
PKCS#7 and bundles
PKCS#7 carries certificates only, never a key. .p7b files from Windows CAs
are this.
openssl pkcs7 -in chain.p7b -print_certs -out chain.pem openssl pkcs7 -in chain.p7b -inform DER -print_certs -out chain.pem openssl pkcs7 -in chain.p7b -print_certs -noout # just list them # PEM bundle -> PKCS#7 openssl crl2pkcs7 -nocrl -certfile chain.pem -out chain.p7b
A multi-certificate PEM bundle is literally concatenation, so cat and split
are valid tools:
cat cert.pem intermediate.pem root.pem > bundle.pem
Gotchas
- OpenSSL 3.x refuses to read old PKCS#12 files made with RC2 or 40-bit
RC4 and errors with unsupported or error:0308010C. Add -legacy, and
add -legacy when writing a file for an ancient client too.
- -descert on export writes 3DES, only needed for pre-2010 importers. The
3.x default is PBES2 with PBKDF2 and AES-256-CBC, which old Java rejects.
- -nodes is now -noenc. Both still parse, -noenc is what the help
text shows.
- openssl rsa, openssl ec, and openssl dsa are algorithm specific.
openssl pkey handles all of them, so scripts should use pkey.
- DER holds exactly one object. There is no such thing as a DER chain file,
so a chain must be PEM, PKCS#7, or PKCS#12.
- .cer and .crt say nothing about the encoding. Windows exports both
DER and PEM as .cer. Check the first line before you convert.
- Java keytool cannot import a bare PEM key. Go through PKCS#12:
keytool -importkeystore -srckeystore bundle.p12 -srcstoretype PKCS12
-destkeystore ks.jks.