Skip to content
Latchkey

openssl rsa: PEM, DER and PKCS#1 vs PKCS#8

openssl rsa changes a key between PEM and DER and between the PKCS#1 and PKCS#8 layouts.

Different runtimes want different key headers. Knowing PKCS#1 (RSA PRIVATE KEY) vs PKCS#8 (PRIVATE KEY) saves hours of "unsupported key" debugging.

What it does

openssl rsa re-encodes RSA keys. -traditional emits PKCS#1 (header "BEGIN RSA PRIVATE KEY"); without it OpenSSL 3.x emits PKCS#8 ("BEGIN PRIVATE KEY"). openssl pkcs8 converts the other direction or adds encryption.

Common usage

Terminal
# PKCS#8 -> PKCS#1 (traditional)
openssl rsa -in pkcs8.pem -traditional -out pkcs1.pem
# PKCS#1 -> PKCS#8
openssl pkcs8 -topk8 -nocrypt -in pkcs1.pem -out pkcs8.pem
# PEM -> DER
openssl rsa -in key.pem -outform der -out key.der

Options

FlagWhat it does
-traditionalEmit PKCS#1 (RSA PRIVATE KEY) instead of PKCS#8
-outform der|pemOutput encoding
-topk8 (pkcs8)Convert to PKCS#8 with the pkcs8 command
-nocrypt (pkcs8)Produce an unencrypted PKCS#8 key

In CI

OpenSSL 1.1.1 wrote PKCS#1 by default; OpenSSL 3.x writes PKCS#8. A script that worked on an old runner image can break on a newer one purely because of the changed default header. Pin the format explicitly with -traditional or -topk8.

Common errors in CI

A library reporting "unsupported" or "unsupported PEM" on a key it used to read is hitting the PKCS#1 vs PKCS#8 default change; convert with -traditional or -topk8 to match what it expects. "header too long" means PEM was handed to a DER reader.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →