Skip to content

OpenSSH Certificates

OpenSSH certificates replace the traditional authorized_keys model with a trust hierarchy: a Certificate Authority (CA) signs your public key, and any server that trusts the CA lets you in — no per-server key deployment required. ZestSSH supports OpenSSH user certificate authentication: import a CA-signed certificate, attach it to one of your keys, and connect.

This is the client that Vault SSH, Smallstep step-ca, Teleport, and hand-rolled ssh-keygen -s CA setups have been waiting for.

Certificate management (importing and attaching certificates) lives in the desktop Keys view. Once a certificate is attached to an identity, it is presented automatically whenever that identity connects.

PlatformStatus
WindowsFull support (import + attach)
macOSFull support (import + attach)
LinuxFull support (import + attach)
AndroidCertificate management not available (desktop only)
iOSCertificate management not available (desktop only)

Traditional SSH authentication requires deploying each user’s public key to every server’s authorized_keys file. That does not scale: onboarding a new engineer or rotating a key means editing files on every host. Certificates fix this by introducing a signer everyone already trusts:

  1. A Certificate Authority (CA) generates a signing key pair.
  2. The CA’s public key is configured as trusted on each server (TrustedUserCAKeys in sshd_config).
  3. A user’s public key is signed by the CA, producing a certificate that bundles the public key with metadata — principals, validity window, serial number, and extensions.
  4. When the user connects, the server accepts the certificate because it carries a valid CA signature. No authorized_keys entry is needed.

The analogy: an authorized_keys entry is like a guard who keeps a photo of every face allowed through the door. A certificate is a passport — the guard only needs to recognize the issuing government’s seal, and the passport itself says who you are and when it expires.

During public key authentication, ZestSSH advertises the certificate algorithm (for example [email protected]) and sends the full certificate blob as the public key. The signature over the authentication challenge is still produced by your underlying private key — the certificate changes what the server sees, not how signing works. ZestSSH accepts user certificates only; if you paste a host certificate it is rejected with a clear error, because host certificates authenticate servers, not people.

ZestSSH parses and presents all nine OpenSSH user-certificate algorithms:

Certificate algorithmUnderlying key
[email protected]Ed25519
[email protected]RSA (SHA-256 signature)
[email protected]RSA (SHA-512 signature)
[email protected]RSA (SHA-1 signature, legacy)
[email protected]ECDSA P-256
[email protected]ECDSA P-384
[email protected]ECDSA P-521
[email protected]FIDO2 Ed25519 (hardware-backed)
[email protected]FIDO2 ECDSA P-256 (hardware-backed)

The two sk-* rows are FIDO/security-key certificate types — a certificate that wraps a hardware-resident key. See FIDO2 Hardware Keys for how the underlying sk- keys are handled through the OS ssh-agent.

The working path today is sign externally, then import and attach. You need a software key already saved as an identity — the certificate is attached to it.

Have your CA sign the public key that matches the identity you will attach it to. With OpenSSH’s own tooling:

Terminal window
# ca_key is your CA's private key; id_ed25519.pub is the key in your ZestSSH identity
ssh-keygen -s ca_key -I alice@example -n alice,deploy -V +52w id_ed25519.pub
# produces id_ed25519-cert.pub

Vault SSH, step-ca, Teleport, or any other CA that emits standard OpenSSH certificates works the same way — the output is an id_*-cert.pub line.

  1. Open the Keys view.
  2. Under Certificates, choose Import certificate.
  3. Paste the id_*-cert.pub line (or use Pick file… to load it).
  4. ZestSSH parses it and shows the details: algorithm, key ID, serial (hex), principals, validity window, and the CA’s SHA-256 fingerprint. An expired certificate is flagged in red.
  1. In the same dialog, pick the identity to attach the certificate to.
  2. Only identities whose key algorithm and public-key bytes match the certificate are selectable — everything else is shown but disabled with the reason, so you can see why a key does not qualify.
  3. Confirm with Attach certificate. ZestSSH re-verifies that the certificate’s embedded public key matches the identity’s private key, stores the certificate blob in secure storage, mirrors its metadata for display, and flips the identity’s auth method to Certificate.

From then on, connecting with that identity presents the certificate automatically.

ZestSSH’s SSH engine (zest_ssh_core) includes a full certificate signer — it can build a to-be-signed blob, sign it with a CA key held in secure storage, and emit a standard id_*-cert.pub line, including default permit-* extensions that mirror ssh-keygen -s. The in-app “Generate certificate” flow is being finalized (it needs the CA-key editor to ship alongside it). Until then, the Generate certificate button points you at the external workflow above: sign with ssh-keygen -s (or your CA), then import the result.

  • Attaching a certificate to the wrong key. The certificate embeds a specific public key. If it does not match the identity’s private key, ZestSSH refuses the attach — re-check that you imported the certificate issued for that key, or re-issue it.
  • Importing a host certificate. Host certificates (type 2) authenticate servers. ZestSSH only accepts user certificates for client login and will tell you so.
  • Expired or not-yet-valid certificates. The validity window is enforced by the server. ZestSSH surfaces the valid after / valid before dates and flags expiry, but a stale certificate still fails at the server — re-issue with a fresh -V window.
  • CA not trusted on the server. The certificate is worthless unless the server lists your CA in TrustedUserCAKeys. Verify the CA fingerprint ZestSSH shows matches the CA the server trusts.
  • Principal mismatch. If the certificate’s principals do not include the username you are logging in as, the server rejects it. Check the Principals line in the import summary.

Certificate authentication is not tier-gated — it is available on Free, Squeezed, and Juiced. The only Free-tier limit that touches SSH is the concurrent-session cap (up to 4 on desktop, 2 on mobile); the authentication method you use makes no difference.

Q: Can I import an OpenSSH certificate into ZestSSH? A: Yes. Paste an id_*-cert.pub line (or pick the file) in the Keys view, then attach it to the matching software key.

Q: Can ZestSSH act as the CA and sign certificates for me? A: The engine can, but the in-app generation UI is still being finalized. For now, sign with ssh-keygen -s or your CA of choice and import the result.

Q: Does ZestSSH work with HashiCorp Vault SSH? A: Yes, with the certificate signing backend. Have Vault sign your public key, then import the returned certificate. (Vault’s OTP backend also works — enter the OTP as a password.)

Q: Are host certificates supported for verifying servers? A: Not yet. Host key verification uses the trust-on-first-use (TOFU) known-hosts model with changed-key warnings. Certificate authentication described here is for user login only.

Q: Which underlying key types can carry a certificate? A: Ed25519, RSA, ECDSA (P-256/P-384/P-521), and the two FIDO2 sk- types. See the table above.