GnuGP SSH Authentication with Yubikey and PuTTY

This configuration documentation assumes that the client is a Windows 10 PC, with gpg4win installed and functional and the server is a Linux host running OpenSSH. I am sure that other versions and platforms will work with the same configuration. In my case I am using a Raspberry Pi with SSH enabled as the ‘Linux host’ and my Windows 10 Laptop as my ‘Windows 10 PC’ running PuTTY version.

IMPORTANT NOTE: This is not a step-by-step tutorial, it is a configuration guide and it assumes you have IT skills. Also ignore the best practices that I am not following in this document. The primary goal is to have enough information here to setup the SSH Authentication with GunPG and a YubiKey using PuTTY on Windows.

Configuration Files edited

Linux host

  • /etc/ssh/sshd_config
  • /home/userid/.ssh (Permissions 700 on this directory)
  • /home/userid/.ssh/authorized_keys (Permissions 600 on this file)

Windows 10 PC (these configuration files you may need to create)

  • %APPDATA%/gnupg/gpg-agent.conf
  • %APPDATA%/gnupg/sshcontrol
  • %APPDATA%/gnupg/scdaemon.conf

IMPORTANT NOTE: All windows files should only be edited in WordPad or a text editor that handles end of line characters correctly. I spent many hours debugging issues that all resulted in the fact I was using Windows Notepad as my editor. Do not use Windows notepad when editing the GnuPG files. Additionally, always leave one extra blank space at the end of the configuration files. If the last configuration line item does not have a end of line character then GnuPG may not read that configuration line item.

Configuration on the Linux Host

Ensure the following lines are either added or not commented out in the SSHD configuration file (/etc/ssh/sshd_config)

PubkeyAuthentication    yes
AuthorizedKeysFile      %h/.ssh/authorized_keys 

These config line items do two things. First it will enable public key authentication. Second it will set the default location of the file where you will place your authorized public SSH keys. If you need to edit this file to add the above lines, ensure you restart the SSH daemon (/etc/init.d/ssh restart). Of course both editing this file as well as restarting the SSH daemon will require root privileges.

Next, setup your user profile. In the example below we are using the default ‘pi’ user that comes with a Raspberry pi. First create the ‘.ssh’ directory with 700 user permissions, and then create the ‘.ssh/authorized_keys’ file that will be used to put your public GnuPG authentication key for SSH authentication.

pi@ct-pi:~ $ mkdir .ssh
pi@ct-pi:~ $ chmod 700 .ssh
pi@ct-pi:~ $ touch .ssh/authorized_keys
pi@ct-pi:~ $ chmod 600 .ssh/authorized_keys

Lastly edit your ‘.ssh/authorized_keys’ file and paste in your GnuPG authentication key that was created with the ‘gpg –export-ssh-key’ command. This command is not issued on this Linux Host, but the host that has access to your GnuPG private key – in this case the Windows Host

Configuration on the Windows 10 PC

Make sure that both GnuPG and Putty are both installed and functioning. Before doing to much on the key generation side and all that fun stuff you will first need to ensure that GnuPG recognizes your Yubikey as a smart card. For me that was done by (creating or) editing the ‘%APPDATA%/gnupg/scdaemon.conf’ file and adding the following configuration line. You can also use the GUI to add this line in. Either works.

reader-port Yubico YubiKey

I think the reader-port can be different for different types of YubiKeys, but for the Yubikey 5 NFC that I have this is the correct line item. PLEASE NOTE my important note at the top of this page: Edit all windows GnuPG files using a text editor like WordPad that handles end of line characters correctly. Never use Notepad, and always leave a blank line on the bottom of the file.

Next, Edit (or create) the gpg-agent configuration file ‘%APPDATA%/gnupg/gpg-agent.conf’ and add the following two lines

enable-putty-support
enable-ssh-support

Again, no NotePad and make sure you hit that enter key after the last line! Once the above two files has been edited restart all GnuPG services.

GnuPG key generation

Okay lets generate the GnuPG keys, move the private keys to the Yubikey, and distribute the public key to our SSH Server. There are also lots of excellent guides out there to do this, such as the one I just linked as well as this one.

There are two main ways to do the key generation, one is generate the private key on the local computer (the windows machine in this case), or you can generate it directly on the Yubikey. I decided to generate the key on a computer for the sole reason that I can then backup the private keys (In my case I backed it up to a USB and stored it in a safe location). If the private key is generated on the YubiKey, and the YubiKey gets lost, stolen or damaged then its gone. Not good. Now if you want to be super duper secure, AND have a backup, use a computer that has never been connected to a network (I.E. a live CD, new virtual machine, etc.) to do your key generation. So, lets move on – Key Generation

