This guide is for Linux/WSL. I don’t have a Mac to test with, but I suspect most of the principles apply. You will need to be running OpenSSH 8.2 or later (released 2020-02-14).
Modern Yubikeys (5.2.3+) can perform ed25519 operations onboard. This includes keeping the private key onboard, which is really what we’re after. There are other guides describing how to do this, but they’re all missing some key ingredient, or they add extra steps that I don’t need.
If you follow these steps:
- Your git commits will be cryptographically signed, and GitHub will show this.
- All authenticated GitHub operations (push/pull) will require a touch to your Yubikey.
- Your private key never leaves your Yubikey.
- You won’t need to learn GPG or have to maintain GPG keys.
- If your Yubikey is lost or stolen, your key is protected by a PIN.
1. Install ykman
ykman
is a Yubikey CLI tool we’ll use for some initial setup. Download ykman
2. Create a PIN for FIDO operations
This PIN will protect you if your key is stolen or lost. You’ll need to memorize this PIN, because every time you reboot your computer, you’ll need to enter it before performing any crypto operations. The PIN is mandatory.
ykman fido access change-pin --new-pin
You should probably write your PIN down somewhere on paper.
3. Create a new ed25519 key
ssh-keygen -t ed25519-sk -C ben@mars.sk1 -O user=ben@mars.sk1 -O resident
The email addresses that you specify to ssh-keygen don’t have any effect on signing or identify verification, which is why I use them merely to help identify my keys. I use the “sk1” suffix to tell me that this is my security key #1. My second Yubikey will use “sk2”, etc. “Mars” is the hostname where I generated the key.
The -O user
option will cause that string to be written into the key data on the Yubikey, which helps identify it, if you have multiple keys on one device (I only have one).
The -O resident
option tells ssh-keygen
that the private key is going to live on the hardware device.
The -sk
in ed25519-sk
stands for Security Key, and if you want more details about all this, see the OpenSSH 8.2 Release Notes
4. Make sure the new key is on your Yubikey
ykman fido credentials list
My output looks like this:
ssh: 62656e406d6172732e736b310000000000000000000000000000000000000000 openssh
The long string ending in 00000 is the hex encoding of the identifier that you specified in “-O user”, padded with zeroes.
5. Delete the private key off your hard drive
rm ~/.ssh/id_ed25519_sk
Note however, that we leave the public key file id_ed25519_sk.pub
, because we’ll need it for signing git commits.
6. Tell ssh-agent about your hardware key
Add keys from hardware devices into your local store:
ssh-add -K
My output is:
Resident identity added: ED25519-SK SHA256:7vuh0DJyNjehHIEZnDEQ7ZafWp/o2Eed+tNKtps6l9g
This does not copy the private key into memory. You’ll still need to touch your Yubikey whenever the private key is needed. But ssh-add -K
is necessary for informing ssh-agent that this key exists.
Note that every time you reboot, you’ll need to run ssh-add -K
before using your key, and this operation requires your PIN.
7. Add your key to Github
You can use this command to list your public keys:
ssh-add -L
My output looks like this:
sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIE7Isiad1PJ/pusAKFtiPYg617QxeFcDJcbuFPJ+L8nPAAAABHNzaDo=
Go to your Github profile, and under SSH and GPG keys
, add this new key.
You’ll have to add it twice. Once as an Authentication
key, and once as a Signing
key.
8. Configure git to sign with your new key
git config --global commit.gpgsign true
git config --global gpg.format ssh
git config --global user.signingkey "~/.ssh/id_ed25519_sk.pub"
9. Make a test commit
In order to complete the creation of your commit, you’ll need to touch your Yubikey. It should flash, indicating that it wants to be touched.
git push
will also require a touch.
10. Verify on GitHub
Any commit that you make from now on, should show up on Github with the green Verified
badge, and if you click on it,
GitHub will show you the person associated with that commit.
If you click on the Verified
button on GitHub, it will show you the SHA256 hash of the key that signed this commit, which should match the hash
that you’ll see when doing ssh-add -K
.
11. Verify locally
Unfortunately, I don’t know how to verify signatures locally. I think this is because GPG doesn’t understand the sk-ssh-ed25519@openssh.com
key format.
The following procedure might work in future, but it doesn’t work for me now.
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
cat ~/.ssh/id_ed25519_sk.pub >> ~/.ssh/allowed_signers
git show --show-signature
Sources
This guide was based on the following sources: