I was coworking with a friend the other day when he saw my Yubikey and asked me if I was using it to store my servers’ SSH keys.

“Can my YubiKey store SSH keys?”, I thought. And I started researching. Well, turns out it doesn’t work that way, but you can use your YubiKey (or any FIDO U2F device, for that matter) to harden your SSH login.

Here’s what we’re trying to accomplish:

  1. We try to log in into our machine with SSH
ssh [email protected]

2. The machine asks for YubiKey authentication, even though we have the right SSH private key

ssh [email protected]
> Confirm user presence for key ECDSA-SK SHA256:...

3. You touch your YubiKey

5nfc-touch-2020.jpg

4. You’re in!

ssh [email protected]
> Confirm user presence for key ECDSA-SK SHA256:...
> User presence confirmed

We have effectively added a second factor authentication to our SSH login using our Yubikey’s U2F capabilities.


Why would you do this?

Same reason why you add Second Factor Authentication (2FA) to any password-protected account you own.

If an attacker gains access to your user and password, they’d be unable to log in unless they also have access to your hardware key or OTP device you use for 2FA.

Your SSH private key is kind of like a password. Only that you store it in your hard drive. So anyone who hacks into your computer could access all servers that private key is configured to.

I’ve been tinkering with crypto stuff lately, so my mental model is that storing your SSH private key in your hard drive is kind of like having a hot wallet. Pretty secure most of the time, but you’re done if someone gets access to your computer – which is plausible, since your computer is connected to the internet and the internet is full of bad actors. Adding a multi factor authentication with a Yubikey makes it more like a cold wallet. Part of the secret key is stored in an independent hardware device that’s not connected to the internet and that’s designed not to leak the key.

Adding a Yubikey 2FA to your SSH login is interesting for several reasons:

  • It’s resistant to data leaks / data being stolen. Even if your computer or backups get accessed to, compromising the SSH private keys, attackers can’t access the servers.
  • It’s resistant to phishing attacks. You can’t reveal what you don’t know.
  • It’s resistant to digital hacks. The attacker would need physical access to the key.

The only possible attack would be a targeted attack. Someone would have to single you out, know which servers you access to, what’s the SSH certificate you use to access them, somehow steal that private key AND then get physical access to your Yubikey to gain access of the servers. It’s not impossible, but it’s definitely more secure than not having the Yubikey additional protection in place.

How to configure your Yubikey to protect your SSH login with 2FA

Time needed: 15 minutes.

To create a 2FA-enabled SSH key pair, go through the following steps:

  1. Check that you have OpenSSH 8.2 or higher both on your local machine and on your server

    Versions previous to OpenSSH_8.2 do not support 2FA with hardware security keys like Yubikey. To check what version you’re running, execute:

    ssh -V

    Note for macOS users: your native version of OpenSSH won’t work. You’re gonna need to install OpenSSH via homebrew:

    brew install openssh

    The reason is even though your OpenSSH version is higher than 8.2p1, Apple has specifically compiled OpenSSH with the –disable-security-key flag, making their OpenSSH version unable to interact with Yubikeys. If you try to use the native macOS version of OpenSSH, you’ll get the following error message:

    Key enrollment failed: unknown or unsupported key type

    If your server runs Debian 10 Buster (like mine did, and many AWS Lightsail images), you’re gonna need to upgrade to Debian 11 (Bullseye).

  2. Check ssh-keygen can generate U2F keys

    Run:

    ssh-keygen --help

    and look at the types of keys it can generate. On my system, that’s: [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]

    The ecdsa-sk and ed25519-sk types are the only valid ones for 2FA enabled SSH key pairs. The ‘-sk’ part stands for ‘security key’.

  3. Generate a ecdsa-sk or ed25519-sk SSH key pair using ssh-keygen

    Run:

    ssh-keygen -t ed25519-sk -f ~/.ssh/securitykey

    It’ll ask you to touch your Yubikey:

    > Generating public/private ed25519-sk key pair.
    > You may need to touch your authenticator to authorize key generation.


    Just touch the metal circle and it’ll bind the SSH key pair to your Yubikey.

    When it says “Enter passphrase (empty for no passphrase)”, you can just press enter to leave it empty.

    This will generate an ed25519 SSH keypair named securitykey under ~/.ssh

  4. Copy your new U2F SSH public key to your server

    If you have password access to your server, you can just run

    ssh-copy-id -i ~/.ssh/securitykey.pub user@server

    And enter the login password when it asks you for it.

    If you’re accessing your server with a previous SSH key, you can just ssh into your server and edit the authorized_keys file

    nano ~/.ssh/authorized_keys

    Just append the contents of securitykey.pub to the end of it, save and exit.

  5. Create a backup U2F SSH certificate

    If you lose your Yubikey, you lose access to your servers. That’s why it’s recommended to have several Yubikeys as backup, so that you can still access your services in case you lose the one hardware key you usually carry around with you.

    You can’t add a second Yubikey to the SSH key pair we’ve just created, but you can create another key pair with a different Yubikey. Just repeat steps 3-4 with a different Yubikey, changing the name of the SSH certificate, as in securitykey1 and securitykey2.

