Re-signing Openssh Certificates

Seldom do I get to write a post where I am offering information which might not actually be out there in a lot of places. I could not find this information on the web, and had to figure it out myself, by reading the code, and doing experiments.

I talked in the last post about the need to re-issue all the openssh certificates, in order to update the hash algorithm used for the signatures. My way of maintaining the certificates, in my repository, would make it easy for the signing box to get all the existing certificates, but not (directly) the public keys that are inside those certificates.

If I could extract the public keys, then I wouldn’t have to go visit every single box, gather its keys, send them to the signer, etc. I could just have a piece of code go through all the certificates, extract the public keys, sign them again, and put them back into the repository. True I will still have to visit every box, but I’ll only have to do an svn update and move the certs.

But how to extract public keys from an existing ssh certificate. Easy to do for X509 certificates with openssl, but I cannot find any option in ssh or ssh-keygen to do it.

However, what one can do is export a public key from openssh format in a couple of other formats, like pem, or RFC4716 (for use by the commercial ssh2 product, or as PKCS8. Reading the code in openssh I came across a comment suggesting that (at least in some places) one can use an openssh certificate on the command line in ssh-keygen in place of an openssh public key. I wondered if this would work. I tried it, and it does.

So, I can export the public key from an openssh certificate with:

ssh-keygen -e -m pkcs8 -f id_rsa-cert.pub \
   > id_rsa.pkcs8

And then import it back into openssh public key format with:

ssh-keygen -i -m pkcs8 -f id_rsa.pkcs8 \
   > id_rsa.pub

I chose pkcs8 instead of pem because I’m wanting to do this with the ssh_host_*_key-cert.pub files as well, and I discovered that I cannot export an ecdsa host key to pem format, but I can export it to pkcs8 and then reimport it.

Now, armed with the public key, I can sign it again, generating a new certificate (after first saving the old cert for safety’s sake):

ssh-keygen -s <ca-key> -t rsa-sha2-512 \ 
   -P<pw> -I<id> -n <principals> id_rsa.pub

This regenerates the certificate, but now the signature algorithm uses the rsa-sha2-512 hashing algorithm, which is “acceptable”.