| Bri Hatch | Personal | Work |
|---|---|---|
| bri@ifokr.org | Dropzone.AI |
https://www.ifokr.org/bri/presentations/seagl-2025-ssh-certificates/
Copyright 2025, Bri Hatch, Creative Commons BY-NC-SA License
Classic username/password authentication
laptop$ ssh wbagg@remote wbagg@remote's password: 🔒 (types password)

Generate local key pair:
laptop$ ssh-keygen -t ed25519 -C "wbagg@example.edu" Generating public/private ed25519 key pair. Enter passphrase (empty for no passphrase): 🔒 (types passphrase) Enter same passphrase again: 🔒 (types passphrase) Your identification has been saved in ~/.ssh/id_ed25519 Your public key has been saved in ~/.ssh/id_ed25519.pub ... laptop$ ls ~/.ssh/ id_ed25519 id_ed25519.pub
laptop$ ssh-copy-id -i ~/.ssh/id_ed25519.pub remote wbagg@remote's password: 🔒 (types password) laptop$ ssh wbagg@remote # Look ma, no password prompt! remote$ cat ~/.ssh/authorized_keys ssh-ed25519 Tm8gc2VjcmV0IG1lc3NhZ2UgaGVyZSEhISEhISEK wbagg@example.edu
ssh-agentssh sessions, ala ssh -A ...authprogs)no-pty, no-port-forwarding)from=)man sshdno-port-forwarding,no-user-rc ssh-ed25519 Tm8gc2Vjcm... wbagg@example.edu
authorized_keys file management
ssh-ed25519 Tm8gc2VjcmV0IG1lc3NhZ2UgaGVyZSEhISEhISEK wbagg@example.edu ssh-ed25519 TWF5YmV0aGlzaXNtYWxpY2lvdXM/Pz8/Pz8/
-o CertificateFile=filename if you have multiple~/.ssh/authorized_keys filesI can haz authority?
ca-server$ sudo ssh-keygen -t ed25519 \
-f /etc/ssh-ca/wtf-user-ca \
-C "Widgets Trade Factory CA"
...
Your identification has been saved in /etc/ssh-ca/wtf-user-ca
Your public key has been saved in /etc/ssh-ca/wtf-user-ca.pub
The key fingerprint is:
SHA256:e4kM7f/6ovfio4S6jM/APdnA5tBAQcO5M Widgets Trade Factory CAca-server$ ls -l /etc/ssh-ca; cat /etc/ssh-ca/wtf-user-ca.pub total 8 -rw------- 1 root root 419 Nov 5 23:44 wtf-user-ca -rw-r--r-- 1 root root 106 Nov 5 23:44 wtf-user-ca.pub ssh-ed25519 VGhpc2lzbid0Zm9vbGluZ2FueW9uZS4u Widgets Trade Factory CA
Allow cert-based authentication
/etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh-ca/wtf-user-ca.pub
$ sudo service sshd reload
The CA signs a user's pubkey
ca-server$ ls
wbagg-id_ed25519.pub
ca-server$ ssh-keygen -s /etc/ssh-ca/wtf-user-ca \
-I "keyid" \
-n wbagg \
-V +1m \
./wbagg-id_ed25519.pub
ca-server$ ls
wbagg-id_ed25519.pub
wbagg-id_ed25519-cert.pub
ca-server$ ssh-keygen -L -f wbagg-id_ed25519-cert.pub
wbagg-id_ed25519-cert.pub:
Type: ssh-ed25519-cert-v01@openssh.com user certificate
Public key: ED25519-CERT SHA256:oWK0HYhl+MAY5bFhGe28bG1cqasObgdfFBI3cb2BjW8
Signing CA: ED25519 SHA256:e4kM7f/6ovfio4S6jMniJfpkfwzy/APdnA5tBAQcO5M (using ssh-ed25519)
Key ID: "keyid"
Serial: 0
Valid: from 2025-04-19T11:43:00 to 2025-04-19T11:44:00
Principals:
wbagg
Critical Options: (none)
Extensions:
permit-X11-forwarding
permit-agent-forwarding
permit-port-forwarding
permit-pty
permit-user-rcWendell gets the cert back and puts it aside his normal key
laptop$ ls ~/.ssh/ ./id_ed25519 ./id_ed25519.pub ./id_ed25519-cert.pub laptop$ ssh wbagg@remote echo 'I am $(whoami) on $(hostname)' I am wbagg on remote laptop$ ssh alice@remote echo 'I am $(whoami) on $(hostname)' alice@remote's password: 🔒 laptop$ sleep +1m laptop$ ssh wbagg@remote echo 'I am $(whoami) on $(hostname)' wbagg@remote's password: 🔒
What the server said:
sshd[271828] Accepted publickey for wbagg from ::1 port 56992
ssh2: ED25519-CERT SHA256:... ID keyid (serial 0) CA
ED25519 SHA256:...
...
sshd[314159]: error: Certificate invalid: name is not a
listed principal
...
sshd[628318] error: Certificate invalid: expired
Certificate Restrictions
-n alice,bob) -V +1h to restrict it to a 1 hour TTLpty, agent/X11 forwarding, source IP CIDR, or force commands (-O options)
ca-server$ ssh-keygen -s /etc/ssh-ca/wtf-user-ca \
-I "keyid" \
-n wbagg \
-V +1m \
-O force-command=/usr/games/fortune
./wbagg-id_ed25519.pub
And then...
laptop$ ssh wbagg@remote Do what comes naturally. Seethe and fume and throw a tantrum. laptop$ ssh wbagg@remote echo Hello World You never know how many friends you have until you rent a house on the beach.
While you're here, consider disabling unneeded authentication methods
in /etc/ssh/sshd_config and restarting sshd
... PasswordAuthentication no AuthenticationMethods publickey

$ ssh server.example.edu The authenticity of host 'server.example.edu' can't be established. ED25519 key fingerprint is SHA256:HanveypyIgIHS08W0KgFX+7w3IdHZg. Are you sure you want to connect (yes/no)? yes
$ ssh server.example.edu The authenticity of host 'server.example.edu' can't be established. ED25519 key fingerprint is SHA256:HanveypyIgIHS08W0KgFX+7w3IdHZg. Are you sure you want to connect (yes/no)? yes

wtf-host-ca)ca-server$ ssh-keygen -s wtf-host-ca \ -I server.example.edu \ -n server.example.edu \ -h -V +52w ssh_host_rsa_key.pub
/etc/ssh/etc/ssh/sshd_config
HostCertificate /etc/ssh-ca/ssh_host_rsa_key-cert.pub
Add the host CA entry to your ~/.ssh/known_hosts
laptop$ grep cert-authority ~/.ssh/known_hosts @cert-authority *.example.edu ssh-rsa AAAABdnA5tBAQcO... wtf-host-ca
Never see this again!
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
There are tools you can use to streamline this

Presentation: https://www.ifokr.org/bri/presentations/seagl-2025-ssh-certificates/
| Personal | Work |
|---|---|
| Bri Hatch bri@ifokr.org |
Dropzone.AI www.dropzone.ai |
Copyright 2025, Bri Hatch, Creative Commons BY-NC-SA License