Using a Yubikey for connecting from a Mac to a server via SSH wasn't so straight-forward as it seemed. You have probably read drduh's guide or even this one, but netiher of them is straight-forward while supporting Yubico's recommendation of having two Yubikeys (one primary, one backup).
After this guide, you will have one primary key for everyday SSH use, and one backup key to put in a safe, both sharing the same private key, without GPG/PGP.
This is a step-by-step guide for how to succeed.
- MacOS with Homebrew
- 2 x Yubikeys (we use 5C, but any CCID-enabled Ubikey should work)
These steps should preferably be done on a fresh computer that we easily can disconnect from internet, and earse the whole computer afterwards. We used a Raspberry Pi. It might sound paranoid, but let's just be 100% sure that your private key can't be compromised in any way. If you follow this recommendation or not is totally up to you.
Either:
brew install ykman
sudo apt-get update
sudo apt-get install yubikey-manager
I'm not kidding - disconnect from internet.
Connect your Ubikey, and either:
ykman piv change-management-key --touch --generate
ykman piv change-management-key --touch
The default is 3 retries each, then you're screwed. You might want to increase these:
ykman piv set-pin-retries 10 10
The default PIN/PUK codes are 123456 and 12345678 respectively - we do obviously want to change these:
ykman piv change-pin
ykman piv change-puk
Yubikey 5C does unfortunately only support 2048-bit RSA keys at best.
openssl genrsa -des3 -out key.pem 2048
openssl rsa -in key.pem -outform PEM -out private.pem
openssl rsa -in key.pem -outform PEM -pubout -out public.pem
Requiring key touch will improve security, but we don't want to do this all the time. Setting touch-policy to cached will "only" require a touch every 15 seconds. You can also choose never if you're bothered with this.
ykman piv import-key --touch-policy cached 9a private.pem
ykman piv generate-certificate -s ssh 9a public.pem
As the private keys on Yubikeys are read-only, you should really want to save the generated files to an encrypted USB stick. If you don't want to bother with encrypted partitions, the easiest encryption is a ZIP file. It's better than nothing:
zip -e piv.zip .
If it's a Raspberry Pi, earse everything on the SD card. If not, then ensure all files are properly deleted permanently and empty your trash can. Put your USB stick and backup Yubikeys in a safe.
Now we're back online with our MacOS. Let's configure the ssh-agent to listen for our Ubikeys.
brew cask install opensc
ssh-add -s /usr/local/lib/opensc-pkcs11.so
These should be identical for every key:
ssh-keygen -D /usr/local/lib/opensc-pkcs11.so
Add it to the servers you want to SSH into with your Ubikey.
Edit your ~/.ssh/config file with either:
Host *
PKCS11Provider /usr/local/lib/opensc-pkcs11.so
IdentitiesOnly yes
Host example.com
PKCS11Provider /usr/local/lib/opensc-pkcs11.so
IdentitiesOnly yes
You should now be able to connect to your servers as usual as long as your Ubikey is connected:
ssh username@host.com
You will notice that when you connect to the server, it will freeze. This is because the key is waiting for your touch. Touch it, and you're in.