Revoke SSH Keys and Certificates with OpenSSH KRL

Tested on RHEL 10.2 as SSH server (192.168.56.116); Ubuntu 26.04 as CA/admin workstation and SSH client (192.168.56.121)
Package openssh-server-9.9p1-25.el10_2.x86_64 / OpenSSH_10.2p1 Ubuntu
Applies to Modern OpenSSH on RHEL, Rocky, AlmaLinux, Fedora, Ubuntu, and Debian (ssh-keygen -k / -u / -Q, RevokedKeys)
Privilege sudo or root on the SSH server for the KRL file, sshd_config, and reload; normal user for CA signing and client login tests
Scope OpenSSH-native Key Revocation Lists for plain public keys and user certificates (create, update, query, serial/range/Key ID/fingerprint revocation, RevokedKeys). Does not cover Vault, Smallstep, Teleport, or X.509 CRL/OCSP.
Related guides SSH key authentication
Generate SSH keys
OpenSSH authentication methods
Restrict SSH users and groups
Short on time?Beta Get the gist of this 20-minute read in seconds, then ask follow-up questions

In this article we will revoke SSH access with an OpenSSH Key Revocation List (KRL) so sshd refuses a stolen key or a bad certificate everywhere you deploy that file. You do not need to wait for certificate expiry, and you do not need to hunt every authorized_keys copy in environments that use SSH certificates across many servers.

I ran the full path on RHEL 10.2 as the SSH server and Ubuntu 26.04 as the CA and client: issue a user certificate with a non-zero serial, create a KRL, confirm revocation with ssh-keygen -Q, point RevokedKeys at the file, watch login fail, then update the same KRL with -u and revoke by serial, serial range, Key ID, fingerprint, and plain public key.


What is an OpenSSH Key Revocation List (KRL)?

You may need to cut SSH access when:

  • a private key is stolen
  • an employee or administrator leaves
  • a certificate was issued with the wrong principals
  • a certificate must stop before its expiration time
  • an SSH CA key is compromised
  • a batch of certificates must be invalidated at once

With plain authorized_keys, you usually remove the user's public key from every server that trusts it. That works for one host. It gets painful when the same key is copied across a fleet.

With OpenSSH certificate authentication, short-lived certificates often expire soon enough that you can wait. When access must stop immediately, waiting is not enough.

OpenSSH's answer is a Key Revocation List (KRL): a compact binary file that tells OpenSSH which keys or certificates must no longer be trusted. You build it with ssh-keygen -k, merge more entries with -u, test with -Q, and make sshd enforce it through RevokedKeys.

IMPORTANT
A KRL does not delete the key or certificate from disk. It makes OpenSSH reject that credential when RevokedKeys points at the KRL. Revocation is only enforced on systems that receive the updated KRL and are configured to use it; creating the file on the CA host does not revoke access globally by itself.

What can an OpenSSH KRL revoke?

Credential / identifier Can a KRL revoke it?
Plain SSH public key Yes
User certificate Yes
Host certificate Yes
Certificate serial number Yes
Range of certificate serials Yes
Certificate Key ID Yes
SHA256 public-key fingerprint Yes
Entire CA / CA compromise Remove that CA from the trust configuration and rotate it

A few rules of thumb:

  • Plain SSH keys are usually revoked by public key or fingerprint.
  • Certificates are best revoked by serial number or Key ID.
  • Serial-based KRLs are especially compact. OpenSSH documents that a KRL may use as little as one bit per certificate when you revoke by serial.

KRL vs removing a key from authorized_keys

Situation Best action
One public key in authorized_keys on one server Remove that line
Same public key on many servers A centrally distributed KRL may be easier
SSH certificate must stop before expiry Revoke with a KRL
Short-lived certificate expires soon Often let it expire
CA itself compromised Remove CA trust and rotate the CA

A KRL is not a replacement for careful authorized_keys hygiene on every host. Its biggest advantage is certificate revocation and one file you can push to many servers.


Lab topology

Minimal layout for these commands:

