Creating FIDO2 SSH keys using ssh-keygen

$ ssh-keygen -t ecdsa-sk -f ~/.ssh/id_ecdsa_sk
  • -t ecdsa-sk specifies the key type to generate. Alternatively, you can generate Ed25519 keys using -t ed25519-sk.
  • -f ~/.ssh/id_ecdsa_sk specifies the output path for the newly generated key.

You can provide a passphrase for your key if you would like to do so. Unlike normal ssh keys, the private key is not that sensitive, as it is useless without the physical security key itself.

ed25519-sk vs ecdsa-sk

Newer YubiKeys (firmware >=5.2.3) and some other FIDO2 keys support Ed25519 keys. Ed25519 has some advantages over the common ECDSA keys in several respects:

  • Ed25519 is based on Curve25519, vs. NIST P-256 used for ecdsa-sk. Curve25519 is generally regarded as faster and safer than NIST P-256; see SafeCurves. Furthermore, the underlying signature algorithm (Schnorr vs. DSA) is slightly faster for Ed25519.
  • EdDSA in general, and Ed25519 in particular, uses a deterministic nonce versus the random nonce used by ECDSA. This means that ECDSA is prone to catastrophic entropy failure (see the famous fail0verflow PS3 hack as an example). Assuming your key has access to high-entropy randomness, that shouldn’t be a problem. However, that assumption might turn out to be false, as in the case of the reduced initial randomness in the YubiKey FIPS Series.

On the whole, if you have access to a key that supports ed25519-sk, then it’s preferable to use it. If you don’t, that’s not something to worry about too much. There are probably weaker points in your threat model anyway.

If your FIDO2 key doesn’t support ed25519-sk, you will get the following error when trying to generate a key:

Key enrollment failed: requested feature not supported

Moving keys to a new computer

If you want to use the keys on a new computer, you will have to copy over the private key file that you generated. That will normally be ~/.ssh/id_ecdsa_sk or ~/.ssh/id_ed25519_sk, depending on the type of key you generated.

Alternatively, you can generate resident keys, which are completely stored on the YubiKey. To generate resident keys, append -O resident to your ssh-keygen command. Example:

$ ssh-keygen -t ecdsa-sk -O resident

To import the keys to a new device, use the -K option:

$ ssh-keygen -K

This will download all the keys (public and private) from the YubiKey to the current directory. There is no need to manually transfer any key files.

YubiKey Series 5 devices can hold up to 25 resident keys.

Restricting SSH Access to rsync

Passphrase-less SSH keys allow one to automate remote tasks by not requiring user intervention to enter a passphrase to decrypt the key. While this is convenient, it poses a security risk, as the plain key can be used by anyone who gets hold of it to access the remote server. To this end, the developers of SSH made it possible to restrict, via .ssh/authorized_keys, the commands that can be executed by specific keys. This works great for simple commands, but because using rsync requires executing remote commands with different arguments on the remote end, depending on the invocation on the local machine, it gets quite complicated to properly restrict it via .ssh/authorized_keys.

Luckily, the developers of rsync foresaw this problem and wrote a script called rrsync (for restricted rsync) specifically to make it easier to restrict keys to be used only for rsync via .ssh/authorized_keys. If you have rsync installed, rrsync should have been distributed alongside it. On Debian/Ubuntu machines, it can be found under /usr/share/doc/rsync/scripts/rrsync.gz. If you cannot find it there, you can download the script directly from here. On the remote machine, copy the script, unpack it if needed, and make it executable:

user@remote:~$ gunzip /usr/share/doc/rsync/scripts/rrsync.gz -c > ~/bin/rrsync
user@remote:~$ chmod +x ~/bin/rrsync

On the local machine, create a new SSH key and leave the passphrase empty (this will allow you to automate the rsync via cron). Copy the public key to the remote server.

user@local:~$ ssh-keygen -f ~/.ssh/id_remote_backup -C "Automated remote backup"
user@local:~$ scp ~/.ssh/id_remote_backup.pub user@remote:~/

Once the public key is on the remote server, edit ~/.ssh/authorized_keys and append the public key.

user@remote:~$ vim ~/.ssh/authorized_keys

(Vim tip: Use :r! cat id_remote_backup.pub to directly insert the contents of id_remote_backup.pub into a new line). Now prepend the following to the newly added line:

command="$HOME/bin/rrsync -ro ~/backups/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding

The command="..." restricts access for that public key by executing the given command and disallowing others. All the other no-* stuff further restricts what can be done with that particular public key. As the SSH daemon will not start the default shell when accessing the server using this public key, the $PATH environment variable will be pretty empty (similar to cron), so you should specify the full path to the rrsync script. The two arguments to rrsync are -ro, which restricts modifying the directory (drop it if you want to upload stuff to the remote directory), and the path to the directory you want to enable remote access to (in my example ~/backups/).

The result should look something like:

command="$HOME/bin/rrsync -ro ~/backups/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-rsa AAA...vp Automated remote backup

After saving the file, you should be able to rsync files from the remote server to the local machine, without being prompted for a password.

user@local:~$ rsync -e "ssh -i $HOME/.ssh/id_remote_backup" -av user@remote: etc2/

Two things need to be noted:

  1. You need to specify the passphrase-less key in the rsync command (the -e "ssh -i $HOME/.ssh/id_remote_backup" part).
  2. The remote directory is always relative to the directory given to rrsync in the ~/.ssh/authorized_keys file.

ssh-keygen Tutorial – Generating RSA and DSA Keys

In this post I will walk you through generating RSA and DSA keys using ssh-keygen. Public key authentication for SSH sessions is far superior to password authentication and provides much higher security. ssh-keygen is the basic way to generate keys for this kind of authentication. I will also explain how to maintain those keys by changing their associated comments and, more importantly, by changing the passphrases using this handy utility.
Continue reading ssh-keygen Tutorial – Generating RSA and DSA Keys