How to Use a Yubikey in WSL2 on Windows

/img/wsl2-yubikey/windows-bite.jpg

Windows now includes, natively, a subsystem that provides access to a real instance of Linux (by default Ubuntu). Access to a bash commandline, and Linux tools, can make some situations much easier. However, if you use a yubikey, or other hardware based authentication, it is not obvious how to utilise these within the Linux subsystem for ssh access to remote servers or github commits

This article is aimed at helping to get you setup in WSL2 with working yubikey gpg/ssh access.

Before we get started #

It is assumed that you already have a yubikey, and that you have your gpg/pgp keys setup and ready to go.

If this is not the case, there are a plethora of tutorials available to guide you through it. Please set it up and come back here once you are ready.

The yubikey must function for GPG and SSH in Windows #

Before we dive into the WSL2 environment, it is probably wise to check that the yubikey works in a Windows
environment as we would expect. Essentially, we are just creating a path for the yubikey to access authentication tools from Windows...so if your Yubikey doesn't work properly in Windows, it won't in WSL2 either.

If you are happy that all is well in Windows, then you can skip this section, otherwise make sure to follow the steps that follow.

Install GnuPG and PuTTY in Windows #

You should install GnuPG and PuTTY.

This will give you all the tools you need to successfully use a yubikey in Windows for SSH.

As part of the install for GnuPG you should have a program called Kleopatra. If you open this program and plug in your yubikey, you should be able to click on "Smartcards" in the interface, then click F5 on your keyboard, and it will display the info about the yubikey.

GPG Config file #

To enable SSH to work properly you will need to create a config file.

If we assume our username is "Dave" then the path to this file would be:

C:\Users\Dave\AppData\Roaming\gnupg\gpg-agent.conf

(Obviously change "Dave" to your own username on Windows in the path above)

The above mentioned file will likely not exist. If it doesn't, then just create a blank file, otherwise use the one that is already there.

Then you need to add to the file:

enable-putty-support
enable-ssh-support
default-cache-ttl 600
max-cache-ttl 7200

Ultimate trust for your public key #

Although potentially not essential to this process, it is probably a good idea to include this step.

Essentially we are going to give our public key ultimate trust. I am going to assume you can locate your own public key, from either your own location, or from a keyserver. Once you have located it you need it import it into Kleopatra, or on the commandline if you know how.

Now we are going to assign the key ultimate trust.

Open powershell and type gpg --card-status and you should see various information about your yubikey. If not, something is not working correctly, try rebooting and give it another go. If you still have issues try going through the steps above again.

The next command is gpg --list-keys. This will give you the gpg public key. The top two lines of the output will look something like this:

pub   rsa4096 2019-05-02 [SC]
  1CA87B39873495770098080098336BC4E5C445AB

The long string is your public key fingerprint, which you will need in the next step.

Type gpg --edit-key 1CA87B39873495770098080098336BC4E5C445AB this will bring up a gpg> prompt in which you should type "trust". It will then prompt you for a number. Enter "5", which is ultimate trust. Then confirm as instructed.

If you now go and check in Kleopatra or type gpg --list-keys in the commandline you will see your key has been assigned ultimate trust.

Final checks #

You should now be in a position where SSH works within windows.

Before we proceed, it would make sense to check you can actually use SSH within windows with your yubikey. Either use PuTTY to SSH into a server, or try to sign a git commit etc., and you should see that it is fully functional.

If this is not the case, then something is amiss, and there is no point proceeding to the next stage as it will not work.

One thing you can try is running in powershell the following:

gpgconf --kill gpg-agent
gpg-connect-agent /bye

This should restart gpg-agent so you can give it another shot.

WSL2 Setup #

Install WSL2 (Ubuntu) #

Firstly, install WSL2, which is as easy as running the following command in a powershell prompt with administrator privileges:

wsl --install

It will take you through the various install steps, restarts etc. It is very straight forward. You can install other distributions than Ubuntu, but by default Ubuntu is installed.

After the install you can search for Ubuntu in Windows search, and it will open for you.

If you ever need to properly close a WSL instance, type the following command into the terminal:

wsl.exe --shutdown

Just closing the window will not do this.

Initial steps #

Make sure you are up to date:

sudo apt update
sudo apt upgrade

Run the following commands (change the wsl2-ssh-pageant version number in the download link as appropriate):

