The YubiKey supports four methods to enable hardware-backed SSH authentication.

  • FIDO2
  • PIV
  • PGP
  • OTP

FIDO2 provides the highest security and comes with low complexity. The private key is non-exportable.

Limitations

  • OpenSSH v 8.2.p1 is a requirement better 8.3 for the verify-required option, shouldn’t be an issue since both versions were released in 2020.

  • Windows SSH at the time of writing not supported.

  • The Mac OS bundled openssh version doesn’t support it but this can be fixed.

Configuration

Generate ed25519-sk keys

  • In a Enterprise enviroment you would add -O verify-required to make use of your fido pin additionaly to the touch

  • I get prompted for my existing fido2 pin this is only for the setup. The Password can stay empty this is only for the key handle file. If you set password you will be prompted for the password what adds no additional security

  • My default ssh slot is already used a different slot can be be used by supplying application=ssh:bitlex-homelab

ssh-keygen -t ed25519-sk -O resident -O application=ssh:bitlex-homelab -C "slexi@bitlex.li" 
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
Enter PIN for authenticator: 
You may need to touch your authenticator again to authorize key generation.
Enter file in which to save the key (/home/slexi/.ssh/id_ed25519_sk): /home/slexi/.ssh/bitlex-homelab_ed25519_sk
Enter passphrase for "/home/slexi/.ssh/bitlex-homelab_ed25519_sk" (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/slexi/.ssh/bitlex-homelab_ed25519_sk
Your public key has been saved in /home/slexi/.ssh/bitlex-homelab_ed25519_sk.pub
The key fingerprint is:
SHA256:C0rn46hCkoTODRdrPnin6lPTe6Eh8sd5dfouoMgP6r8 slexi@bitlex.li
 @slexi  ls bitlex*                   
bitlex-homelab_ed25519_sk # = Key Handle file this file must be present to initiate authentication, but is useless without the yubikey  
bitlex-homelab_ed25519_sk.pub # = public key

The private is on the yubikey.

Configure ssh-agent socket

Enable and start the ssh-agent for my user

systemctl --user enable --now ssh-agent

Read the service definition

 @slexi  systemctl --user cat ssh-agent.service
# /usr/lib/systemd/user/
ssh-agent.service
# Requires SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket" to be set in envi
ronment
[Unit]
ConditionEnvironment=!SSH_AGENT_PID
Description=OpenSSH key agent
Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1)
Requires=ssh-agent.socket

[Service]
ExecStart=/usr/bin/ssh-agent -D
SuccessExitStatus=2
Type=simple

[Install]
Also=ssh-agent.socket

On Arch, I added the socket shown above to my shell configuration.

export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

SSH-Agent configuration

The .ssh/config defines how we connect to the server.
We tell the ssh-agent to pick up our key handle file to initiate a connection and optionally set the user.
.ssh/config

Host <destination-server>
    IdentityFile ~/.ssh bitlex-homelab_ed25519_sk  
    IdentitiesOnly yes
    User debian 

Destination Server configuration

Put the pub-key in .ssh/authorized_keys on the destination server can be done with

ssh-copy-id -i ~/.ssh/bitlex-homelab_ed25519_sk.pub <user>@<destination-server>

Test it

ssh <ip/hostname>

Additional

On a new machine, the key file can be extracted from the YubiKey, which will prompt you for your FIDO2 PIN.

ssh-keygen -K

To calculate the pub key again

 ssh-keygen -y -f ~/.ssh/bitlex-homelab_ed25519_sk > ~/.ssh/bitlex-homelab_ed25519_sk.pub



References

https://developers.yubico.com/SSH/
https://amboar.github.io/notes/2023/05/01/sshd-fido2-touch-required.html