OpenSSH 8.2 is coming to the latest Long-Term Service release of Ubuntu, Focal Fossa (20.04), and has some breaking changes for users using an SSH Certificate Authority.

With OpenSSH 8.1 or older, the default certificate type when signing with ssh-keygen is ssh-rsa, although ECDSA- and SHA2-based algorithms have been supported since OpenSSH 5.7. As cited in the release notes,

It is now possible[1] to perform chosen-prefix attacks against the SHA-1 hash algorithm for less than USD$50K.

[1] SHA-1 is a Shambles: First Chosen-Prefix Collision on SHA-1 and Application to the PGP Web of Trust
Leurent, G and Peyrin, T (2020) https://eprint.iacr.org/2020/014.pdf

So the SHA-1 based RSA certificate algorithm is no longer considered secure. As a result,

  • ssh(1), sshd(8), ssh-keygen(1): this release removes the ssh-rsa (RSA/SHA1) algorithm from those accepted for certificate signatures (i.e. the client and server CASignatureAlgorithms option) and will use the rsa-sha2-512 signature algorithm by default when the ssh-keygen(1) CA signs new certificates.

The immediate effect is, when you attempt to log in to a host that presents an RSA/SHA1 certificate, instead of logging in successfully, SSH will complain with the following message:

check_host_cert: certificate signature algorithm ssh-rsa: signature algorithm not supported

and of course, you’re again asked to trust the host key even if you’ve already trusted the @cert-authority.

This can be particularly annoying in larger organizations where the deployment of RSA/SHA1 certificates has spanned everywhere, and OpenSSH 8.2 essentially just broke them all.

Rest assured, there’s a way to make everything go back to normal once more. But as suggested by OpenSSH, you should not rely on this and should instead move away from ssh-rsa certificates soon.

Bring back the compatibility

As described above, the value ssh-rsa has been dropped from the default list of the CASignatureAlgorithms, though as of April 8, the man page for ssh_config(5) contains a small mistake, which claims the default value of CASignatureAlgorithms is as follows:

CASignatureAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa

The actual value, of course, is the same as the above list with ssh-rsa stripped off, and all you need to do is to add it back.

If you just want to fix this for yourself, you can add the following lines to your ~/.ssh/config file:

Host *
  CASignatureAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa

If you want to fix this for all users on a system, you can add the same lines to /etc/ssh/ssh_config instead, which will affect all ssh commands run on that system. Remember this is still not recommended in favor of upgrating the signature algorithm.

Sign new certificates

Good news

You don’t have to generate a new CA and deploy it everywhere. You can still use your RSA private key to generate new certificates for your machines, though it does require a little research first.

Let’s start by looking at the man page for ssh-keygen(1).

ssh-keygen -s ca_key -I certificate_identity [-h] [-U] [-D pkcs11_provider] [-n principals] [-O option] [-V validity_interval] [-z serial_number] file ...

It doesn’t look like there’s a way to control the certificate algorithm. But hold on, have you tried the -t option that appears in many other subcommands…?

ssh-keygen -s ~/.ssh/ca -I Example -t rsa-sha2-256 id_rsa.pub
#                                  ^^^^^^^^^^^^^^^

This will generate a new certificate at id_rsa-cert.pub. You might want to examine it at once, and you might probably be disappointed to see that it still begins with [email protected].

That simply doesn’t matter. To examine a certificate, you should use the ssh-keygen -L command:

ssh-keygen -Lf id_rsa-cert.pub

… and check its output:

id_rsa-cert.pub:
        Type: [email protected] user certificate
        Public key: RSA-CERT SHA256:yP2N3uawwSuoJdww2miEYrsGuBictGYJ6VmkdhvtYcg
        Signing CA: RSA SHA256:yP2N3uawwSuoJdww2miEYrsGuBictGYJ6VmkdhvtYcg (using rsa-sha2-256)
        Key ID: "Example"
        Serial: 0
        Valid: forever
        Principals: (none)
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

Notice how the fourth line reads using rsa-sha2-256? It’s now signed with a different algorithm that’s not considered deprecated anymore, which means it’s ready to deploy.

Tip

OpenSSH 8.2 defaults to using the rsa-sha2-256 algorithm when signing new certificates with an RSA private key, so the -t option is only necessary if you’re using OpenSSH 8.1 or older.

You can try running ssh-keygen -L on one of your old certificates to see how SSH describes it. This is left as a small quiz for you to figure out for yourself.

Leave a comment