Ubuntu client + SSH CA
        |
        | presents SSH key / certificate
        v
   RHEL 10 SSH server
        |
        +-- trusts /etc/ssh/user_ca.pub
        +-- checks RevokedKeys /etc/ssh/revoked_keys

With the companion CA flow spelled out:

SSH CA (Ubuntu)
  |
  +-- signs user certificate
          |
          v
       Client
          |
          v
       Server (RHEL)
          |
          +-- TrustedUserCAKeys
          +-- RevokedKeys (KRL)

Files used in the lab:

text
/etc/ssh/user_ca.pub          # CA public key on the server
/etc/ssh/revoked_keys         # KRL enforced by sshd
~/ssh-user-ca                 # CA private key (Ubuntu only)
~/.ssh/id_ed25519.pub         # user public key
~/.ssh/id_ed25519-cert.pub    # user certificate

If you do not already have a working user CA and a successful certificate login, complete that setup first in the certificate authentication guide, then return here for revocation.


Check your OpenSSH version

Confirm the client and server packages before you change sshd. Do not use ssh-keygen -V for this: that flag is certificate validity syntax, not a version switch.

Ask the client for its OpenSSH build:

bash
ssh -V
output
OpenSSH_10.2p1 Ubuntu-2ubuntu3.6, OpenSSL 3.5.5 27 Jan 2026

On the RHEL server, ask sshd the same way:

bash
sshd -V
output
OpenSSH_9.9p1, OpenSSL 3.5.5 27 Jan 2026

The RPM NEVRA on my RHEL 10.2 server was openssh-server-9.9p1-25.el10_2.x86_64. KRL support has existed for many OpenSSH releases, so this is not a RHEL-only feature.

Confirm the man pages document the flags you will use. Open the ssh-keygen page and look for -k, -u, and -Q in the KEY REVOCATION LISTS section:

bash
man ssh-keygen

Then open sshd_config and search for RevokedKeys. That entry also documents the unreadable-file failure mode:

bash
man sshd_config

Those man pages are the official reference for the specification directives in later sections.


Create a test SSH certificate with a serial number

For certificate revocation, deliberately issue a non-zero serial. OpenSSH uses that serial for compact KRL records, and serial 0 cannot be used for serial-based revocation.

On the Ubuntu CA/client host, sign the user's public key with Key ID deepak-2026-01 and serial 1001:

bash
ssh-keygen -s ~/ssh-user-ca -I deepak-2026-01 -z 1001 -n deepak -V +8h ~/.ssh/id_ed25519.pub
output
Signed user key /home/deepak/.ssh/id_ed25519-cert.pub: id "deepak-2026-01" serial 1001 for deepak valid from 2026-09-22T15:41:00 to 2026-09-22T23:42:26

What those flags mean:

  • -I sets the certificate Key ID string
  • -z 1001 sets the certificate serial
  • -n deepak sets the principal (login name)
  • -V +8h sets a short validity window

Inspect the certificate so you can see the identifiers the KRL will use later:

bash
ssh-keygen -L -f ~/.ssh/id_ed25519-cert.pub
output
/home/deepak/.ssh/id_ed25519-cert.pub:
        Type: ssh-ed25519-cert-v01@openssh.com user certificate
        Public key: ED25519-CERT SHA256:Dh0YicssAH/zkefNQQTmvkkw9FIGvSbijtaP3nx6RVU
        Signing CA: ED25519 SHA256:+axU8dFjZi4r2zKVN7n9jHJs+XaIvwS55hsp5eUhdhc (using ssh-ed25519)
        Key ID: "deepak-2026-01"
        Serial: 1001
        Valid: from 2026-09-22T15:41:00 to 2026-09-22T23:42:26
        Principals:
                deepak
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

Confirm login still works before you revoke anything. With TrustedUserCAKeys already pointing at the CA public key on the server, a certificate login should succeed. The ssh command options below force public-key auth so a password prompt cannot hide a failed cert:

bash
ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no deepak@192.168.56.116 'echo BEFORE_REVOKE_OK'
output
BEFORE_REVOKE_OK

The server log for that success named the certificate Key ID and serial, which is useful when you later match a revoke to a journal line.


Create a KRL that revokes one SSH certificate

