Update: Watch my talk at OWASP Ottawa discussing SSH security (gives perspective to this walkthrough).
At Reliza we are switching to using YubiKeys for our SSH authentication which is possible via PGP encryption. This guide is for Windows and using SSH via PuTTY. I found several nice references on the web (which are listed in the end) but all of them seemed to be missing a thing or two, so I decided this complete walkthrough for my future self and also for anyone interested. Note that I found this guide to be particularly good, but it’s missing few hiccups and description of proper PuTTY integration.
First of all, why do we need this? Answer is simple – Security! Alternatives include storing private keys directly on a workstation – which makes them poorly protected in multitude of attacks directed at workstation, a better option is to use encrypted usb key but this is tedious because leaving inserted and unsealed usb key for a long time is insecure, while inserting it and removing it back and forth all the time is tedious and time consuming.
YubiKey suits much better for this purpose. So let’s start.
1. Compatible hardware:
As listed on the YubiKey website, following products support PGP: YubiKey 4, YubiKey NEO, YubiKey 4 Nano, YubiKey NEO-n, YubiKey 5 NFC (this is what I’m using at the moment), YubiKey 5 Nano, YubiKey 4C, YubiKey 4C Nano, YubiKey 5C, YubiKey 5C Nano
Also it’s highly recommended to verify YubiKey before using it at https://www.yubico.com/genuine/
2. Software you’ll need on Windows:
Install the required software at this step.
3. Prepare the key:
First thing’s first: key comes with some simple factory pins: 123456 regular and 12345678 admin one. Since those are insecure, first we should change them.
For this, insert YubiKey into usb slot, fire up PowerShell and type
This will start gpg/card prompt, where now enter
admin , and then
The menu that appears and shown on the image is self-explanatory. I recommend changing both PIN, admin PIN and setting reset code. Requirements on PINs are as following:
Must be 6 to 8 characters,
Contain characters from three of the following four categories:
- English uppercase characters (A through Z)
- English lowercase characters (a through z)
- Base 10 digits (0 through 9)
- Nonalphanumeric characters (e.g., !, $, #, %)
For storing PIN, a password manager works best, I would particularly recommend hash-based “Master Password”.
4. Set up PGP key on Kleopatra / YubiKey:
There are various methods discussed how to proceed regarding PGP key generation with some authors suggesting generating keys on the host and then exporting to the YubiKey. But I firmly believe that a private key should always be generated on its target medium and not copied or exported around. Caveat – if YubiKey gets lost, key is lost, you’re cut off from the environment. For that purposes, have 2 (or more) YubiKeys, and store them separately. And make sure to have independent keys on each of those YubiKeys. Plus, if we are talking about SSH, there must be more than one admin user per environment. Bottom line – create redundancy, as always in DevOps.
Insert YubiKey into USB slot. In Kleopatra, go to Tools -> Manage Smartcards. This should open “Smartcard Management” screen. In the actions on the bottom click on “Generate new Keys”. Enter name and email and click ok. Choose if you want to backup encryption key (I uncheck it, since I have another YubiKey for redundancy). When promted, enter pin for the card. While generating keys, do mouse movements to generate extra randomness.
Click “Back” on the left of Smartcard Management, which will bring you to the list of certificates and keys. Observe that there is a new certificate now with keys stored on the card.
At this stage, double click this new certificate and click “Export…” on the bottom which will show Public PGP key. This Public key must be backed up and imported to every workstation from which you are going to ssh using YubiKey. Note that it’s possible to publish this certificate to a public URL which makes perfect sense for digital signing case, but I would prefer not to do it for the SSH case and have a separate YubiKey for the signing case.
5. Workaround for Windows custom ssh agent:
Some later versions of Windows 10 include custom ssh agent, which is discussed here. This overwrites ssh-pageant and prevents our stack from working. The workaround is to remove %SYSTEMROOT%\System32\OpenSSH\ from the path.
6. Configure Kleopatra and cygwin to allow SSH support:
In Kleopatra, click on Settings -> Configure Kleopatra. Select GnuPG System and go to Private Keys tab. Check “Enable ssh support” and “Enable putty support” and Apply settings.
In cygwin, add
eval $(/usr/bin/ssh-pageant -r -a "/tmp/.ssh-pageant-$USERNAME")
on startup (i.e. append to the end of ~/.bashrc file)
Note, that there are known glitches on Windows sometimes, for which case restart gpg agent in powershell, using:
gpg-connect-agent killagent /bye gpg-connect-agent /bye
7. Produce public key for authorized keys:
Now, it’s time to establish connection to the server. In cygwin, with YubiKey inserted, type
This will display public key block that should be added into ~/.ssh/authorized_key file on the target server.
8. Using PuTTY with YubiKey:
With inserted YubiKey, PuTTY would work out of the box with default settings, while prompting to enter PIN every first time you SSH after inserting YubiKey into usb.
If it doesn’t work, try the workaround supplied by YubiKey developers (already discussed previously):
gpg-connect-agent killagent /bye gpg-connect-agent /bye
9. Transfering access to another machine:
If you need to transfer access to another machine, make sure to import certificate exported in step 4 to Kleopatra on the new machine using File -> Import.
This will essentially replicate configuration present on the source machine.