And we’re done!

Conclusion

SSH is a secure way of accessing servers. But if your private key gets compromised, an attacker can gain access to your servers.

Adding Second Factor Authentication (2FA) with a hardware security key like Yubikey is a good option to strengthen your SSH setup, because attackers would need to get physical access to your hardware key on top of having your SSH private key.

OpenSSH >= 8.2 adds the capability of creating 2FA-compatible SSH key pairs of type ecdsa-sk and ed25519-sk.

Setting up a few 2FA-enabled SSH key pairs is pretty straightforward and can be done in just a few minutes – saving you lots of headaches in the event your computer is hacked or your private key gets leaked.

P.S.: Follow me on Twitter to stay in the loop. I'm writing a book called Bold Hackers on making successful digital products as an indie hacker. Read other stories I've written. Subscribe below to get an alert when I publish a new post:

No spam ever, unsubscribe with one single click.

  1. Chris
    Feb 01, 2023

    Hey, i think there’s a bug. You say to generate key type ed25519 and not ed25519-sk.

    Reply
    • rameerez
      Feb 04, 2023

      Fixed! Thanks for the heads up!

      Reply
  2. Aragorn
    Mar 28, 2023

    You solved a huge problem for me. Incredible, I’ve searched many sites but they all have complicated instructions and in the end the solution didn’t even work. I followed your “simple” instructions and like magic it worked! Unfortunately, however, I have a problem that blocks me. The key creation operation with the private key memorization in the yubukey, I did in a computer with linux on board. In the .ssh folder I found the file with the .pub extension and another file with the same name but without extension, opening this last file I find private key written at the beginning, is it the private key or is it just a link? But that’s not so much the problem, the problem is that the connection to the remote server doesn’t work for me if I try to connect from a MAC. The version of openssl on the MAC is “OpenSSH_9.0p1, LibreSSL 3.3.6”. The MAC .ssh folder contains only the known_hosts file. Do you have any advice for me?

    Reply
  3. Robin
    Jan 12, 2024

    Wonderful summary! Windows users should bear in mind that they either need to use the Linux subsystem or install Powershell OpenSSH beta which is not easy to find. The integrated SSH as of now is too old.
    https://github.com/PowerShell/Win32-OpenSSH/releases
    If you do not add a comment using the -C option it will put something like “username@yourlocalmachine” as the key identifier. This is confusing since you may register more than one key on the same machine but use them on different machines. So better to use something like -C ‘Yubikey A’.
    Not all servers do yet support this rather new feature so I had to give up and use normal SSH keys instead.

    Reply
  4. Josh
    Feb 13, 2024

    Nice article! You say 2FA several times, but you say to skip the passphrase. You really then have two of the same factor, something you have (private key and yubikey). Better than just one, but not 2FA. you need a passphrase on it (something you know) for 2FA.
    Again, great how to, I will be using this as a guide, with the addition of a passphrase.

    Reply