Start with the simplest path: revoke the certificate file itself. Copy the certificate to the server (or build the KRL on the CA host and distribute it). On the RHEL server:

bash
sudo ssh-keygen -k -f /etc/ssh/revoked_keys -s /etc/ssh/user_ca.pub /tmp/id_ed25519-cert.pub
output
Revoking from /tmp/id_ed25519-cert.pub

What this command does:

  • -k creates a new KRL
  • -f names the KRL file
  • -s supplies the issuing CA public key
  • the final argument is the certificate to revoke

This creates a new KRL. It does not merge into an existing one. OpenSSH records certificate revocation by serial number when it can; if no usable serial exists, it may fall back to the certificate Key ID.

Check that the file appeared with sane ownership and mode:

bash
ls -l /etc/ssh/revoked_keys
output
-rw-r--r--. 1 root root 121 Sep 22 15:42 /etc/ssh/revoked_keys

Root-owned and world-readable is fine for a KRL that every sshd child must read. Do not make the path unreadable; that has a worse failure mode later.


Check whether the certificate is revoked

Before you change sshd, query the KRL directly:

bash
ssh-keygen -Q -f /etc/ssh/revoked_keys /tmp/id_ed25519-cert.pub
output
/tmp/id_ed25519-cert.pub (deepak@client): REVOKED

The exit status is non-zero when at least one tested credential is revoked:

bash
echo $?
output
1

Exit status meaning:

  • 0 means none of the tested credentials are revoked
  • non-zero means at least one credential is revoked, or an error occurred

That makes -Q useful in scripts after you ship a KRL update.

As a contrast, the plain public key is still marked ok in a KRL that only revoked the certificate file:

bash
ssh-keygen -Q -f /etc/ssh/revoked_keys /tmp/id_ed25519.pub
output
/tmp/id_ed25519.pub (deepak@client): ok

Configure sshd to use the KRL

Create a drop-in so the main sshd_config stays untouched:

bash
sudo tee /etc/ssh/sshd_config.d/70-revoked-keys.conf >/dev/null <<'EOF'
RevokedKeys /etc/ssh/revoked_keys
EOF

Validate the config before you reload:

bash
sudo sshd -t

A silent exit means the syntax check passed. Reload sshd on RHEL-family hosts:

bash
sudo systemctl reload sshd

On Ubuntu or Debian the unit name is usually ssh:

bash
sudo systemctl reload ssh

Confirm the effective setting:

bash
sudo sshd -T | grep revokedkeys
output
revokedkeys /etc/ssh/revoked_keys
IMPORTANT
If the file configured by RevokedKeys cannot be read, OpenSSH refuses public-key authentication for all users. Fix path, mode, ownership, and SELinux labels before you point production sshd at a missing file.

Test a revoked certificate login

Attempt the same certificate login again:

bash
ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no deepak@192.168.56.116 true
output
deepak@192.168.56.116: Permission denied (publickey,password).

That client message alone is not enough. Read the server journal for the revoke reason. Unit filtering and time windows are covered in the journalctl reference:

bash
sudo journalctl -u sshd -n 20 --no-pager
output
sshd-session[59310]: error: Authentication key ED25519-CERT SHA256:Dh0YicssAH/zkefNQQTmvkkw9FIGvSbijtaP3nx6RVU revoked by file /etc/ssh/revoked_keys
sshd-session[59310]: Connection closed by authenticating user deepak 192.168.56.121 port 46360 [preauth]

The revoked by file /etc/ssh/revoked_keys line is the proof that sshd enforced the KRL, not only that ssh-keygen -Q recognized the certificate.


Add another key or certificate to an existing KRL

This step is easy to get wrong. Running ssh-keygen -k again without -u against the same path creates a new KRL and can drop earlier revocations.

Sign a second certificate with serial 1002 and Key ID deepak-2026-02, then merge it into the existing file:

bash
sudo ssh-keygen -k -u -f /etc/ssh/revoked_keys -s /etc/ssh/user_ca.pub /tmp/id_ed25519_alt-cert.pub
output
Revoking from /tmp/id_ed25519_alt-cert.pub

