Question is simple:
What are the (private) key types and (their specification - format, syntax) accepted by current openSSH?
The vague answer "the keys generated by ssh-keygen
" is not accepted - I know it. They are called PEM with such headers (RSA, DSA, ECDSA variations):
-----BEGIN RSA PRIVATE KEY-----
The other format is described in PROTOCOL.key and is extension by openssh
. It is also used as a default for Ed25519
keys, as stated in manual and (regardless passphrase) marked with header:
-----BEGIN OPENSSH PRIVATE KEY-----
There are also legacy RSA1
keys that should be gone today with SSHv1 protocol, but can be identified by the header:
SSH PRIVATE KEY FILE FORMAT 1.1
Are there any others? I am searching for more verbose description of other keys. I didn't find it (so far) explicitly specified in any manual page nor in any RFC for SSH.
The bonus question (not needed to answer, but I would appreciate the insight):
What is the reason behind (
openssh
) decoding every dummy file and asking for a passphrase, even if it does not have the proper header?
Footnote: Question was originally posted on openssh-unix-dev list, but so far without any answer so I am trying this awesome community, if there is somebody able to answer it.
-----BEGIN
and-----END
strings are merely encapsulation boundaries (EB) with an included comment. The actual info is found in the base64 serialized structure in between. Without having checked the source code, I'd guess the text in the EBs is ignored by openssh that only tries to decode whatever is in between. The ciphername and KDF info should indicate what are types of the actual keys stored in the structure. I'd also guess these are open to future values and there's no fixed list.openssh
key is documented, them PEM has also RFC specification and it is probably all. Ifopenssh
reads something that does not make sense or is not base64, it should probably error out, shouldn't it?sshkey.c
. Insshkey_parse_private_fileblob_type()
, you can see all the supported key types (for now). If the key type is unspecified,sshkey_parse_private2()
will do all the checks you're expecting it to do, but if it fails and OpenSSL is enabled,sshkey_parse_private_pem_fileblob()
is called and will use OpenSSL'sPEM_read_bio_PrivateKey()
to parse the data and if that fails too, it assumes the wrong passphrase was given.ssh-add <()
, which repetitively asks for passphrase for empty file. It is at least weird. I got with my code inspection to thePEM_read_bio_PrivateKey()
, which was for me black box. As I browse through man page I see the only result from this function isNULL
, regardless the reason (parse error? or wrong passphrase, else?). This is probably the root cause of described behaviour. If I am right, there should be some way of getting the reason of failure through the api and decide regarding to that.https://github.com/openssl/openssl/blob/master/crypto/pem/pem_lib.c
, wherePEM_read_bio()
reads the file data and makes the necessary checks, for example it registers a failure reasonPEM_R_NO_START_LINE
when the first read returns no bytes. Is it possible to read this error inopenssh::sshkey.c
? Not sure. - Anyway, the current behaviour is explained. Is the question now if the implementation can change to return a failure reason, thus becoming a bit more user friendly?