SSH Certificate Authorities (CAs)

As described on our blog, SSH CAs are a way of building SSH authentication on top of a signing SSH keys. This document expands on how SSH CAs work, the different modes of operation, possible improvements, and other interesting things that can be done with CAs.

How an SSH CA Works

An SSH CA key is just a normal SSH key. This bot generates keys via:

ssh-keygen -t ed25519 -f ca-key -m PEM

A signature on a SSH key is a certificate that contains some additional information. A certificate contains:

  1. The public key of the signed key
  2. A key ID that can be used to identify who the key was issued to
  3. A serial number that can be used manage revocation lists
  4. A validity period where the key is considered valid only within that period of time
  5. A list of principals

A list of principals on a certificate is simply strings that are shared for access control. The field is often used to encode roles a user has or groups that they are in, anything that helps the server decide whether or not to allow access (and how much access to grant). We use this field to include a list of keybase teams that the user is in. And the servers are configured to expect the same values (more below). As an example, here is the information encoded in a certificate created by this bot:

$ ssh-keygen -L -f  ~/.ssh/ 
        Type: user certificate
        Public key: ED25519-CERT SHA256:wdzTWhCrVeJrxRIC1KU5nJr8FbxxCUJt1IVeG7HYjmc
        Signing CA: ED25519 SHA256:OEhTm77qM7ZDwb5oltxt78FIpKraXCzxoaboi/KpNbM
        Key ID: "08a093ec-cb4e-4bc2-9800-825095418397:981b88e2-a214-4075-af77-72da9600f34f"
        Serial: 0
        Valid: from 2019-07-31T11:21:00 to 2019-07-31T12:22:50
        Critical Options: (none)

This certificate which was created by the CA bot is the bot’s cryptographic assertion that I am in the specified teams. If I then attempt to SSH into a server with this certificate, it is the responsibility of the server to decide whether or not to allow the connection. This is done via adding two lines to /etc/ssh/sshd_config:

TrustedUserCAKeys /etc/ssh/
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u

The first line specifies that /etc/ssh/ contains the CA public key (as generated by ssh-keygen above). The second line is how we define a mapping between the principals (for this bot: the Keybase teamnames) and the SSH users they are granted access to. For example, if we wanted this server to allow people with the principal sshcademo.root_everywhere to use the root user and people with the principal sshcademo.staging to use the “developer” user, we would create two files. First, /etc/ssh/auth_principals/root with contents sshcademo.root_everywhere and second /etc/ssh/auth_principals/keybase with contents sshcademo.staging.

When the SSH server accepts the connection, it will log the key ID and the serial number which can be combined with the CA bot’s audit logs in order to track a connection to a specific keybase user.

Accepted publickey for developer from port 56914 ssh2: ED25519-CERT ID e662bf1e-0855-41e9-8951-87bf8c0b3614:f650a363-cd34-4ab0-b6bf-52faa120364d (serial 0) CA ED25519 SHA256:OEhTm77qM7ZDwb5oltxt78FIpKraXCzxoaboi/KpNbM

For more information on SSH CAs, here are a few more useful sources:


Future Improvements

Below are a few ideas for future improvements to this project. PRs welcome!

Key Encryption

Currently the CA key is stored on the filesystem unencrypted by the CA bot. As long as the CA bot is run on a well isolated machine, this is not seen as a significant security weakness. Nonetheless, this could be improved upon by adding options that allow for encrypting the CA key.


With an SSH CA it is possible to revoke signed SSH keys via revocation lists. A revocation list is a file on the server that contains a list of revoked keys. It is likely impractical to manually manage a revocation list, so this could be done via a cron job that periodically updates the revocation list. One of the main difficulties of designing this feature as part of the SSH CA bot is that a design goal of this bot was to not require running Keybase on every server. Thus, this revocation list would need to be somehow updated independent of Keybase.

Host Key Signing

SSH CAs can be used to sign SSH host keys. This would remove the below message and strengthen SSH by switching it away from a TOFU model.

$ ssh
The authenticity of host ' (2604:a880:400:d0::38c4:2001)' can't be established.
ECDSA key fingerprint is SHA256:MmB6/g0vDrMkanuRc46n6JCDYPaPKHYsbDpLhQ3y1Yg.
Are you sure you want to continue connecting (yes/no)? 

This feature has not been included because signing host keys is significantly different from signing user keys. Despite this, it could still be a useful feature to build on top of Keybase.