Again, I am not going to go into best practices for key management as that is not the goal of this documentation so I will assume you have all your keys generated at this time. Again, if help is needed here find some good reference documentation on the internet like that one and this one.

Move the private keys to the YubiKey

One thing I will go over here is how to move the private authentication key over to our YubiKey. I personally moved over a signing, authentication and an encryption key to the YubiKey – but again I will not get into that as this is not the purpose of this document. Before we do this make sure you have a good backup of your private keys this moves them, not copies them, to the Yubikey. Run the GPG command seen below with your key fingerprint. Once at the GnuPG prompt select the authentication key (the command is key 2), then use the the keytocard command to move it over to the YubiKey. Select option 3 (Authentication key) when it asks. When you are done and back at the gpg prompt use the save command again like above.

C:\Users\myuserid>gpg --expert --edit-key 30F0BD6A923076A7F39542C93FDFCD24C30D1D53
 gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
 This is free software: you are free to change and redistribute it.
 There is NO WARRANTY, to the extent permitted by law.
 Secret key is available.
 sec  rsa2048/3FDFCD24C30D1D53
      created: 2020-01-10  expires: never       usage: SC
      trust: ultimate      validity: ultimate
 ssb  rsa2048/02F104CCA306E0FB
      created: 2020-01-10  expires: never       usage: E
 ssb  rsa4096/2154216119BA20EF
      created: 2020-01-10  expires: never       usage: A
 ultimate. temporary
 gpg> key 2
 sec  rsa2048/3FDFCD24C30D1D53
      created: 2020-01-10  expires: never       usage: SC
      trust: ultimate      validity: ultimate
 ssb  rsa2048/02F104CCA306E0FB
      created: 2020-01-10  expires: never       usage: E
 ssb* rsa4096/2154216119BA20EF
      created: 2020-01-10  expires: never       usage: A
 ultimate. temporary
 gpg> keytocard
 Please select where to store the key:
    (3) Authentication key
 Your selection? 3

I do not have the full output above as I did not want to overwrite my Yubikey so I stopped. But turst me it works. It will ask for the Admin PIN of the YubiKey. The default Admin PIN is 12345678 (you should change this! And for what it is worth the default (non-ADMIN) pin is 123456 – again, change this)

Distribute the Keys

There are a few things we now need to do: Update the list of keys that can be used for SSHing, start the gpg-agent (putty uses this) and then copy the public GnuPG SSH authentication key to our linux server.

First lets generate all the information we need to distribute.

C:\Users\myuserid>gpg -k --with-keygrip
 C:/Users/myuserid/AppData/Roaming/gnupg/pubring.kbx

 pub   rsa2048 2020-01-10 [SC]
       30F0BD6A923076A7F39542C93FDFCD24C30D1D53
       Keygrip = 5DC92A12A8537AF1DACA650F15395518EA2E3EA2
 uid           [ultimate] temporary
 sub   rsa2048 2020-01-10 [E]
       Keygrip = 98A4FC648EB6F8731AFBDC3A3221B8F14F30D685
 sub   rsa4096 2020-01-10 [A]
       Keygrip = B51A5EC70A47318365AB5E532FA2D6A9882EAB87

 C:\Users\myuserid>gpg --export-ssh-key 30F0BD6A923076A7F39542C93FDFCD24C30D1D53

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDbq3KG/lgpuPtIz0ipCKxd3+iH6mGDjc8v1Mvr3zJy1V8zc44o9lQmkAJq7MHxegHwybOD17BF80YlpcaxCGwlUuWnnRtqr4GELAJ7SDPd5fPbkK/9rKea37JJMmcik6YpeqZ23plQrkTS5m1rvOcxKRwHXxNoJVqpLaRSQSAd19dV/a6Y8lFSddPhTABxUX20kLhfkEg6LRmdNg/aYDIy7Q7D7I3/t2+j0L/WPd4JZG8lWJ7LhMYMFCPWVIPGE47xg2kwh/zkfIYvs3EZqpWYXegoAkuY/D/yyVg9UWE3Mn9Uf+KIAS37Y0JhJ+zSks2kBYxyrGxbA1zR9bFzVLsrxWXp0QdLvXSBbn/Es6tXaTWXpeHQ8EvyUDbMVlXXy0gpjuSfiR80hXSeOWOIfyJwDYNSG8KQiAHpSk3uhxI2leFOG9XoKnqlVJih9DBL8iorJhpfOJBDfTaj2YJ4qNd0DxfNjAiyCYOXGNfIui/4v/Da/HsBMk5vMcyRrtiEPYUUuta7UDbsPZtSb/AH6tM0AtPVZToIBlUvishyn1+7kvB/ByRWNCOvT0FazoOMcL4TRTqARAjplgBSYOQ+rlcQrfx0plC1pVme2coxrNCpy89CVi/SPk79kQ1qUqT/XSBJ/8iRFRogO/YQWl68cASIBkrEumZcHanDYF1q1CMwqQ== openpgp:0x19BA20EF

