Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support loading SSH keys serialized with 'rsa-sha2-{256,512}' as their key type string #11233

Conversation

dlenskiSB
Copy link
Contributor

@dlenskiSB dlenskiSB commented Jul 9, 2024

As described in RFC 8332 [1] ("Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol"):

Since RSA keys are not dependent on the choice of hash function, the
new public key algorithms reuse the "ssh-rsa" public key format as
defined in [RFC4253]:

All aspects of the "ssh-rsa" format are kept, including the encoded
string "ssh-rsa". This allows existing RSA keys to be used with the
new public key algorithms, without requiring re-encoding or affecting
already trusted key fingerprints.

Some real-world SSH servers nevertheless represent their RSA public keys using the string rsa-sha2-256 or rsa-sha2-512 instead of ssh-rsa, so the library should support LOADING them for robustness.

[1] https://datatracker.ietf.org/doc/html/rfc8332#section-3

@dlenskiSB dlenskiSB changed the title Support loading SSH keys serialized with 'rsa-sha2-{256,512}' as thei… Support loading SSH keys serialized with 'rsa-sha2-{256,512}' as their key type string Jul 9, 2024
@dlenskiSB dlenskiSB force-pushed the Support_OpenSSH_RSA_keys_serialized_with_non-standard_key_type branch from 124b1cb to 1e123c3 Compare July 9, 2024 17:34
@reaperhulk
Copy link
Member

I'm fine with supporting this, but I'd love to know some examples of software that generated keys with this prefix. 😄

@alex
Copy link
Member

alex commented Jul 9, 2024 via email

@dlenskiSB
Copy link
Contributor Author

dlenskiSB commented Jul 9, 2024

@reaperhulk wrote:

I'd love to know some examples of software that generated keys with this prefix.

I wish I could tell you, but I'm uncertain myself 😅.

