# Encoding public keys in PEM format

One of the most common uses of PEM files is storing or exchanging public keys. But there is more than one way to store a public key in a PEM file.

## PKCS#1 RSAPublicKey

The oldest and arguably most simple PEM-based file format for public keys is `RSAPublicKey`

.
We can recognize `RSAPublicKey`

files by their `BEGIN RSA PUBLIC KEY`

header:

```
-----BEGIN RSA PUBLIC KEY-----
MIIBigKCAYEAq3DnhgYgLVJknvDA3clATozPtjI7yauqD4/ZuqgZn4KzzzkQ4BzJ
ar4jRygpzbghlFn0Luk1mdVKzPUgYj0VkbRlHyYfcahbgOHixOOnXkKXrtZW7yWG
jXPqy/ZJ/+...
-----END RSA PUBLIC KEY-----
```

We can create a public key in RSAPublicKey format with OpenSSL like so:

```
openssl genrsa -out private-key.pem 3072
openssl rsa -in private-key.pem -RSAPublicKey_out -out public-key.pem
```

Notice the `-RSAPublicKey_out`

parameter, which explicitly instructs OpenSSL to
use the `RSAPublicKey`

format.

When we open the resulting public key file in an ASN.1 Editor, the format looks pretty straightforward – it’s just a sequence of two integers:

As we saw last time,
ASN.1 doesn’t encode any metadata such as field names. To
make sense of the data structure, we need to take a look at
RFC 3447:
*Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1*:
In appendix A, the RFC
describes how RSA keys should be represented in ASN.1, and defines the following structure:

```
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
```

So the two integers that we see in the screenshot are the modulus, followed by the exponent.

While RSA is still popular, it obviously isn’t the only asymmetric encryption algorithm anymore. What if we want to use another algorithm like elliptic curve cryptography and store a public key for it? Clearly, we need a more flexible file format than one that only supports RSA. That leads us to…

## X.509 SubjectPublicKeyInfo

Today, the public key format we see most commonly looks like this:

```
-----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAq3DnhgYgLVJknvDA3clA
TozPtjI7yauqD4/ZuqgZn4KzzzkQ4BzJar4jRygpzbghlFn0Luk1mdVKzPUgYj0V
kbRlHyYfcahbgOHixOOnXkKXrtZW7yWGjXPqy/ZJ/+kFBNPAzxy7fDuAzKfU3Rn5
0sBakg95pua14W1oE4rtd4/U+sg2maCq6HgGdCLLxRWwXA8IBtvHZ48i6kxiz9tu
...
-----END PUBLIC KEY-----
```

This is the `SubjectPublicKeyInfo`

format, and it’s the format OpenSSL uses by default
when generating a public key:

```
openssl genrsa -out private-key.pem 3072
openssl rsa -in private-key.pem -pubout -out public-key.pem
```

When we open this `SubjectPublicKeyInfo`

-formatted RSA public key file in an ASN.1 Editor,
it looks a bit more complex:

To make sense of this ASN.1 structure, we again have to refer to an RFC – this time
RFC5280, which describes the
*Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile*. The RFC contains the following definition:

```
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING }
```

What we have here is essentially a discriminated union:
The first field, `algorithm`

, contains an OID
that idenfifies the format of the key in the `subjectPublicKey`

field.

For example, if `algorithm`

contains `1.2.840.113549.1.1.1`

, then `subjectPublicKey`

contains a `RSAPublicKey`

structure, which is the one we’ve seen previously. Indeed, if you compare the
two screenshots, you notice that the second one looks like the first, just with a header prepended.

Thanks to its more flexible structure, we can use the `SubjectPublicKeyInfo`

format for other
asymmetric encryption algorithms such as ECC:

```
openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem
openssl ec -in private-key.pem -pubout -out public-key.pem
```

If we open an ECC public key, we can see that the header contains a different OID, and that
the `subjectPublicKey`

bit string isn’t interpreted as an RSA public key anymore:

## SSH2 public keys

There’s another public key format that we’re frequently dealing with, SSH2 public keys:

```
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "2048-bit RSA,... "
AAAAB3NzaC1yc2EAAAADAQABAAABAQCh3jBV1PZ7i/FAqfx0Vev77BuuXyxO0eocYZ1Zkq
ZdRqWzzbB5CByO3X9CAGhqAs/d5cI7vVXKtSijJHl+RDUHfGYoRerJbFrl+gl1jt0I4RLt
cFoFnVUdhF/5aK9J29VmwIkcudq9Hi2f9ryWpJgmuZ+Ok6tb5jIwWEv4Mpl5cq7ubBw1Fq
iqF3kSI/OB7c6Ck...
---- END SSH2 PUBLIC KEY ----
```

This looks deceivingly similar to the `RSAPublicKey`

- and `SubjectPublicKeyInfo`

-formatted
PEM files we looked at previously – but that’s a red herring: SSH public keys don’t
use the PEM format at all, as the RFC astutely points out:

Implementers should take care to notice that while the format is superficially similar to those specified by PEM [RFC1421] and OpenPGP [RFC2440], it is not identical; most notably:

- The other specifications use different BEGIN/END delimiters (five dashes, no space rather than four dashes and a space).
- There is no blank line before the start of the base64-encoded contents.
- There is no Cyclic Redundancy Check (CRC) at the end of the base64-encoded block.
- Header continuation uses a backslash at the end of the continued line rather than whitespace at the start of the next line.

So what is it then, if not a PEM file? It’s just a slightly enhanced version of the original OpenSSH key format defined in [RFC4253], Section 6.6, which looks like this:

```
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCh3jBV1PZ7i/FAqfx0Vev77BuuXyxO0eocYZ1ZkqZdRqWzzbB5CByO3X9CAGhqAs/d...
```

The base64-encoded body is the same in both formats, all that the SSH2 format adds is the header, footer, and the ability to add metadata such as comments.

In the next posts, we’ll explore how we can import and export public keys in .NET.