Edit the ‘%APPDATA%/gnupg/sshcontrol’ file (again, not in Notepad, I cannot say this enough) and add your “KeyGrip” for your authentication key. So the file in my example looks like:

# List of allowed ssh keys.  Only keys present in this file are used
# in the SSH protocol.  The ssh-add tool may add new entries to this
# file to enable them; you may also add them manually.  Comment
# lines, like this one, as well as empty lines are ignored.  Lines do
# have a certain length limit but this is not serious limitation as
# the format of the entries is fixed and checked by gpg-agent. A
# non-comment line starts with optional white spaces, followed by the
# keygrip of the key given as 40 hex digits, optionally followed by a
# caching TTL in seconds, and another optional field for arbitrary
# flags.   Prepend the keygrip with an '!' mark to disable it.
B51A5EC70A47318365AB5E532FA2D6A9882EAB87

Do not forget to add that extra blank line at the bottom!

Restart all your GnuPG services at this point (just to be sure these files are loaded). Now start start the gpg-agent (its a pagent replacement that PuTTY leverages) by issuing the command “gpg-connect-agent /bye” at a command prompt. If you are troubleshooting and need to restart it issue a “gpg-connect-agent KILLAGENT /bye” followed by a “gpg-connect-agent /bye”.

FINAL THING TO DO

The output of the ‘gpg –export-ssh-key ‘ command above needs to be copied into that autorized_keys files on the Linux host. So in this example the /home/userid/.ssh/authorized_keys file would have a line that looks like this.. Note this is all one line in the file.

 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDbq3KG/lgpuPtIz0ipCKxd3+iH6mGDjc8v1Mvr3zJy1V8zc44o9lQmkAJq7MHxegHwybOD17BF80YlpcaxCGwlUuWnnRtqr4GELAJ7SDPd5fPbkK/9rKea37JJMmcik6YpeqZ23plQrkTS5m1rvOcxKRwHXxNoJVqpLaRSQSAd19dV/a6Y8lFSddPhTABxUX20kLhfkEg6LRmdNg/aYDIy7Q7D7I3/t2+j0L/WPd4JZG8lWJ7LhMYMFCPWVIPGE47xg2kwh/zkfIYvs3EZqpWYXegoAkuY/D/yyVg9UWE3Mn9Uf+KIAS37Y0JhJ+zSks2kBYxyrGxbA1zR9bFzVLsrxWXp0QdLvXSBbn/Es6tXaTWXpeHQ8EvyUDbMVlXXy0gpjuSfiR80hXSeOWOIfyJwDYNSG8KQiAHpSk3uhxI2leFOG9XoKnqlVJih9DBL8iorJhpfOJBDfTaj2YJ4qNd0DxfNjAiyCYOXGNfIui/4v/Da/HsBMk5vMcyRrtiEPYUUuta7UDbsPZtSb/AH6tM0AtPVZToIBlUvishyn1+7kvB/ByRWNCOvT0FazoOMcL4TRTqARAjplgBSYOQ+rlcQrfx0plC1pVme2coxrNCpy89CVi/SPk79kQ1qUqT/XSBJ/8iRFRogO/YQWl68cASIBkrEumZcHanDYF1q1CMwqQ== openpgp:0x19BA20EF 

Final thoughts

  • Notepad sucks, do not use it. I am sure Notepad++ would have worked fine – but as I said in this document WordPad did the trick too.
  • I did not cover in depth, at all, proper key management. Backup your keys, and generate them securely.
  • You may, like me, want to create a startup script for gpg-connect-agent to start on login. I did not cover this in the document.
  • I noticed after-the-fact that I mention to use 4096 bit’s in my key, but in the example output it shows I used 2048. My bad.
  • Once you get this working you may wish to disable passwords via SSH and only allow keys. If you do this make sure your keys are properly backed up and/or you have console access to your SSH host.
  • Please let me know if this information helped you in any way