sudo apt install socat
mkdir ~/.ssh
wget https://github.com/BlackReloaded/wsl2-ssh-pageant/releases/download/v1.4.0/wsl2-ssh-pageant.exe -O ~/.ssh/wsl2-ssh-pageant.exe
chmod +x ~/.ssh/wsl2-ssh-pageant.exe

Edit bash-rc #

Append the following to your ~/.bashrc file (use nano, vim etc.):

# SSH Socket
# Removing Linux SSH socket and replacing it by link to wsl2-ssh-pageant socket
export SSH_AUTH_SOCK="$HOME/.ssh/agent.sock"
if ! ss -a | grep -q "$SSH_AUTH_SOCK"; then
  rm -f "$SSH_AUTH_SOCK"
  wsl2_ssh_pageant_bin="$HOME/.ssh/wsl2-ssh-pageant.exe"
  if test -x "$wsl2_ssh_pageant_bin"; then
    (setsid nohup socat UNIX-LISTEN:"$SSH_AUTH_SOCK,fork" EXEC:"$wsl2_ssh_pageant_bin">/dev/null 2>&1 &)
  else
    echo >&2 "WARNING: $wsl2_ssh_pageant_bin is not executable."
  fi
  unset wsl2_ssh_pageant_bin
fi
# GPG Socket
# Removing Linux GPG Agent socket and replacing it by link to wsl2-ssh-pageant GPG socket
# NOTE: the "config_path" and "-gpgConfigBasepath ${config_path}" are generally needed for
# gpg4win 4.0 and later 
export GPG_AGENT_SOCK="$HOME/.gnupg/S.gpg-agent"
if ! ss -a | grep -q "$GPG_AGENT_SOCK"; then
  rm -rf "$GPG_AGENT_SOCK"
  wsl2_ssh_pageant_bin="$HOME/.ssh/wsl2-ssh-pageant.exe"
  config_path="C\:/Users/<username>/AppData/Local/gnupg" # replace <username> with your own username
  if test -x "$wsl2_ssh_pageant_bin"; then
    (setsid nohup socat UNIX-LISTEN:"$GPG_AGENT_SOCK,fork" EXEC:"$wsl2_ssh_pageant_bin -gpgConfigBasepath ${config_path} --gpg S.gpg-agent" >/dev/null 2>&1 &)
  else
    echo >&2 "WARNING: $wsl2_ssh_pageant_bin is not executable."
  fi
  unset wsl2_ssh_pageant_bin
fi

Now restart WSL2:

wsl.exe --shutdown

You should now have access to your Yubikey in WSL2:

Try gpg --card-status in WSL2 and you should get info about your yubikey. If not something is wrong. Try going through the steps again.

It should also be possible to use SSH. For example ssh-add -L should return a key.

Change key trustworthiness to ultimate #

This is the same thing we did previously in windows, except we will do it on the commandline (obviously use your own key):

$ gpg --edit-key 1CA87B39873495770098080098336BC4E5C445AB
gpg> trust
Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
gpg> quit

If you now run gpg --list-keys the keys should have ultimate trust.

Done! #

That should be it. You should be able to SSH into a server or use git commits etc.

Visual Studio Code #

One of the things you may want to do is use a text editor/IDE rather than using VIM or Nano on the commandline. This is certainly preferable if you are a software developer and need to edit lots of text files.

Fortunately, you can easily use a program such as VS Code for this.

How to use VS Code in WSL2 #

You do not need to install VS Code within the WSL2 Ubuntu install. You only need VS Code installed in windows as normal.

On the commandline in WSL2 just type the following:

code .

The dot is quite important so don't forget that!

It will then open a VS Code instance with the path of where you are in the terminal, so maybe "cd" to your project root path first before running it.

It is quite well intergrated so if for example you are running a python virtual environment, it will pick this up and allow you to select the virtual environment that exists within Ubuntu. This greatly helps with general work, and debugging.

References #

The main place that the info in this article comes from is here:

Jaroslav Živný

You can also refer to the information provided by the wsl2-ssh-pageant tools author on github:

wsl2-ssh-pageant

🙏🙏🙏

Since you've made it this far, sharing this article on your favorite social media network would be highly appreciated. For feedback, please ping me on Twitter.

...or if you want fuel my next article, you could always:

Buy Me a Coffee at ko-fi.com

Published