Flags:

  • -k stays in KRL mode
  • -u merges into the existing KRL instead of replacing it

Query both certificates afterward:

bash
ssh-keygen -Q -f /etc/ssh/revoked_keys /tmp/id_ed25519-cert.pub /tmp/id_ed25519_alt-cert.pub
output
/tmp/id_ed25519-cert.pub (deepak@client): REVOKED
/tmp/id_ed25519_alt-cert.pub (deepak-alt@client): REVOKED

Both stay revoked. That is the create-versus-update difference short tutorials often skip.


Revoke a plain SSH public key

KRLs are not only for certificates. By this point /etc/ssh/revoked_keys already exists and holds certificate revocations, so merge the plain public key with -u. Do not re-run bare ssh-keygen -k against the live path or you will create a new KRL and drop earlier entries.

bash
sudo ssh-keygen -k -u -f /etc/ssh/revoked_keys /tmp/id_ed25519.pub
output
Revoking from /tmp/id_ed25519.pub

If you only want a throwaway demo file, create a separate path such as /tmp/krl-plain-key with ssh-keygen -k instead of writing over /etc/ssh/revoked_keys.

Confirm the plain key is now revoked:

bash
ssh-keygen -Q -f /etc/ssh/revoked_keys /tmp/id_ed25519.pub
output
/tmp/id_ed25519.pub (deepak@client): REVOKED

Revoking the underlying public key also blocks authentication that presents a certificate for that same key. I tested a KRL that contained only the plain public key: ssh-keygen -Q reported the certificate REVOKED, and sshd logged both the certificate and the bare key as revoked by the file. If the private key is compromised, revoke the public key (or rotate), not only one certificate serial.


Revoke an SSH certificate by serial number

You do not need the original certificate file if you know the CA public key and the serial. Write a one-line KRL specification:

bash
printf 'serial: 1001\n' | sudo tee /tmp/revoke-serial.txt >/dev/null

Build a KRL from that specification:

bash
sudo ssh-keygen -k -f /tmp/krl-serial -s /etc/ssh/user_ca.pub /tmp/revoke-serial.txt
output
Revoking from /tmp/revoke-serial.txt

Query the certificate that carried serial 1001:

bash
ssh-keygen -Q -f /tmp/krl-serial /tmp/id_ed25519-cert.pub
output
/tmp/id_ed25519-cert.pub (deepak@client): REVOKED

A different serial from the same CA stays valid against that KRL:

bash
ssh-keygen -Q -f /tmp/krl-serial /tmp/id_ed25519_alt-cert.pub
output
/tmp/id_ed25519_alt-cert.pub (deepak-alt@client): ok

Serial 0 cannot be used for this form. Assign non-zero 64-bit serials when you issue certificates you expect to manage centrally.


Revoke a range of certificate serials

For an incident window or a bad issuance batch, revoke a contiguous range:

bash
printf 'serial: 1000-1099\n' | sudo tee /tmp/revoke-range.txt >/dev/null

Merge that range into the serial KRL:

bash
sudo ssh-keygen -k -u -f /tmp/krl-serial -s /etc/ssh/user_ca.pub /tmp/revoke-range.txt
output
Revoking from /tmp/revoke-range.txt

Serial 1002 is now revoked as part of the range:

bash
ssh-keygen -Q -f /tmp/krl-serial /tmp/id_ed25519_alt-cert.pub
output
/tmp/id_ed25519_alt-cert.pub (deepak-alt@client): REVOKED

Practical uses:

  • certificates issued during a bad deployment window
  • a group of certificates issued during the same compromised or incorrect signing window
  • retiring a reserved serial allocation range

Serial-based revocation is compact, which is one of the strongest reasons to assign meaningful non-zero serials at issue time.


Revoke certificates by Key ID

The certificate inspected earlier carried Key ID deepak-2026-01. Write that as a specification:

bash
printf 'id: deepak-2026-01\n' | sudo tee /tmp/revoke-id.txt >/dev/null

Build a KRL from the Key ID:

