Repository navigation
x/crypto/ssh: add support for hostkeys@openssh.com #37245
Description
Activity
- addedNeedsFixThe path to resolution is known, but the work has not been done.The path to resolution is known, but the work has not been done.FeatureRequestIssues asking for a new feature that does not need a proposal.Issues asking for a new feature that does not need a proposal.
on Feb 16, 2020 I'm interested in taking this on, as it would be helpful for our implementations. I've reviewed the extension details in the openssh PROTOCOL file and it's relatively light on specifics, but seems to be enough to implement it.
One question I have on the
x/crypto/sshside of things: You mention implementation on server-side, but if memory serves all the tests in that package use the client to test the server. Since there won't be a client-side implementation (maybe a config callback could be added that would be called when changes are found?), how would you expect the server side to be tested? Just sending raw messages from a client to the server and checking the expected responses?Hi @aphistic,
I'm a little short on time right now but this is also on my TODO.
I think we should also add a client implementation consisting of callbacks to implement in the application using crypto/ssh.Reacted by Kristin DavidsonHey @drakkan!
Is this something where you'd want to collaborate on it, or I should put it off? Do you have any thoughts on the implementation of it that I should implement?
We currently have a fork of
x/cryptowe're maintaining with support for RFC8332 and RFC8308 (server-sig-algs), but also has a couple of modifications made to allow us to introspect things about the connection (host key alg or kex alg chosen for a connection) and allowed us to implement the host key extension in our service directly.Since the recent release of
x/cryptonow implements the features we originally created the fork for, we're looking to get back to using the upstream version. In order to use that, though, we'd need to have the host keys extension implemented. That's where the desire to work on this comes from.Hi @aphistic,
yes I would like to collobarate but I'm currently busy with other things, if this is urgent for you feel free to start. I haven't had time to think about the implementation details yet. I just added this issue to my TODO and I marked it as low priority
Is your crypto fork public? I think it would be a good starting point.
I recently became a crypto/ssh maintainer and I'm trying to help implement the common features we all need 😄
I'm currently working on these issues
Hello, I would like to contribute and help here if possible, I am also interested in this feature. @aphistic can you share the host key implementation that you have?
Hello,
I propose the following API changes:
// HostKeysProve sends a hostkeys-prove@openssh.com message to request the // server prove ownership of the private half of the key and validates the // received signatures. func (c *Client) HostKeysProve(publicKeys []PublicKey) error // HostKeys00Callback is the function type used to receive the host keys sent by // servers using the hostkeys-00@openssh.com global message. type HostKeys00Callback func(publicKeys []PublicKey) type ClientConfig struct { .... // HostKeys00Callback is called after the authentication if the server sends // a hostkeys-00@openssh.com message. The client configuraton can supply // this callback to get notified about the received public keys. HostKeys00Callback HostKeys00CallbackNo server-side API changes are needed because the
hostkeys-00@openssh.comrequest can always be sent after user-authentication has completed. We only need to allow to accept multiple host keys with the same key format inAddHostKey.We can also add something like
FixedHostKeysto simplify verification for multiple host keys but I think this should be a separate commitChange https://go.dev/cl/559055 mentions this issue:
ssh: add support for hostkeys@openssh.comHelp with testing the above CL and thoughts on it are greatly appreciated. Thank you!
CL updated with new API
// HostKeyUpdate represents a public key sent from servers using the // hostkeys-00@openssh.com global message. type HostKeyUpdate struct { key PublicKey } // Fingerprint returns the key's fingerprint as unpadded base64 encoded sha256 // hash. func (h *HostKeyUpdate) Fingerprint() string { return FingerprintSHA256(h.key) } // KeyType returns the key type. func (h *HostKeyUpdate) KeyType() string { return h.key.Type() } // Equal reports whether the public part of the host key matches the one // supplied. func (h *HostKeyUpdate) Equal(key PublicKey) bool { return bytes.Equal(h.key.Marshal(), key.Marshal()) } // PublicKey sends a hostkeys-prove@openssh.com message to request the server // prove ownership of the private half of the key and returns the public key if // the verification is successful. func (h *HostKeyUpdate) PublicKey(client *Client) (PublicKey, error) { if err := client.hostKeysProve([]PublicKey{h.key}); err != nil { return nil, err } return h.key, nil } // HostKeysUpdateCallback is the function type used to receive the host keys // sent by servers using the hostkeys-00@openssh.com global message. type HostKeysUpdateCallback func(keysUpdate []HostKeyUpdate) type ClientConfig struct { .... // HostKeysUpdateCallback is called after the authentication if the server // sends a hostkeys-00@openssh.com message. The client configuration can // supply this callback to get notified about the received public keys. HostKeysUpdateCallback HostKeysUpdateCallback ....The purpose of these changes is to allow clients to get public keys only after servers prove ownership.
Clients can useFingerprint,KeyTypeandEqualmethods to check if they already know the public key.Also updated the check in
AddHostKeyto avoid adding the same host key multiple times. I think this was the purpose of the previous code. If we add the same host key multiple times OpenSSH returns an error like thisclient_input_hostkeys: received duplicated ssh-rsa host keytype HostKeysUpdateCallback func(keysUpdate []HostKeyUpdate)we should make this
type HostKeysUpdateCallback func([]*HostKeyUpdate)Also,
(*HostKeyUpdate).PublicKeyshouldn't take a Client, which instead should be saved inHostKeyUpdate.8 remaining items
This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review groupAny comments on the API in #37245 (comment)?
I assume the empty struct is not really empty but has unexported fields.
@rsc, I confirm that the struct has unexported fields used to immplement the public methods
Here are the struct fields in the proposed CL
type HostKeyUpdate struct { key PublicKey mux *mux sessionID []byte }keyis used to implementFingerprint,KeyTypeandEqualmethods.muxandsessionIDare used to send thehostkeys-prove@openssh.comto the server to verify the public key before returning it.The public key is not exposed directly to prevent users from trusting it without sending the
hostkeys-prove@openssh.comrequest.Based on the discussion above, this proposal seems like a likely accept.
— rsc for the proposal review groupThe proposal details are in #37245 (comment).
No change in consensus, so accepted. 🎉
This issue now tracks the work of implementing the proposal.
— rsc for the proposal review groupThe proposal details are in #37245 (comment).
- changed the title
[-]proposal: x/crypto/ssh: add support for hostkeys@openssh.com[/-][+]x/crypto/ssh: add support for hostkeys@openssh.com[/+]on Apr 4, 2024
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsAccepted
The
hostkeys@openssh.comextension lets a server notify a client of all its host keys to enable a smooth transition if they have UpdateHostKeys enabled. We should offer it server-side.