10

I want to create private and public key pairs to be used for SSH authentication.

I can't figure out the difference between this:

openssl genrsa -out MyPrivateKey 4096
openssl rsa -in MyPrivateKey -pubout -out MyPublicKey

which first creates a private RSA key and then derives the public key from it, or:

ssh-keygen -b 4096 -t rsa -f MyFancyKey

which creates a private RSA key in the file 'MyFancyKey' and the corresponding public key in 'MyFancyKey.pub'.

The structure for the private keys seems somewhat similar, although the one created with openssl begins with:
-----BEGIN RSA PRIVATE KEY-----

And the one from ssh-keygen begins with:
-----BEGIN OPENSSH PRIVATE KEY-----

Is there a fundamental difference between these two kinds of keys?


Then the corresponding public keys, the one from openssl contains:

-----BEGIN PUBLIC KEY-----
  ...base64 encoded...
-----BEGIN PUBLIC KEY-----

While the one from ssh-keygen just contains one line:
ssh-rsa XXXXXX...base64 encoded...XXXXX Rocketnuts@Rocketnuts-MBP.my.networkname

Are these essentially the same kind of data but formatted differently? Or are they really incompatible?

I'm trying to fully understand how all this works in relation to SSH. For example why is my username, my computer name, and my local network name in that key, isn't it typically supposed to be used to access SSH on other computers? With my username on that computer, not my own.

RocketNuts
  • 1,342

1 Answers1

9

Private keys

Is there a fundamental difference between these two kinds of keys?

No, they're essentially the same data.

  • BEGIN RSA PRIVATE KEY indicates "PKCS#1" or "PEM" key format, which is Base64 encoding of an ASN.1 DER serialized structure. It's a basic ASN.1 sequence containing the RSA parameters (n, e, d, p, q, etc).

    This format comes from the PEM email security effort that later became S/MIME (hence the usage of ASN.1 DER) and was commonly used for SSL/TLS as well as miscellaneous generic RSA.

    For a long time, it was also OpenSSH's primary key format (because OpenSSH already uses OpenSSL's cryptographic code, so the "load key" and "write key" functions were also conveniently available). This means you can use ssh-keygen -m PEM to generate or convert such keys.

  • BEGIN PRIVATE KEY indicates "PKCS#8" key format (unencrypted); it'the contents are very similar to the PEM format, with the same RSA parameters nested inside another structure that indicates that it is indeed an RSA key.

    PKCS#8 is specifically meant as the more modern replacement of the PEM format. Compared to PEM, the PKCS#8 format more cleanly separates the "payload" (key algorithm, encryption) from the outer Base64 wrapper – all metadata is now inside the structure, so it's easier to update for new key types. The new format also supports better ciphers and KDFs for encrypted keys.

    OpenSSH will recognize this format too (due to its OpenSSL usage for key loading), and I think recent versions are also able to create it.

  • BEGIN OPENSSH PRIVATE KEY is a format invented by OpenSSH for OpenSSH, and unlike the PEM/PKCS formats, it uses SSHv2 packet serialization for its data structures (no more DER or ASN.1).

    One reason OpenSSH now uses this format so that it could avoid depending on OpenSSL entirely, and/or so that it could add new key algorithms without waiting for OpenSSL to implement loading/saving of those keys – which also means waiting for PKIX to standardize the ASN.1 OID and structure for each new algorithm (which otherwise has absolutely nothing to do with SSH).

    For example, it took a while for OpenSSL to gain full Ed25519 support, during which time OpenSSH could neither use OpenSSL's libcrypto for the actual math, nor for loading/saving Ed25519 key files – that's what prompted the creation of this format.

    Another advantage of the OpenSSH format is that passphrase-encrypted keys use bcrypt for the encryption key derivation; at the time the PEM format was limited to a very weak (i.e. easy to bruteforce) KDF, and even PKCS#8 supports only the slightly inferior PKBDF2.

  • PuTTY has its own .ppk format, which is mostly text-based.

    Its claimed advantage is that it doesn't need a separate .pub file because it only encrypts the private parameters selectively – whereas both the earlier PKCS formats and the later OpenSSH format encrypt everything or nothing, so they need the .pub file so that they could offer the key before asking you for the passphrase to unlock it.

    You can use /usr/bin/puttygen to convert between all these formats.

  • Java software might use the PKCS#12 (PFX) format due to it being the native "Java keystore" format, and some software might even use the SSH.COM alleged-standard format.

See also: OpenSSH public key file format?

Public keys

Are these essentially the same kind of data but formatted differently?

Yes, they're essentially the same data.

  • BEGIN PUBLIC KEY is, I believe, also PKCS#8 – so inside Base64 there's a DER-serialized ASN.1 structure which identifies it as an RSA key, followed by key parameters (n, e).

  • The one-line format is partially OpenSSH-specific, although the central Base64-encoded data is in exactly the same format as used within the SSHv2 protocol itself ("on the wire"). As you might guess, the encoded data uses SSHv2 packet serialization – but it still holds the same RSA n and e values.

See also: OpenSSH public key file format?

For example why is my username, my computer name, and my local network name in that key

It's a comment to help you distinguish this public key from other public keys when you have a long authorized_keys file.

grawity
  • 501,077