bash
sudo ssh-keygen -k -f /tmp/krl-id -s /etc/ssh/user_ca.pub /tmp/revoke-id.txt
output
Revoking from /tmp/revoke-id.txt

The matching certificate is revoked:

bash
ssh-keygen -Q -f /tmp/krl-id /tmp/id_ed25519-cert.pub
output
/tmp/id_ed25519-cert.pub (deepak@client): REVOKED

A certificate with a different Key ID is not:

bash
ssh-keygen -Q -f /tmp/krl-id /tmp/id_ed25519_alt-cert.pub
output
/tmp/id_ed25519_alt-cert.pub (deepak-alt@client): ok

Serial vs Key ID

Method Effect
Serial (or serial range) Targets one certificate or a numeric range
Key ID May revoke every certificate from that CA that carries the same Key ID

Key IDs are useful for identities or issuance batches. Assign them consistently, and do not reuse one Key ID across unrelated certificates unless you intend a group revoke.


Revoke a key by SHA256 fingerprint

When logs only give you a fingerprint, start from the public key or from sshd output:

bash
ssh-keygen -lf ~/.ssh/id_ed25519.pub
output
256 SHA256:Dh0YicssAH/zkefNQQTmvkkw9FIGvSbijtaP3nx6RVU deepak@client (ED25519)

Put that fingerprint into a hash: specification:

bash
printf 'hash: SHA256:Dh0YicssAH/zkefNQQTmvkkw9FIGvSbijtaP3nx6RVU\n' | sudo tee /tmp/revoke-hash.txt >/dev/null

Build the KRL (no -s is required for a plain-key hash revoke):

bash
sudo ssh-keygen -k -f /tmp/krl-hash /tmp/revoke-hash.txt
output
Revoking from /tmp/revoke-hash.txt

Query the public key:

bash
ssh-keygen -Q -f /tmp/krl-hash /tmp/id_ed25519.pub
output
/tmp/id_ed25519.pub (deepak@client): REVOKED

KRLs also support sha256: records. That directive takes a public key line; OpenSSH stores the SHA256 hash of that key in the KRL. Prefer hash: when all you already have is the fingerprint from logs. SHA1 forms exist for older compatibility; use SHA256 for new revocations.


KRL specification file reference

Directive Use
serial: 1001 One certificate serial
serial: 1000-1099 Inclusive serial range
id: deepak-2026-01 Certificate Key ID
key: ssh-ed25519 ... Explicit public key
sha256: ssh-ed25519 AAAA... Supply a public key; the KRL stores its SHA256 hash
hash: SHA256:... Supply an already-known fingerprint from logs or ssh-keygen -l

serial: and id: require the issuing CA public key via -s. Plain-key forms do not.


Inspect a KRL

Current OpenSSH can dump a readable summary with -Q -l:

bash
ssh-keygen -Q -l -f /etc/ssh/revoked_keys

After I revoked both certificates and the plain public key, the dump looked like this:

output
# KRL version 0
# Generated at 20260922T154248

hash: SHA256:Dh0YicssAH/zkefNQQTmvkkw9FIGvSbijtaP3nx6RVU # ssh-ed25519

# CA key ssh-ed25519 SHA256:+axU8dFjZi4r2zKVN7n9jHJs+XaIvwS55hsp5eUhdhc
serial: 1001-1002

That is enough to see which CA and serials are covered. The on-disk format remains a compact binary; do not expect a full pretty-print of every historical input file.


Revoke a compromised SSH CA

Revoking one certificate and removing the trusted CA public key are different incidents.

If the user CA private key is compromised:

  1. Stop trusting that CA: remove or replace it in TrustedUserCAKeys.
  2. Generate a new CA key pair.
  3. Distribute the new CA public key to every server.
  4. Reissue valid user certificates from the new CA.
  5. Optionally add the old CA public key itself to a KRL, depending on your trust model.

Do not try to enumerate every certificate ever issued by a compromised CA if you can remove the trusted CA public key from TrustedUserCAKeys. Removing that trust (sometimes called the trust anchor) is the cleaner incident response.


Revoke host keys and host certificates

