Does the ssh-agent protocol allow adding a certificate for a private key which it already has? The idea is to issue a certificate for a key the agent already has, to avoid the entropy drain of generating a new key. https://tools.ietf.org/html/draft-miller-ssh-agent-04 shows private keys, and doesn't mention certificates at all.? However it does say: "Typically only the public components of any keys supported on a hardware token will be loaded into an agent" - which suggests that the SSH_AGENTC_ADD_IDENTITY message might be able to carry only the public parts of a key. https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys defines new *public* key formats for certificates - they don't contain the private key components as far as I can see. However, looking at the Go ssh-agent client, it inserts a private key and certificate in a single SSH_AGENTC_ADD_IDENTITY or SSH_AGENTC_ADD_ID_CONSTRAINED message: https://github.com/golang/crypto/blob/master/ssh/agent/client.go#L664 (and I haven't been able to find documentation which defines that private key + certificate message format). So basically: can I send just a certificate to ssh-agent?? And if so, how is that done? Thanks, Brian.
On 2/7/21 1:09 PM, Brian Candler wrote:> Does the ssh-agent protocol allow adding a certificate for a private key > which it already has? The idea is to issue a certificate for a key the > agent already has, to avoid the entropy drain of generating a new key. > > https://tools.ietf.org/html/draft-miller-ssh-agent-04 shows private > keys, and doesn't mention certificates at all.? However it does say: > > "Typically only the public components of any keys supported on a > hardware token will be loaded into an agent" - which suggests that the > SSH_AGENTC_ADD_IDENTITY message might be able to carry only the public > parts of a key. > > https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys defines > new *public* key formats for certificates - they don't contain the > private key components as far as I can see. > > However, looking at the Go ssh-agent client, it inserts a private key > and certificate in a single SSH_AGENTC_ADD_IDENTITY or > SSH_AGENTC_ADD_ID_CONSTRAINED message: > > https://github.com/golang/crypto/blob/master/ssh/agent/client.go#L664 > > (and I haven't been able to find documentation which defines that > private key + certificate message format). > > So basically: can I send just a certificate to ssh-agent?? And if so, > how is that done?Hi, this was discussed in the following two bugs in context of pkcs11 keys, but without any definite solution. https://bugzilla.mindrot.org/show_bug.cgi?id=2472 https://bugzilla.mindrot.org/show_bug.cgi?id=2808 To support this, we would need and update of ssh-agent protocol (or extension) and some variant of a patch in the first bug above. Regards, -- Jakub Jelen Senior Software Engineer Crypto Team, Security Engineering Red Hat, Inc.
On Sun, 7 Feb 2021, Brian Candler wrote:> Does the ssh-agent protocol allow adding a certificate for a private key > which it already has? The idea is to issue a certificate for a key the > agent already has, to avoid the entropy drain of generating a new key. > > https://tools.ietf.org/html/draft-miller-ssh-agent-04 shows private > keys, and doesn't mention certificates at all.? However it does say: > > "Typically only the public components of any keys supported on a > hardware token will be loaded into an agent" - which suggests that the > SSH_AGENTC_ADD_IDENTITY message might be able to carry only the public > parts of a key. > > https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys > defines new *public* key formats for certificates - they don't contain > the private key components as far as I can see. > > However, looking at the Go ssh-agent client, it inserts a private key > and certificate in a single SSH_AGENTC_ADD_IDENTITY or > SSH_AGENTC_ADD_ID_CONSTRAINED message: > > https://github.com/golang/crypto/blob/master/ssh/agent/client.go#L664 > > (and I haven't been able to find documentation which defines that > private key + certificate message format). > > So basically: can I send just a certificate to ssh-agent?? And if so, > how is that done?Yes, it is possible but poorly documented (patches welcome as always). The format for encoding a certificate with private key is is roughly {cert, private fields}. See sshkey.c:sshkey_private_serialize_opt() for the actual code, but it's basically the following, where "certificate blob" is the entire public certificate key. RSA string "ssh-rsa-cert-v01 at openssh.com" string certificate blob mpint rsa_n mpint rsa_e mpint rsa_d mpint rsa_iqmp mpint rsa_p mpint rsa_q DSA string "ssh-dsa-cert-v01 at openssh.com" string certificate blob mpint dsa_priv ECDSA string "ecdsa-sha2-nistp256-cert-v01 at openssh.com" / "ecdsa-sha2-nistp384-cert-v01 at openssh.com" / "ecdsa-sha2-nistp521-cert-v01 at openssh.com" string certificate blob mpint ecdsa_priv ED25519 string "ssh-ed25519-cert-v01 at openssh.com" string certificate blob string ed25519_pubkey string ed25519_privkey ECDSA/FIDO string "sk-ecdsa-sha2-nistp256-cert-v01 at openssh.com" string certificate blob string sk_application uint8 sk_flags string sk_key_handle string sk_reserved ED25519/FIDO string "sk-ssh-ed25519-cert-v01 at openssh.com" string certificate blob string ed25519_pubkey string sk_application uint8 sk_flags string sk_key_handle string sk_reserved Note in ED25519 and FIDO key types there are some redundant fields between the cert blob and the subsequent fields.