Skip to main content

SSH key on a FIDO2 token: ed25519-sk and ecdsa-sk

Security · 09.11.2026 · 6 min read

Why give an SSH key a hardware token

An ordinary private key is a file, and it can be stolen along with a disk or a backup. With a key on a FIDO2 token the secret stays inside the device, and logging in requires physically touching the token. The file on disk does not grant access by itself, and malware cannot log in to the server without your touch.

If you add the verify-required option, a PIN joins the touch — that makes two factors. The general scheme is described in the article on two-factor authentication on a server.

What you will need

You need OpenSSH 8.2 or newer and a FIDO/U2F token. Support for such keys appeared in OpenSSH 8.2, and the verify-required option, which demands a PIN, in 8.4. Resident keys require a token that specifically supports FIDO2.

WhatRequirement
Client and serverOpenSSH 8.2 or newer
PIN on every signaturethe verify-required option, OpenSSH 8.4 or newer
ecdsa-skmandatory for any FIDO/U2F token
ed25519-sknot every token supports it
Resident keya FIDO2 token, usually with a PIN set
libfido2OpenSSH recommends version 1.5.0 or newer

How to create the key

Creation is a single ssh-keygen command with the type ed25519-sk or ecdsa-sk. The token must be plugged in, and at the right moment you have to touch it. If the token does not support ed25519-sk, choose ecdsa-sk.

  1. Plug in the token and make sure OpenSSH 8.2 or newer and libfido2 are installed.
  2. Run ssh-keygen with the type you need and, optionally, -O verify-required; touch the token.
  3. Set a passphrase on the key file if you want to protect that as well.
  4. Copy the public part to the server.
  5. Open a second session and test the login without closing the first.
ssh-keygen -t ed25519-sk -O verify-required -f ~/.ssh/id_ed25519_sk
# if the token does not know ed25519-sk
ssh-keygen -t ecdsa-sk -O verify-required -f ~/.ssh/id_ecdsa_sk
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub user@server.example

In authorized_keys the public key will begin with sk-ssh-ed25519@openssh.com, and for ecdsa-sk with sk-ecdsa-sha2-nistp256@openssh.com. General rules for working with keys are in the article on SSH keys for a VDS.

Resident keys

An ordinary key has two parts: a file on the computer and a secret in the token. With a resident key the handle file lives on the token itself, so the key can be downloaded to another computer with ssh-keygen -K. This is convenient, but it carries a risk described below.

ssh-keygen -t ed25519-sk -O resident -O verify-required -O application=ssh:work
ssh-keygen -K

You need a FIDO2 token, usually with a PIN set beforehand. By default the application is ssh:, and OpenSSH uses only resident keys that begin that way, so put your own suffix after it. The command with -K writes the key files to the current directory.

A caveat from the ssh-keygen manual: storing both parts of a key on the token increases the likelihood that an attacker can use a stolen token. For a resident key, set a PIN and verify-required.

Server setup: touch and PIN

By default sshd requires a touch of the token. You can tighten this with the PubkeyAuthOptions option in sshd_config or relax it for a single key in authorized_keys. Do not relax it without need: the touch is the main argument for such a key.

OptionWhere it is setWhat it does
touch-requiredPubkeyAuthOptionsrequires a touch
verify-requiredPubkeyAuthOptions or authorized_keysrequires user verification, currently a PIN
no-touch-requiredauthorized_keyslets the key log in without a touch

A key created with -O no-touch-required will not work on a server without that permission. The other daemon settings are covered in the article on hardening sshd_config, and for many servers look at SSH certificates with a certificate authority.

How not to lose access

A token can be lost, broken or left at home, so a single token is a single point of failure. Get a second token and register both keys on the server, and do not disable the old way of logging in until the new one has been tested in a separate session.

  1. Create a key on the second token and add both public keys to authorized_keys.
  2. Keep a spare ordinary key on offline media in a safe place.
  3. Test the login with the new key in a new session without closing the working one.
  4. Only then tighten sshd_config and remove the old keys or passwords.
  5. Find out in advance how to reach the server through the host console if key login fails.
# on Debian and Ubuntu the service is called ssh
sshd -t && systemctl reload sshd
grep -c "^sk-" ~/.ssh/authorized_keys

By FIDO design the secret cannot be extracted from the token, so losing a single token with no spare is losing your login.

Limitations and pitfalls

The main limits of such a login are that the token must be at hand and the touch cannot be automated. A key with a touch is not suitable for scripts, CI and cron: create a separate ordinary key with narrow rights. Servers running OpenSSH older than 8.2 will not accept sk keys.

  • Not every token can do ed25519-sk: for FIDO/U2F only ecdsa-sk is mandatory.
  • Not all tokens support resident keys and verify-required.

Frequently asked questions

Which type should I pick: ed25519-sk or ecdsa-sk?

Start with ed25519-sk. If the token does not support it, take ecdsa-sk: that is the one mandatory for all FIDO/U2F tokens.

Do I need a PIN?

For resident keys, usually yes. For ordinary ones the PIN is optional: the verify-required option adds it to the touch, but not all tokens support it.

What should I do if I lose the token?

Log in with the spare key or the second token, delete the lost key’s line from authorized_keys and issue a new one. The spare has to be prepared in advance.

What should ZevsHost customers do?

On shared hosting keys are added through cPanel while sshd belongs to the provider’s server: you can enable neither mandatory touch nor a PIN there, and whether the server accepts an sk-key depends on its OpenSSH version. The token comes into its own on a VPS or dedicated server, where authorized_keys and sshd_config are yours: second token first, then testing, then tightening.

Was this article helpful?
← Back to Knowledge Base Ask Support