Skip to main content

Is this a cryptographic key which I see before me?

· 4 min read
Daniel Bevenius
Maintainer

Yes, it is. Really? Then what format is it in and how can I tell?

I've found myself in this situation a number of times and this post tries to provide some guidelines for figuring out the type and format of keys without having to go off and read some project's documentation.

To start off we can try to determine if the key is in a PEM format, or in DER format.

Keys in PEM format are in ascii and can be inspected from the command line using cat, or opened in any text editor. For example:

$ cat pubkey.pem
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDTvL0PRsxoxMXfSaXu+7w0ovVNzZ
k/BAIoz2GL2cPY3qZENU/+YrR92AuZFXn0jSmmvOktpAzGhnDhtidonkyA==
-----END PUBLIC KEY-----

If we try the same with DER format then we will get a bunch of strange characters printed. For example:

$ cat pubkey.der
;���lƌL]��^��J/T�ٓ�@"����=��dCT��+G݀��W�HҚkΒ�@�hgv���$

PEM formatted keys

So we have determined that the key we have in front of us is in PEM format. Now, if we take a look at the PEM output above again:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDTvL0PRsxoxMXfSaXu+7w0ovVNzZ
k/BAIoz2GL2cPY3qZENU/+YrR92AuZFXn0jSmmvOktpAzGhnDhtidonkyA==
-----END PUBLIC KEY-----

We can see that it has a header and the footer. Notice that there is no information about the type of public key that this file contains. This means that the information about the type of key in baked in there somewhere. So how can we find out what the type of the key?
One option is to use the openssl asn1parse command:

$ openssl asn1parse -i  -in pubkey.pem
0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING

And we can see, that there is an id here which is ecPublicKey.

As a rule of thumb, if there is no key type in the PEM header, then the format of the key is most probably in Subject Public Key Info (SPKI) if it is a public key, and in Public-Key Cryptography Standard 8 (pkcs8) format if it is a private key.

With the knowledge that the key is an Elliptic Curve (EC) public key we can use the following openssl command to inspect it:

$ openssl ec -pubin -in pubkey.pem --text --noout
read EC key
Public-Key: (256 bit)
pub:
04:0d:3b:cb:d0:f4:6c:c6:8c:4c:5d:f4:9a:5e:ef:
bb:c3:4a:2f:54:dc:d9:93:f0:40:22:8c:f6:18:bd:
9c:3d:8d:ea:64:43:54:ff:e6:2b:47:dd:80:b9:91:
57:9f:48:d2:9a:6b:ce:92:da:40:cc:68:67:0e:1b:
62:76:89:e4:c8
ASN1 OID: prime256v1
NIST CURVE: P-256

Some PEM keys can also be in a specific key format, in which case the type is in the header of the pem, for example:

-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----

And if needed we can use the openssl rsa command to inspect them further.

The same reasoning can be applied to private keys as well with regards to the PEM header/footer information, and in the case of private keys the -pubin argument to the openssl commands should left out.

DER formatted keys

As mentioned before we can't just print DER files as they are in binary format, but we can still use openssl asn1parse:

$ openssl asn1parse -i -inform der  -in pubkey.der
0:d=0 hl=2 l= 89 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
23:d=1 hl=2 l= 66 prim: BIT STRING

And just like with the PEM example we can use other openssl tools to inspect the key.

When the guidelines fail

The above seems to work for most situations, but it can fail.

One example of this is when openssl cannot parse the key at all. I ran into this recently with in-toto-rs, which uses the Rust ring crate to handle Ed25519 keys.

The issue here is that ring supports pkcs8 version 2 (RFC-5958), and OpenSSL currently only supports pkcs8 version 1 (RFC-5208), so the openssl tools will not be able to parse keys in the version 2 format.

Below is an example of trying to use a version 2 formatted Ed25519 key with openssl:

$ openssl pkey -inform der -in ed25519-1 -pubout
Could not read key from ed25519-1

There is an open openssl issue for this.

Hopefully there will not be many cases like this, and we hope that the guidelines provided in this post are helpful.