General Computing
ssh rsa ssh-keygen
Updated Fri, 15 Jul 2022 11:31:29 GMT

Differences between "BEGIN RSA PRIVATE KEY" and "BEGIN OPENSSH PRIVATE KEY"


I'm trying to genereate RSA key to access somw git repositories in azure with ssh.

Having Ubuntu 22.04 and openssl version OpenSSL 3.0.2 15 Mar 2022,
I generate RSA key like this:

$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/me/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/me/.ssh/id_rsa
Your public key has been saved in /home/me/.ssh/id_rsa.pub
The key fingerprint is:
...
The keys randomart image is:
+---[RSA 4096]----+
....
....
+----[SHA256]-----+

But when I do $ cat ~/.ssh/id_rsa, I see my key file start with

-----BEGIN OPENSSH PRIVATE KEY-----

Should it be BEGIN RSA PRIVATE KEY instead? What is the difference?




Solution

Should it be

No, not really. The only "should" is that it should be a format that ssh itself understands. (The private key is never sent to the server, so there's no question about compatibility with Azure it only has to be compatible with your client.) So the key format that you currently have is correct; if your ssh-keygen produced it, then your ssh client will be able to use it.

There's no standard format for storing SSH private keys in files; each SSH client might use its own and in practice there are probably 4 or 5 different formats out there. Previously OpenSSH (the ssh program) just happened to use the PKCS#1 format because the OpenSSL library already used the same format for its own private keys and provided a convenient function for loading and storing keys in this format.

However, OpenSSH doesn't want to depend on OpenSSL after all, SSH itself isn't based on SSL/TLS in any way; the only reason OpenSSH is using OpenSSL at all is for its cryptography functions (libcrypto, e.g. RSA or AES) so it ended up creating its own private key format, initially just for Ed25519 keys, but eventually began using it for all algorithms. (Although it still understands the old format.)

Note that the actual "keys" (e.g. RSA primes, or EC points) still work the same way regardless of file format, so if needed you can easily convert from one format to another (using ssh-keygen -p -m or PuTTY's puttygen tools).

What is the difference?

PKCS#1 key files (BEGIN RSA PRIVATE KEY) come from the PEM encrypted messaging project. The format is fairly outdated, e.g. it's weak against passphrase bruteforcing. Even OpenSSL itself later started using a newer PKCS#8 format (which uses BEGIN PRIVATE KEY or BEGIN ENCRYPTED PRIVATE KEY headers) for all new private keys.

However, both PKCS#1 and PKCS#8 formats internally use ASN.1, which is a rather complex data serialization method for TLS software that's still acceptable, because they already need ASN.1 support to parse TLS certificates anyway, but for SSH clients it just brings another unnecessary dependency on OpenSSL.

In addition, their development is also primarily driven by TLS and X.509 certificates, which is a different world from SSH for example, when OpenSSH first got support for Ed25519 keys, it couldn't use OpenSSL's existing functions to store them, because that algorithm hadn't been adopted by the TLS world yet; an algorithm ID hadn't been assigned, the data format hadn't been agreed to.

So as a result, OpenSSH created its own format for storing private keys (the one with BEGIN OPENSSH PRIVATE KEY headers), which uses the same structures and algorithm identifiers as SSH itself does, meaning that any keys that SSH supports can be stored in the OpenSSH key format and they can be loaded/stored without relying on a SSL/TLS library any longer.

(PuTTY also has its own "PPK" key format for a similar reason of avoiding complex external libraries.)





Comments (1)

  • +0 – Just a couple of days ago I had to convert a private key using ssh-keygen, on account of paramiko not accepting the original format. — May 15, 2022 at 01:47