## 1. Introduction

Keys are an integral part of security. They support authentication by verifying the identity of the key holder. Although there are standards that define each key format, different applications can employ incompatible formats.

In this tutorial, we explore ways to convert a PEM key to a DER key. First, we talk about the DER format. After that, we move to the PEM format. Next, we convert from PEM to DER. Finally, we perform the reverse conversion from DER to PEM.

We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.2.15. It should work in most POSIX-compliant environments unless otherwise specified.

## 2. Distinguished Encoding Rules (DER) Format

To begin with, the ASN.1 (Abstract Syntax Notation 1) is a language to define data structures. It’s the root for many formats.

For example, let’s see the ASN.1 fields for encoding an RSA private key as defined in RFC 3447 – Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1:

``````RSAPrivateKey ::= SEQUENCE {
version           Version,
modulus           INTEGER,  -- n
publicExponent    INTEGER,  -- e
privateExponent   INTEGER,  -- d
prime1            INTEGER,  -- p
prime2            INTEGER,  -- q
exponent1         INTEGER,  -- d mod (p-1)
exponent2         INTEGER,  -- d mod (q-1)
coefficient       INTEGER,  -- (inverse of q) mod p
otherPrimeInfos   OtherPrimeInfos OPTIONAL
}``````

According to the standard, such [SEQUENCE]s of fields are encoded in several ways:

• BER (Basic Encoding Rules)
• CER (Canonical Encoding Rules)
• DER (Distinguished Encoding Rules)

Critically, BER, CER, and DER are all binary formats.

For example, let’s explore a DER file:

``````\$ cat data.der
0
x
\$ cat --show-all data.der
0^O^D\$
0^H^B^B^BM-BM-^Z^B^B^BM-BM-^[^S^Ax
\$ xxd data.der
00000000: 300f 040a 3008 0202 02c2 9a02 0202 c29b  0...0...........
00000010: 1301 78                                  ..x``````

As we can see, the simple cat command doesn’t properly display all of the data, since it contains non-printable characters. Still, we can see them in M-notation via the –show-all flag of cat. Further, we can also confirm the content with a hex editor like xxd.

Notably, ASN.1 structures can represent many kinds of data, not only security keys or certificates.

## 3. Privacy-Enhanced Mail (PEM) Format

The Privacy-Enhanced Mail (PEM) standard takes content in the BER, CER, or DER format, encodes it in Base64, and wraps it with a special clear-text header and footer:

``````-----BEGIN XDATA-----
MA8ECjAIAgICwpoCAgLCmxMBeA==
-----END XDATA-----``````

Here, we can see the —–BEGIN <LABEL>—– header and the —–END <LABEL>—– footer surrounding the Base64 string of data. In fact, this is the value of data.der from earlier.

Similar to DER, PEM can represent different data.

For example, let’s use openssl to [gen]erate 2048-bit rsa keys in the (default) PEM format and extract the public key in a separate file:

``````\$ openssl genrsa -outform PEM -out pem.key 2048
\$ openssl rsa -in pem.key -pubout -out pem.key.pub
writing RSA key``````

So, we now have a pem.key private and a pem.key.pub public key files:

``````\$ cat pem.key
-----BEGIN PRIVATE KEY-----
[...]
93tbu666Rsbi/w==
-----END PRIVATE KEY-----
\$ cat pem.key.pub
-----BEGIN PUBLIC KEY-----
[...]
-----END PUBLIC KEY-----``````

Let’s see how we can convert them to DER.

## 4. PEM to DER

Both PEM and DER are often used for TLS and in conjunction with the X.509 certificate standard. However, they can also represent keys.

Let’s see how to convert our private and public RSA PEM keys to DER:

``````\$ openssl rsa -inform PEM -in pem.key -outform DER -out key.der
writing RSA key
\$ openssl rsa -pubin -inform PEM -in pem.key.pub -outform DER -out key.der.pub
writing RSA key``````

Apart from the filenames, the main difference between the two conversions is the -pubin public key indicator flag. In case of errors, we can check the proper input format. For example, default ssh-keygen public keys won’t work directly with openssl, since they don’t adhere to the PEM format.

At this point, we have the key.der private and key.der.pub public keys in the DER format.

## 5. DER to PEM

Now, let’s see a basic way to convert the data.der file to the PEM format:

``````\$ printf -- '-----BEGIN XDATA-----\n%s\n-----END XDATA-----' "\$(cat data.der | base64)"
-----BEGIN XDATA-----
MA8ECjAIAgICwpoCAgLCmxMBeA==
-----END XDATA-----``````

Here, we use the printf command to output the PEM header and footer. Between them, we insert the result of a \$() command substitution via the %s string format specifier. Within the command substitution, we pipe the contents of data.der to the base64 utility for encoding.

In essence, we manually converted data.der to the PEM format.

Naturally, we can do the same for keys. However, it’s usually better to employ a standard tool like openssl for the purpose:

``````\$ openssl rsa -inform DER -in key.der -outform PEM -out pem.key
writing RSA key
\$ openssl rsa -pubin -inform DER -in key.der.pub -outform PEM -out pem.key.pub
writing RSA key``````

Now, let’s verify the resulting PEM files:

``````\$ cat pem.key
-----BEGIN PRIVATE KEY-----
[...]
93tbu666Rsbi/w==
-----END PRIVATE KEY-----
\$ cat pem.key.pub
-----BEGIN PUBLIC KEY-----