Keep this short and separate from user login revocation.

  • RevokedKeys on the server rejects credentials presented for public-key authentication, including host certificates used in some host-based flows when they appear as authentication material.
  • On SSH clients, host-key KRLs are configured with RevokedHostKeys in ssh_config. That is separate from the server-side RevokedKeys directive used for user authentication.

Do not confuse deleting a line from ~/.ssh/known_hosts with KRL-based revocation. A compromised host certificate CA is primarily a client trust problem: rotate the host CA and update @cert-authority (or equivalent) trust, then reissue host certificates. For the full host-certificate path, stay with the certificate authentication guide rather than expanding this page into a second lab.


KRL vs certificate expiration

Situation Expiry KRL
Normal short-lived user certificate Best primary control Usually unnecessary
Laptop stolen before expiry Too slow Revoke immediately
Wrong principal issued Too slow Revoke
Certificate already expired Already invalid No need
Private key compromise Future certs must also be addressed Revoke the key / rotate
CA compromise Expiry of individual certs is insufficient Remove the trusted CA public key and rotate

Use short validity windows for routine access. Use a KRL when something must stop now.


KRL vs authorized_keys removal

Plain key on one server

Remove the line from:

text
~/.ssh/authorized_keys

Same key trusted across many servers

Distribute one KRL (or remove the key from every copy of authorized_keys). The KRL path scales better when the change rate is high.

Environments that use SSH certificates across many servers

A KRL is the native OpenSSH emergency revocation mechanism. Pair it with short-lived certificates so most access ends without a revoke at all.


Distribute a KRL across multiple SSH servers

A KRL only works on hosts that have the updated file. Creating it on the CA machine does not push revocation to the fleet by itself.

High-level options:

  • configuration management (Ansible, Puppet, Salt, and similar)
  • a controlled rsync or scp from a single source of truth
  • packaging the KRL with your config deployment system

When you update the production KRL, generate the new file separately and replace /etc/ssh/revoked_keys atomically rather than editing the live file in place. OpenSSH may consult that path on each authentication attempt, so an in-place rewrite can race with a login. Stage the new content under a temporary name next to the live path:

bash
sudo install -m 0644 /tmp/revoked_keys.new /etc/ssh/revoked_keys.new

Then move it over the live name so the replace is a single rename:

bash
sudo mv /etc/ssh/revoked_keys.new /etc/ssh/revoked_keys

After the file lands, validate the configuration first:

bash
sudo sshd -t

A silent exit means the syntax check passed. Reload so workers pick up the new KRL contents if your distribution requires it after the replace:

bash
sudo systemctl reload sshd

Keep the CA private key off the SSH servers. The servers need the CA public key and the KRL, not the signing key.


Check KRL permissions and availability

Confirm the path RevokedKeys names is present and readable:

bash
ls -l /etc/ssh/revoked_keys
output
-rw-r--r--. 1 root root 186 Sep 22 15:43 /etc/ssh/revoked_keys
IMPORTANT
If RevokedKeys is set but the file cannot be read, sshd refuses public-key authentication for all users. Treat a missing or unreadable KRL as an outage risk, not a soft warning.

Keep a recovery session open (console or an already authenticated session) while you change RevokedKeys or replace the file.


Troubleshooting OpenSSH KRL

Problem Likely cause Fix
Revoked certificate still works RevokedKeys not configured or not reloaded Check sshd -T | grep revokedkeys, then reload
Second revocation removed the first Recreated the KRL without -u Use ssh-keygen -k -u
ssh-keygen -Q says not revoked Wrong KRL, wrong key, or different certificate Inspect serial, Key ID, and CA with ssh-keygen -L
serial: rule fails Serial is 0, or wrong CA passed with -s Use a non-zero serial and the issuing CA public key
KRL blocks all public-key login File unreadable or path wrong Fix path, mode, ownership, SELinux; keep a recovery session
Key ID revoke hits more certificates than expected Same Key ID reused Use unique Key IDs; prefer serials for one-off revokes
Certificate already expired Expiry rejected it, not the KRL Check validity with ssh-keygen -L
Login still succeeds with a password Only the key or cert was revoked Review enabled authentication methods