Here is an Internet-facing server observed by Shodan which:

  1. Has a strange banner: SSH-2.0-f5C4Zrzn (there are literally 0 google hits for this string, it doesn't match any well-known SSH server software 🤷🏻‍♂️)

  2. Yields the following raw hostkey bytes if you point a suitably enlightened ssh-keyscanner at it:

    $ python3 ssh-audit.py -d x.y.z.w:22
    …
    Hostkey type: [rsa-sha2-512]; hostkey size: 2048; CA type: []; CA modulus size: 0
    Raw hostkey bytes (284): [0000000c7273612d736861322d353132000000030100010000010100de5a…bded]
    …
    

Quite likely keys like this get overlooked because OpenSSH itself doesn't probe them and doesn't find them. OpenSSH's own ssh-keyscan utility only uses the ssh-rsa key type when probing a server for its keys:

$ ssh -V
OpenSSH_9.0p1, LibreSSL 3.3.6
$ ssh-keyscan x.y.z.w
x.y.z.w ssh-rsa $BASE64_BLOB
$ echo $BASE64_BLOB | base64 -d | hd
15:30 $ echo AAAAB3NzaC1yc2EAAAADAQABAAABAQDeWpKkbxdKeRqMWp7Asg/ZcWw9fUvhTAF6dSaR0x0btLoxdUDPeUr+EXRS69/pTx0xfQM/JysI9m1L6GQVC7kjlBJZCKbxrdi0tTs8SqGDrgDHAiFTKVzEvex54wcmiThBsWmFPaOMq9YP0heViNslb59myzaVbU80j3PFs1oKHt4Og9Ltef+wohufKPPdNI000pafmE/K/W5wcLFK6c2VjeYESlB/jqMjJQBmubtiSM6wk8xJeEinnJcVqZx2zQkkhx+DV+ygZMA68rkCHcCqvKZQO4rS24/sCtaKCihxTzNIG4h5n59DX+uCPT3eeEvmZYDIObdM0MfBrsIDgb3t|base64 -d|hd
00000000  00 00 00 07 73 73 68 2d  72 73 61 00 00 00 03 01  |....ssh-rsa.....|
00000010  00 01 00 00 01 01 00 de  5a 92 a4 6f 17 4a 79 1a  |........Z..o.Jy.|
…
00000110  c1 ae c2 03 81 bd ed                              |.......|
00000117

Basically, if you ask this weird server "what is your ssh-rsa key?" or "what is your rsa-sha2-512 key?" it will give you the same RSA public key (same e, n), but with a different prefix prepended. Contrast this with "normal" OpenSSH servers will give you ssh-rsa keys in both cases:

$ python3 ssh-audit.py -d $NORMAL_OPENSSH_SERVER
…
Hostkey type: [rsa-sha2-256]; hostkey size: 3072; CA type: []; CA modulus size: 0
Raw hostkey bytes (407): [000000077373682d727361000000030100010000018100…384 bytes of RSA modulus…]
…

@dlenskiSB
Copy link
Contributor Author

dlenskiSB commented Jul 9, 2024

tl;dr:

  • RFC8332-compliant SSH servers will give you the exact same key bytes if you ask them to do an ssh-rsa key exchange, or an rsa-sha2-{256,512} key exchange, including the same key-type prefix (b"\0\0\0\x07ssh-rsa") in the host-key bytes.
  • There are weird/bad/non-compliant servers which will give you a different prefix depending on which one you ask for.
  • Given the historical baggage and inconsistency wherein different uses have been shoehorned into the same field (public key type vs. key exchange algorithm) this kind of inconsistent behavior seems inevitable.
  • pyca/cryptography should be able to load the weird/non-compliant forms of the key, for maximum robustness 😃

@alex
Copy link
Member

alex commented Jul 9, 2024 via email

@dlenskiSB
Copy link
Contributor Author

dlenskiSB commented Jul 9, 2024

@alex wrote:

What do other libraries, such as go's x/crypto/ssh do?

I personally have zero knowledge about the Go ecosystem, but a quick grep in the codebase shows they have a near-identical (hmmm 🤨) comment about how rsa-sha2-{256,512} are only "key algorithms" and not "key formats":
https://github.com/golang/crypto/blob/d66d9c31b4ae80d173d1187a9e40c188788dbdbc/ssh/keys.go#L48-L52

@dlenskiSB dlenskiSB force-pushed the Support_OpenSSH_RSA_keys_serialized_with_non-standard_key_type branch from 1e123c3 to 5063488 Compare July 16, 2024 05:37
@dlenskiSB
Copy link
Contributor Author

I don't understand the flake8 failure in CI. There appears to be something missing from the log.

@reaperhulk
Copy link
Member

Just run ruff locally and it will automatically reformat.

@reaperhulk
Copy link
Member

nox -e local will do this along with running tests btw

…r key type string

As described in RFC 8332 [1] ("Use of RSA Keys with SHA-256 and SHA-512
in the Secure Shell (SSH) Protocol"):

> Since RSA keys are not dependent on the choice of hash function, the
> new public key algorithms reuse the "ssh-rsa" public key format as
> defined in [RFC4253]:
>
> …
>
> All aspects of the "ssh-rsa" format are kept, including the encoded
> string "ssh-rsa".  This allows existing RSA keys to be used with the
> new public key algorithms, without requiring re-encoding or affecting
> already trusted key fingerprints.

Some real-world SSH servers nevertheless represent their RSA public keys
using the string `rsa-sha2-256` or `rsa-sha2-512` instead of `ssh-rsa`, so
the library should support LOADING them for robustness.

[1] https://datatracker.ietf.org/doc/html/rfc8332#section-3
@dlenskiSB dlenskiSB force-pushed the Support_OpenSSH_RSA_keys_serialized_with_non-standard_key_type branch from 5063488 to 395d82a Compare July 16, 2024 15:31
@reaperhulk
Copy link
Member

It is not generally our approach to be maximally accepting of non-compliant data. Absent a concrete need to support incorrect things we err on the side of standards correctness and/or minimal surface area. I'm -1 on adding support for this until/unless we find a significant real world deployment doing this wrong, although I appreciate you doing the diligence to find out the current state of the world! @alex any objections?

@alex
Copy link
Member

alex commented Jul 18, 2024 via email

@reaperhulk reaperhulk closed this Jul 20, 2024
@dlenskiSB
Copy link
Contributor Author

although I appreciate you doing the diligence to find out the current state of the world!

Thanks, I do understand this point of view and the drive for adherence to standards and sanity.

However, I also think that widely-used cryptographic libraries like this one ought to adhere to the robustness principle ("be liberal in what you accept as input, be conservative in what you output") in order to maximize adoption.

If widely-used and carefully-implemented libraries don't support loading and using cryptographic objects in slightly-malformed but unambiguous formats, then those who encounter such formats are likely going to turn to "roll-your-own cryptography" as an alternative… and that has a long history of bad consequences. 😅

@alex
Copy link
Member

alex commented Jul 22, 2024

The robustness principle has been repudiated by many of us who work in security, see https://datatracker.ietf.org/doc/html/rfc9413

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants