Subject: Re: rsa-sha2-256/512: handling of incorrect signature encoding

From: Ron Frederick <[email-masked]>
Date: Sun, 11 Sep 2016 19:39:07 -0700

Denis Bider (Bitvise) wrote:
> If you are sending an rsa-sha2-XXX signature, you cannot set all 3 fields in the authentication request to "ssh-rsa", because then this makes for a SHA-1 signature as it was done traditionally, not a SHA-2 signature. To send a SHA-2 signature, at least one field has to contain "rsa-sha2-XXX".
>  
> The draft specifically says the signature format names are "rsa-sha2-XXX", but the public key format name stays "ssh-rsa", which it must stay in order to preserve existing RSA key fingerprints.
>  
> The signature format is defined thus:
>  
>   string    "rsa-sha2-256" / "rsa-sha2-512"
>   string    rsa_signature_blob
>  
> These specifications seem to me very clear and unambiguous. In a user authentication request, when sending a SHA-2 signature, the only correct encoding of algorithm names is as follows:
>  
> byte      SSH_MSG_USERAUTH_REQUEST
> string    user name
> string    service name
> string    "publickey"
> boolean   TRUE
> string    "rsa-sha2-256" / "rsa-sha2-512"
> string    public key blob:
>   string    "ssh-rsa"
>   mpint     e
>   mpint     n
> string    signature:
>   string    "rsa-sha2-256" / "rsa-sha2-512"
>   string    rsa_signature_blob
> If your implementation does not encode the algorithm names this way, it is incorrect. The latest OpenSSH versions encode the algorithm names this way, though a previous version used "ssh-rsa" in the third field by mistake.
>  
> Bitvise SSH Client encodes the fields this way also, and the current version of Bitvise SSH Server expects the algorithm names this way, and only this way.

I did an implementation of this recently for AsyncSSH, and I have matched the above in the case where regular keys are used, with the first and third identifiers being rsa-sha2-256/rsa-sha2-512 and the second identifier remaining ssh-rsa when the new-style signatures are used. However, I also wanted to verify the correct identifiers to use in the certificate case.

Right now, I’m using [email-masked] <mailto:[email-masked]> as both the first and second identifier in the certificate case, and only using rsa-sha2-256/rsa-sha2-512 for the third identifier associated with the signature. This seems to work when talking to an OpenSSH server, and in fact OpenSSH doesn’t seem to accept the certificate if the first identifier does not identify that a certificate is being used, even if the second identifier indicates that a certificate was provided as the public key blob.

I know that certificates are OpenSSH-specific, so my apologies in advance if this is the wrong list to ask this question on. I just happened to see this thread in the mailing list archive, and though it would be good to get confirmation from the group.
-- 
Ron Frederick
[email-masked]

---

From: "denis bider \(Bitvise\)" <[email-masked]>
Date: Mon, 12 Sep 2016 13:14:20 -0600

Hello Ron,

I’m not familiar with the OpenSSH certificate implementation, but there is an RFC specifying the use of X.509 certificates in SSH that defines its own key type for RSA with SHA-2 based signatures:

https://tools.ietf.org/html/rfc6187

I don’t know what your users require, but from our users we are seeing requests to implement X.509 as per this RFC, not the @openssh versions.

denis

From: Ron Frederick 
Sent: Sunday, September 11, 2016 20:39
To: [email-masked] 
Subject: Re: rsa-sha2-256/512: handling of incorrect signature encoding

Right now, I’m using [email-masked] as both the first and second identifier in the certificate case, and only using rsa-sha2-256/rsa-sha2-512 for the third identifier associated with the signature. This seems to work when talking to an OpenSSH server, and in fact OpenSSH doesn’t seem to accept the certificate if the first identifier does not identify that a certificate is being used, even if the second identifier indicates that a certificate was provided as the public key blob.

---

From: Ron Frederick <[email-masked]>
Date: Mon, 12 Sep 2016 20:34:00 -0700

On Sep 12, 2016, at 12:14 PM, denis bider (Bitvise) <[email-masked]> wrote:
> https://tools.ietf.org/html/rfc6187 <https://tools.ietf.org/html/rfc6187>
>  

[Ron] Thanks, Denis. I have looked at that RFC, and have thought about adding support for both those and the OpenSSH variants. For deployments where this is already a good X.509-based public key infrastructure in place, I can definitely see the value in being able to use a common set of certificate authorities for both SSL/TLS and SSH.

That said, there are some challenges with supporting RFC 6187:

- Parsing X.509 certificates is extremely complex, and validating a certificate chain is even more so. If you want to do it right, you need to bring in a bunch of additional crypto infrastructure, like support for CRLs and OCSP.

- The RFC provides a recommendation for how to validate server names when certificates are used for host authentication, but for user authentication it simply says "the mapping between certificates and user names is left as an implementation and configuration issue for implementers and system administrators.” It also really doesn’t provide any guidance about how to specify the list of trusted root CAs for either user or host authentication.

- While the RFC does provide a way to indicate if an X.509 certificate can be used for user or host authentication, it doesn’t currently define any way to put restrictions on when a user can use a particular certificate or what they can do when they authenticate with a particular certificate. This would not be difficult to do in X.509, but I haven’t seen a proposed spec for encoding any such restrictions.

OpenSSH certificates addresses these points pretty well:

- All parsing is done using the same mechanism used for parsing other SSH packets, just like OpenSSH-format keys. There’s no need to pull in an ASN.1 parser or deal with the large number of OID values that need to be understood to properly parse X.509 certificates.

- Specifying the list of trusted CAs and revoked certificates is done as a natural extension of the existing authorized_keys and known_hosts file formats.

- OpenSSH provides very rich ways of limiting when certificates can be used and what actions can be taken by a user presenting a certificate. This can be done in either the authorized_keys file on the host deciding whether to accept a certificate or in the certificate itself, such that the limitations automatically apply to all hosts the certificate is accepted on.

There are some ways in which OpenSSH is behind, though:

- There’s no support for certificate chaining. It only supports direct signing of keys by a root CA, with no intermediate CAs. For many organizations, I imagine this would be a show-stopper.

- While it can support the equivalent of CRLs for revocation, there’s currently nothing in OpenSSH equivalent to OCSP for real-time revocation checking.

If you’re interested, more info on OpenSSH certificates can be found at http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/ssh/PROTOCOL.certkeys?rev=1.10&content-type=text/plain <http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/ssh/PROTOCOL.certkeys?rev=1.10&content-type=text/plain>.
-- 
Ron Frederick
[email-masked]