I recently had to use Dropbear to connect to a remote server using SSH. Dropbear is a lightweight SSH server and client designed for use in embedded environments. It provides the expected basic functionality and performs quite well.
However, there is one caveat - it doesn’t support common private key formats
used by OpenSSH. It’s using its custom binary format instead. There are two
utilities provided by the Dropbear package that help with the creation and
conversion of keys to the Dropbear format: dropbearkey and dropbearconvert.
Because I already had a key in a different format, I’ve decided to convert it to
make it usable with Dropbear. I’ve tried using dropbearconvert but it failed
with the following error message: Error: Ciphers other than DES-EDE3-CBC not supported
. I didn’t know what cipher my key was using or what type it was but I
decided to find out. This is how my journey into the subject of SSH keys began.
I spent a couple of hours reading about the various key types, differences between them, and how to convert them. This blog post is a summary of my research. The information here could be useful to others who also got confused by the subject but I also write is as a future reference for myself. I want to keep things practical, so I am not going to describe the theoretical details.
The most common types of SSH keys are PKCS #1, PKCS #8, and OpenSSH key format. Things like PEM, DER, PKCS #12, PFX are not key formats themselves but are often mentioned in relation to the keys so I will describe them here too.
PKCS #1
PKCS stands for Public-Key Cryptography Standards. PKCS #1 is the first standard in the PKCS group. It defines the mathematical properties that private and public keys should have, operations for encrypting and signing the keys, as well as cryptographic schemes.
PKCS #1 can only use the RSA algorithm, which is its biggest weakness. RSA is still safe but there are more secure algorithms out there and if you want to use them, PKCS #1 is not the right format for you.
Another problem with it is that PKCS #1 cannot be encrypted. That feature became available only later, in PKCS #5.
The PKCS #1 private key encoded in PEM looks like this:
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDN9S7xcO41n009aa2iBj5gkimJf1w6m6TLgSKmOjU50BlhEJeo
gGFUhnObOJLYbYO50CCe4RLcScdw8/gFQHP/9Y7Cdsil+KhSUyFTKS6R336IDzeV
Dfada3HiYBMIdt6kvP0imm+16Sau0bCUYuHiOy4G2YUuC6Q85l4nkR2IzwIDAQAB
AoGBAI9oNnyVVrhtqLmnWOhlko9plpSP4udIMtIko7y88QzFUraceA0y/xJ84Ahn
txAOCVebjOsz6w8KLF4A8mStwVZrK2PFVGl43XGZZnjMWwsLAJ7bDfNYJknrQLMe
FPAzWt2Vbsm+OJF456c6q/YgXpx3eIE7VUt4oOvl1ucH8LIZAkEA8ia/N/yH9zDw
tFpCtUNGXnjbe8Oq/5VI+nK8b27Lcsqc6sDLXtLhaxOS9yBUA6DVIKdKsECitON2
Mg4slZ+UOwJBANm8idu1EpIv9UgAiY/aIbzK8EA9uazY46ZZhGhYzhaXPht3W1Ee
mJp0bg4ObqFNQ9hlZYb6vCVmXlUEUzM7+H0CQDEFHQKlcZTd6GxqNUTiiJVJXA0y
8CPrQanJnlHkmPT1BU0UmFbq081MWh0DA170qRCCLUF+5DFANsYtTmM/uc8CQDKe
hl4xpnOd+qQWm+R5jcZaV6hXsUbh1Wri/MlVe/P8jU/NW8lsF4Yw8zUJXebaE5/H
Uucie4MmXV/edYk/s/ECQQDbuiOJKfEdrdd8h/n7PhIsXOVZvUBXu0Fg+txRG7Q9
IUrKwCtQsXo8WsTmA6iCZJKF5tr7iT/D7il0L35t/RdJ
-----END RSA PRIVATE KEY-----
Similarly, the PKCS #1 public key:
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAM31LvFw7jWfTT1praIGPmCSKYl/XDqbpMuBIqY6NTnQGWEQl6iAYVSG
c5s4kthtg7nQIJ7hEtxJx3Dz+AVAc//1jsJ2yKX4qFJTIVMpLpHffogPN5UN9p1r
ceJgEwh23qS8/SKab7XpJq7RsJRi4eI7LgbZhS4LpDzmXieRHYjPAgMBAAE=
-----END RSA PUBLIC KEY-----
NOTE: Sometimes PKCS #1 keys can be referred to as PEM keys.
I spotted this in the
OpenSSH documentationfor example.
The reason for this seems to be because PEM encoded keys using algorithms
different than RSA can also take a form similar to PKCS #1. See
RFC5915 for example.
PKCS #8
PKCS #8 is a newer standard that, compared to PKCS #1, brought support for encryption of the private keys and usage of algorithms other than RSA.
PKCS #8 private keys have the following opening and closing text:
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
The encrypted version:
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----
Public key:
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
OpenSSH private key format
This is a non-standard private key format developed by the OpenSSH team. It doesn’t have much in common with the PKCS keys, as it is constructed in a different way than them. It is however the default format for ssh-keygen. It is preferred by OpenSSH because it is supposedly more secure and allows for comments in the key. Just like PKCS #8, it can be encrypted and supports various algorithms.
An example of a OpenSSH private key:
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBiCMDSKv
BpGYDr79QiKcVIAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDGaG46lLBA
7DMaQHJoX/dGFpnJmbis4kBvyYxzRRuoKoxPKcqRvNSUbxG9PjovzJ0Ox0eK45qj2u4wq6
6PecJ8YIqCHBHxSCRFAyofCasfmqkQXW/k4K0rYevpB8cYPdCA6vXR1YAa0Yw8ZBKFROHh
82JrxEzvLq9luQLjSqZuVwAAAhCS+gS4s5RzCMyPuqE54qzaR9nuDB3Qai2ApsHdBopT5R
LhwHWZd79y4DYHRHiWGIqeGAXm0k3vrJd1MLWteSQeIMC+kJf6uFp9Ri7WJTO3QYcFLdzs
BbtTlzgTMZHRHMOGm1c5rVhwu+QcnvwMDdiLaAv4LMSmBl/IFsI7f1NEBjRfnyn9tEeKqO
M9ZHoMfIPzzuutypDHdb0kQdmEg8kQrBRGEa0pFiZ8YC+ADvG+nFOuJh0MfA6wtGciKeod
IxnwfWFXc7B1GdeNf3/q2TAa5mKKMhOIrk2uNWRcawYOB26TPQ0sxQcRlU0Qo06paPS3Qg
RyS8Rpbhsf87fodwxkU7ZKvK3mvbKG9PkQB/O2De5NnYBOsGaQhTDKr1lstqMQv5AgiLwY
pKotQ7ejhndVtp8FwrWqy5zKwpYX7pcBvie4wLgTrNHLdXiQm+hm1jyGtEtU5+ZfFXbt9b
PWtKlpke4Zcd34i3qKlgY6CGV40jPFmJ7gTRR5+l9KiFmPvCxFIi6g+y8APOBURT3wI57J
atANpQNpmbEFg+rVSrfP1W7ewhSxlZzCtxEwJU2xZ3y1vz1/UyyAjfJZzSgYcpeP9tmYJB
GqPVRk4FE8genXTeDy0UCm60/Pe+KnNGOjBr9L7ItO4jq1gK0oKIkVACaak0IF4zBsAcFi
J8UzZk/Kn2dZejEgB11ZtNXSDFUg9jI=
-----END OPENSSH PRIVATE KEY-----
The encrypted version has the same header and footer.
RFC4716 public key format
RFC4716 published by Internet Engineering Task Force (IETF) describes the standard SSH public key format. It is the public key format that is probably more common than PKCS #1 and PKCS #8 public key formats. Unlike them, it can contain some extra information like the Subject header for storing the user name associated with the key or the Comment header.
This is how it looks:
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "1024-bit RSA, converted from OpenSSH by me@example.com"
x-command: /home/me/bin/lock-in-guest.sh
AAAAB3NzaC1yc2EAAAABIwAAAIEA1on8gxCGJJWSRT4uOrR13mUaUk0hRf4RzxSZ1zRb
YYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ
5TT4SfsUu/iKy9lUcCfXzwre4WWZSXXcPff+EHtWshahu3WzBdnGxm5Xoi89zcE=
---- END SSH2 PUBLIC KEY ----
It can also take a one-line form, which is more common:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1on8gxCGJJWSRT4uOrR13mUaUk0hRf4RzxSZ1zRbYYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ5TT4SfsUu/iKy9lUcCfXzwre4WWZSXXcPff+EHtWshahu3WzBdnGxm5Xoi89zcE= 1024-bit RSA, converted from OpenSSH by me@example.com
PKCS #12 / PFX
PKCS #12 is an archive file format. It is typically used to bundle a private key and the certificate associated with it. It can be encrypted and signed. It is a binary file format. It was first developed by Microsoft as PFX (Personal Information Exchange) and then re-released as PKCS #12.
ASN.1, DER, PEM
As a bonus, a little explanation about the things often mentioned in relation to SSH keys.
ASN.1 stands for Abstract Syntax Notation One and is an interface description language that is a standard for defining cryptographic data structures.
Here’s an example of the RSA private key represented in ASN.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
}
You can find this example and read more about it in RFC8017.
The data in this form cannot be transferred, so it needs to be encoded. Typically, that would mean encoding it in DER or PEM formats.
DER stands for Distinguished Encoding Rules and is a binary encoding format. The private key from the example about PKCS #1 encoded into DER looks following:
00000000: 3082 025d 0201 0002 8181 00cd f52e f170
00000010: ee35 9f4d 3d69 ada2 063e 6092 2989 7f5c
00000020: 3a9b a4cb 8122 a63a 3539 d019 6110 97a8
00000030: 8061 5486 739b 3892 d86d 83b9 d020 9ee1
00000040: 12dc 49c7 70f3 f805 4073 fff5 8ec2 76c8
00000050: a5f8 a852 5321 5329 2e91 df7e 880f 3795
00000060: 0df6 9d6b 71e2 6013 0876 dea4 bcfd 229a
00000070: 6fb5 e926 aed1 b094 62e1 e23b 2e06 d985
00000080: 2e0b a43c e65e 2791 1d88 cf02 0301 0001
00000090: 0281 8100 8f68 367c 9556 b86d a8b9 a758
000000a0: e865 928f 6996 948f e2e7 4832 d224 a3bc
000000b0: bcf1 0cc5 52b6 9c78 0d32 ff12 7ce0 0867
000000c0: b710 0e09 579b 8ceb 33eb 0f0a 2c5e 00f2
000000d0: 64ad c156 6b2b 63c5 5469 78dd 7199 6678
000000e0: cc5b 0b0b 009e db0d f358 2649 eb40 b31e
000000f0: 14f0 335a dd95 6ec9 be38 9178 e7a7 3aab
00000100: f620 5e9c 7778 813b 554b 78a0 ebe5 d6e7
00000110: 07f0 b219 0241 00f2 26bf 37fc 87f7 30f0
00000120: b45a 42b5 4346 5e78 db7b c3aa ff95 48fa
00000130: 72bc 6f6e cb72 ca9c eac0 cb5e d2e1 6b13
00000140: 92f7 2054 03a0 d520 a74a b040 a2b4 e376
00000150: 320e 2c95 9f94 3b02 4100 d9bc 89db b512
00000160: 922f f548 0089 8fda 21bc caf0 403d b9ac
00000170: d8e3 a659 8468 58ce 1697 3e1b 775b 511e
00000180: 989a 746e 0e0e 6ea1 4d43 d865 6586 fabc
00000190: 2566 5e55 0453 333b f87d 0240 3105 1d02
000001a0: a571 94dd e86c 6a35 44e2 8895 495c 0d32
000001b0: f023 eb41 a9c9 9e51 e498 f4f5 054d 1498
000001c0: 56ea d3cd 4c5a 1d03 035e f4a9 1082 2d41
000001d0: 7ee4 3140 36c6 2d4e 633f b9cf 0240 329e
000001e0: 865e 31a6 739d faa4 169b e479 8dc6 5a57
000001f0: a857 b146 e1d5 6ae2 fcc9 557b f3fc 8d4f
00000200: cd5b c96c 1786 30f3 3509 5de6 da13 9fc7
00000210: 52e7 227b 8326 5d5f de75 893f b3f1 0241
00000220: 00db ba23 8929 f11d add7 7c87 f9fb 3e12
00000230: 2c5c e559 bd40 57bb 4160 fadc 511b b43d
00000240: 214a cac0 2b50 b17a 3c5a c4e6 03a8 8264
00000250: 9285 e6da fb89 3fc3 ee29 742f 7e6d fd17
00000260: 49
Because the binary files are not that convenient to send over email or other text-oriented channels, PEM was created.
PEM stands for Privacy-Enhanced Mail. It is a set of standards designed for the encryption of emails. It was never really adopted, as PGP and S/MIME turned out to be more used. However, the text encoding of keys it proposed, is still widely used.
PEM formatted keys are basically DER keys encoded using base64 with some metadata.
Useful commands
Below you can find a number of commands that can be used for creating the keys and converting them to different formats.
Generate PKCS #1 private key
ssh-keygen -m pem -b <size> -f <output file>
or
openssl genrsa -out <output file> <size>
Generate PKCS #8 private key
ssh-keygen -m pkcs8 -t <algorithm> -b <size> -f <output file>
or
openssl genpkey -out <output file> -algorithm <algorithm>
Generate OpenSSH private key
ssh-keygen -t <algorithm> -b <size> -f <output file>
Extract the public key
ssh-keygen -y -f <input file>
or
openssl pkey -in <input file> -pubout -out <output file>
Convert PKCS #1 private key to PKCS #8
ssh-keygen -m pkcs8 -p -N '' -f <input file>
or
openssl pkcs8 -topk8 -in <input file> -nocrypt -out <output file>
Convert PKCS #8 private key to PKCS #1 or other PEM formats
ssh-keygen -m pem -p -N '' -f <input file>
or
openssl pkcs8 -traditional -in <input file> -nocrypt -out <output file>
Convert PKCS #1 or PKCS #8 private keys to OpenSSH format
By “adding” an empty comment:
ssh-keygen -f <input file> -o -c -C ''
By setting an empty password:
ssh-keygen -p -N '' -f <input file>
Generate Dropbear private key
dropbearkey -t <algorithm> -f <output file> -s <size>
Convert OpenSSH private key to Dropbear
dropbearconvert openssh dropbear <input file> <output file>