2

For an ordinary user, how would I verify that a private key file was generated using reasonably secure algorithms? In response to things like allegedly insecure ssh-keygen defaults.

forest
  • 64,616
  • 20
  • 206
  • 257
l0b0
  • 2,981
  • 20
  • 29
  • On *nix systems, `grep BEGIN ~/.ssh/id_*` ... If it **doesn't** have OPENSSH PRIVATE KEY ... then you have the old format keys. .... I typically use my PGP keys through ssh-agent and let GPG handle the key management. – RubberStamp Jan 07 '19 at 03:05
  • @RubberStamp Assuming that an ordinary user has no idea what "old format" means, how would they know what that means and whether it's secure or not? – l0b0 Jan 07 '19 at 03:06
  • Related... and [possible dup](https://security.stackexchange.com/questions/39279/stronger-encryption-for-ssh-keys) ... try `openssl asn1parse -in -` ... – RubberStamp Jan 07 '19 at 03:24
  • @RubberStamp @TomLeek is able to read that output, but I'm not. The `man` page just says "Some knowledge of the ASN.1 structure is needed to interpret the output." I wouldn't know where to begin to establish within a reasonable amount of time what the KDF is, for example. – l0b0 Jan 07 '19 at 04:21
  • @RubberStamp+ asn1parse doesn't work at all on either kind of encrypted privatekey file ssh-keygen can create, neither the OpenSSL 'traditional' format with PEM-level encryption nor the OpenSSH 'new' format with body-level encryption but non-ASN.1 encoding (instead XDR-like) – dave_thompson_085 Jan 07 '19 at 05:05
  • @dave_thompson_085 ... >ans1parse doesn't work on encrypted... *That's why `openssl` prompts for the passphrase when one attempts to do so...* My fist comment, now your answer, was the quick and easy way to test and given key... My second comment, linked to the very excellent and detailed Q/A from 5 years ago, shows how to dissect a key if one knows the passphrase. – RubberStamp Jan 07 '19 at 12:51
  • @RubberStamp: `openssl rsa`, `openssl pkey`, and other operations that internally call `PEM_read_*PrivateKey`, prompt for the password when needed; `openssl asn1parse` does not, and can't decrypt even if you could give it a password. Plus OpenSSL can't handle OpenSSH-newformat encryption at all. The Bear's answer at your link (as you say, and as usual, excellent) doesn't use the password to 'dissect' anything; it does use `asn1parse` to show the _unencrypted_ metadata for PKCS8, but ssh-keygen never writes PKCS8. I agree it is a pretty good dupe for the Q, though. – dave_thompson_085 Jan 09 '19 at 09:42
  • >openssl asn1parse does not, and can't decrypt even if you could give it a password..... *The magic of piping... `openssl rsa -in mykey.pem | openssl asn1parse -in -` ... I did not write that the passphrase is used to dissect anything. Please quote exactly if you wish to quote. – RubberStamp Jan 09 '19 at 11:46

1 Answers1

8

As RubberStamp points out, this is covered in detail in stronger encryption for SSH keys but to summarize:

Look at the words in the first line, and the next one or two.

 -----BEGIN RSA PRIVATE KEY-----
 Proc-Type: 4,ENCRYPTED
 DEK-Info: DES-EDE3-CBC,(hex)

 (several lines of base64)
 -----END RSA PRIVATE KEY-----

(or similarly with DSA PRIVATE KEY or EC PRIVATE KEY) is the old, bad-PBKDF format.

 -----BEGIN RSA PRIVATE KEY----- # or DSA,EC
 (base64 immediately)
 -----END RSA PRIVATE KEY----- # ditto 

is the old unencrypted format, which is even worse.

 -----BEGIN OPENSSH PRIVATE KEY-----
 (several lines of base64)
 -----END OPENSSH PRIVATE KEY-----

is the OpenSSH-specific 'new' format, which is why it says OPENSSH right there. However, this format doesn't directly show whether it's encrypted or not. The easiest way is to try reading it (either for an ssh connection, or with ssh-keygen to convert or modify it) and see if it needs a password. Alternatively, you can strip the labels and decode the base64 (conveniently, openssl base64 -d does both of these!) and look at it:

$ openssl base64 -d <se200935.clr |od -c
0000000   o   p   e   n   s   s   h   -   k   e   y   -   v   1  \0  \0
0000020  \0  \0 004   n   o   n   e  \0  \0  \0 004   n   o   n   e  [snip rest]

$ openssl base64 -d <se200935.enc |od -c
0000000   o   p   e   n   s   s   h   -   k   e   y   -   v   1  \0  \0
0000020  \0  \0  \n   a   e   s   2   5   6   -   c   b   c  \0  \0  \0
0000040 006   b   c   r   y   p   t [snip rest]
dave_thompson_085
  • 9,759
  • 1
  • 24
  • 28
  • So is the "new OpenSSH-specific format" considered secure or not? I don't get this from your answer unfortunately. – bers Nov 26 '19 at 10:09
  • 1
    @bers: Yes, OpenSSH 'new' format -- IF encrypted (see edit) -- uses bcrypt with sane parameters, which is a good PBKDF. It also uses good symmetric encryption, but that's not a differentiator, even OpenSSH 'old' format which is OpenSSL 'traditional' format does that. – dave_thompson_085 Nov 28 '19 at 08:09
  • This hex dumping answer is great. A small simplification that's easier on the eyes is to use strings instead. E.g. `openssl base64 -d < ~/.ssh/id_rsa | strings` – JPvRiel Jan 11 '21 at 18:29
  • `hexdump -C` is a very readable alternative. – Marcus Apr 21 '21 at 07:43