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
# 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.derOptions
| Flag | What it does |
|---|---|
| -traditional | Emit PKCS#1 (RSA PRIVATE KEY) instead of PKCS#8 |
| -outform der|pem | Output 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.