Operational recommendations

  • Assign non-zero certificate serial numbers at issue time.
  • Use meaningful, deliberate Key IDs.
  • Prefer short-lived certificates for routine access control.
  • Use a KRL for emergency revocation.
  • Always use -u when updating an existing KRL.
  • Test every change with ssh-keygen -Q before and after reload.
  • Distribute KRL updates consistently to every server that trusts the CA.
  • Replace the live KRL atomically (install to a temp name, then mv) rather than editing it in place.
  • Protect the CA private key separately from the KRL distribution path.
  • Keep a recovery session open while changing sshd revoke settings.

Summary

An OpenSSH KRL is a compact binary revoke list. You create it with ssh-keygen -k, merge more entries with ssh-keygen -k -u, test credentials with ssh-keygen -Q, and make sshd enforce the file through RevokedKeys.

The beginner path starts with a real certificate file, then moves to specification directives: serial, serial range, Key ID, fingerprint, and plain public key. Serial-based revocation is especially efficient, which is why managed environments should issue non-zero serials instead of leaving -z unused.

The two operational mistakes that hurt most are recreating a KRL without -u (you drop earlier revocations) and pointing RevokedKeys at a missing or unreadable file (public-key authentication fails for everyone). Short-lived certificates reduce how often you need revocation. Use a KRL when access must stop before the certificate expires, after theft, or after a wrong principal. For CA compromise, remove the trusted CA public key and rotate rather than trying to list every old serial.


References


Frequently Asked Questions

What is an OpenSSH KRL?

A Key Revocation List is a compact binary file that lists SSH public keys and certificates OpenSSH must refuse. You build it with ssh-keygen and point sshd at it with RevokedKeys.

How do I revoke an SSH certificate?

Create or update a KRL with ssh-keygen -k (add -u to merge), supplying the CA public key with -s and either the certificate file or a serial:/id: specification. Configure RevokedKeys, run sshd -t, reload sshd, and confirm with ssh-keygen -Q plus a failed login and the revoked-by-file journal line.

How do I revoke a normal SSH public key?

When a live KRL already exists, merge with ssh-keygen -k -u and the .pub file. Use ssh-keygen -k only when creating a new KRL on a separate path. You can also use a hash: SHA256 fingerprint specification when you only have the fingerprint from logs. Revoking the underlying public key also blocks certificates that wrap that same key.

What is the difference between ssh-keygen -k and -k -u?

ssh-keygen -k creates a new KRL. ssh-keygen -k -u merges new revocations into an existing KRL. Re-running -k without -u against the same path can replace the file and lose earlier entries.

Can I revoke an SSH certificate by serial number?

Yes. Put serial: 1001 in a specification file, pass -s with the issuing CA public key, and build or update the KRL. Serial 0 cannot be used for serial-based revocation, so issue non-zero serials when you plan to manage certificates centrally.

Can I revoke multiple SSH certificates at once?

Yes. Merge several certificate files with -u, or revoke a serial range such as serial: 1000-1099. Key ID revocation can also hit every certificate from that CA that shares the same Key ID.

What happens if the RevokedKeys file is missing or unreadable?

sshd refuses public-key authentication for all users until the path is readable again. Fix permissions and path before enabling RevokedKeys in production, and keep a recovery session open while you change it.

Does deleting a certificate from the client revoke it?

No. Removing the certificate file from the client only stops that client from presenting it. Any copy of the private key plus certificate still works until expiry or until servers enforce a KRL (or stop trusting the CA).

Should I use certificate expiry or a KRL?

Use short expiry as the everyday control. Use a KRL when access must stop immediately, when a wrong principal was issued, or when a private key is compromised before the certificate would have expired.

How do I revoke a compromised SSH CA?

Remove or replace the CA in TrustedUserCAKeys, generate a new CA, distribute the new CA public key, and reissue valid certificates. Enumerating every old serial is usually worse than removing the trusted CA public key. Optionally revoke the old CA public key itself in a KRL depending on your trust model.

Finished reading?Beta Get the key takeaways in seconds, then ask follow-up questions
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with 15+ years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)