Convert OpenSSL Keys and Certificates Without Guessing the Format
You will finish with a repeatable way to read and write PEM and DER keys or certificates, recognise when OpenSSL can detect a format for you, and avoid confusing a PKCS#12 bundle with an ordinary certificate. The examples use the installed openssl command, reported here as OpenSSL 3.6.1. The local openssl-format-options(1ssl) manpage is from the Ubuntu openssl package version 3.0.13-0ubuntu3.15, so check the individual command's help when working on a different installation.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow 15 minutes. You need a shell and an input key or certificate that you are authorised to handle. These examples create new output files and read private-key material, but do not require root. Do not paste private keys into tickets, chat or shell history.
1. Identify the format options
The format options are attached to the OpenSSL command that consumes or produces the object:
-inform formatselects an input stream format.-outform formatselects an output stream format.-keyform formatselects the format of a private-key input source.-CRLform formatselects the format of a certificate-revocation-list input source.
Not every command accepts every option. Start with the command's own help and copy the spelling exactly:
$ openssl pkey -help | grep -E -- '-(in|inform|out|outform)'
-in val Input key
-inform format Key input format (ENGINE, other values ignored)
-out outfile Output file for encoded and/or text output
-outform PEM|DER Output encoding format (DER or PEM)
Checkpoint: if your command does not list the option, stop and read that command's manpage. Do not assume that a format option from openssl pkey also belongs on another subcommand.
2. Let OpenSSL detect a normal key or certificate
Since OpenSSL 3.0, commands can normally try DER, PEM and P12 when reading keys, single certificates and CRLs. That makes a simple read useful when the file's extension is untrustworthy:
$ openssl pkey -in ./server-key.pem -noout -text
Private-Key: (2048 bit, 2 primes)
...key details...
The command reads the object and prints its details. The filename ending is not the format selector. A file called server-key.bin may still contain PEM, while a file called server-key.pem may be binary DER.
Automatic detection is convenient, but it is not always desirable. If a protocol or an interface requires one encoding, enforce it with -inform. A forced format is also a useful diagnostic: a DER input passed as -inform PEM should fail rather than being silently accepted as something else.
3. Convert a private key to DER, then verify it
DER is binary ASN.1 data. It is compact and predictable for interfaces that require binary input, but it is not readable in a text editor. Convert to a new path, leaving the original intact:
$ openssl pkey \
-in ./server-key.pem -inform PEM \
-out ./server-key.der -outform DER
$ openssl pkey -in ./server-key.der -inform DER -noout -text
Private-Key: (2048 bit, 2 primes)
...key details...
The first command reads PEM and writes DER. The second command forces DER while reading the result, so a successful parse verifies both the output file and the format choice. The details vary with the key algorithm and size; the important result is that OpenSSL accepts the file without an error.
Checkpoint: compare the file types without treating the output of file as cryptographic proof:
$ file ./server-key.pem ./server-key.der
./server-key.pem: PEM private key
./server-key.der: data
On some systems file identifies DER more specifically, and on others it only says data. The forced OpenSSL parse is the meaningful verification.
4. Convert a certificate and preserve its meaning
A certificate can be converted in the same way. The object does not change when its encoding changes:
$ openssl x509 \
-in ./server-cert.pem -inform PEM \
-out ./server-cert.der -outform DER
$ openssl x509 -in ./server-cert.der -inform DER \
-noout -subject -issuer -dates
subject=CN = example.invalid
issuer=CN = Example Test CA
notBefore=...
notAfter=...
Use the same inspection fields on the original and converted files if you need a direct check:
$ openssl x509 -in ./server-cert.pem -noout -fingerprint -sha256
$ openssl x509 -in ./server-cert.der -inform DER -noout -fingerprint -sha256
sha256 Fingerprint=...
The fingerprints should match. Do not use a visual comparison of PEM text: base64 wrapping and trailing newlines are encoding details, not certificate identity.
5. Treat PEM, P12 and ENGINE as different cases
PEM is text containing base64 between labelled BEGIN and END lines. The label must match the object the command expects. A certificate label will not satisfy a command reading a private key. PEM may also contain an encrypted private key, in which case OpenSSL needs a password supplied through its password-input options.
P12 means a DER-encoded PKCS#12 object, commonly a bundle containing a certificate and private key. It is not a generic synonym for every DER file. Use a command that understands PKCS#12, and expect it to request a decryption password when the bundle protects its private key:
$ openssl pkcs12 -in ./identity.p12 -info -noout
Enter Import Password:
MAC: sha256, Iteration 2048
...
This command inspects a bundle without writing its private contents to standard output. Protect the password and avoid putting it directly in the command line. If you only have a standalone DER certificate, use openssl x509, not openssl pkcs12.
ENGINE is different again. It names cryptographic material supplied by an OpenSSL engine. The engine must be configured or selected with the relevant engine option, and a PIN or password may be supplied through -passin. Do not replace ENGINE with DER merely because the key ultimately comes from hardware.
6. Avoid overwriting and privilege traps
These options select how data is parsed or emitted. They do not enable a certificate, install a key, change a service or make a private key safe to share. Write to a fresh temporary or destination path, inspect it, then perform the separately reviewed deployment step.
OpenSSL can overwrite an existing output path when the surrounding command permits it. Before a conversion, check the destination:
$ test ! -e ./server-key.der && echo 'destination is unused'
destination is unused
If it already exists, choose another name or move it only under your normal backup procedure. Recovery is simple when the source remains: delete the failed conversion and rerun it to a new path. Do not delete the source to save space until the consumer has accepted the converted file and your retention policy allows removal.
Normal reads and conversions run as your user. Use elevated privileges only when the input or output path is deliberately protected and your change procedure authorises access. sudo does not fix a format mismatch, and using it can create root-owned output that your service account cannot read.
Done means
- You checked that the specific OpenSSL subcommand accepts the format option.
- You know whether the input is being auto-detected or deliberately forced with
-inform. - A conversion writes a new path and the result is parsed again with the forced output format.
- Certificate fingerprints match before and after an encoding conversion.
- PEM, standalone DER, PKCS#12 and ENGINE inputs are not treated as interchangeable.
- Private keys and passwords remain protected, and no conversion overwrote the source.