GPG-sign your Git commits and remember your SSH key passwords in WSL2 including Yubikey PGP support
Tags: gpg, ssh, yubikey, wsl
Published: 2020-12-30 20:40:39

---
title: GPG-sign your Git commits and remember your SSH key passwords in WSL2 including Yubikey PGP support
published: true
description: GPG-sign your Git commits and remember your SSH key passwords in WSL2 including Yubikey PGP support
tags: gpg, ssh, yubikey, wsl
//cover_image: https://direct_url_to_image.jpg
canonical_url: https://snapcraft.ninja/2020/07/30/gpg-ssh-keys-in-wsl2-with-yubikeys/
---

This is a follow-up to my [WSL2 hack enabling Systemd](https://snapcraft.ninja/2020/07/29/systemd-snap-packages-wsl2/) to run enabling all the awesome features such as service management and session management. The session management enables most graphical or GUI applications in the WSL2 Distro to function without issue when combined with an appropriate Windows-based X11 server such as [X410](https://www.microsoft.com/store/productId/9NLP712ZMN9Q), [MobaXTerm](https://mobaxterm.mobatek.net/) or [VCXSRV](https://sourceforge.net/projects/vcxsrv/).

So, you're working away in your WSL2 distro and then you want to sign a GIT commit with your PGP key which is backed by a Hardware Security Module like a YubiKey. Or you want to SSH into a remote system using an SSH key that has a long and difficult to remember password. Both activities can be improved or enabled by using Windows-based "Agents". For PGP we can use GPG4Win's `gpg-agent` and for SSH we can use the SSH agent that is shipped with Windows.

## Installation

We only need to install GPG4Win, because Windows comes with the SSH Agent out of the box. So, to install GPG4Win we'll use winget. In a CMD or PowerShell window run:

```bat
winget.exe install gpg4win
```

## Loading your keys

Next we load your Private SSH or PGP keys or HSM-backed Public PGP keys into the Windows agents. For SSH keys this is easy; simply copy the keys to `C:\Users\<your-username>\.ssh\`.

For PGP keys, use the Start Menu to open Kleopatra. If you are using an HSM you only need the public key as a file or the fingerprint ID to lookup the public key on a key server. To import a file-based key select "File" and then "Import" (or press `ctrl+I`), locate your key file in the browser, and click "Open". To lookup a public key on a key server with the key ID select "File" and then "Lookup on server" (or press `ctrl+shift+I`). In the dialog that opens enter your key's fingerprint ID, click search, select the correct key from the list and finally click "Import".

## Ensuring the agents start automatically

For SSH Agent this is easy to do with PowerShell. Open the run dialog by pressing `win+r` and type powershell into the text box and finally pressing `ctrl+shift+enter` to start it in a privileged mode. Now we type the following into the PowerShell window and then you can close it because we're finished there:

```powershell
Set-Service ssh-agent -StartupType automatic
Start-Service ssh-agent
```

To start the GPG agent open a new unprivileged PowerShell window and run:

```powershell
& 'C:\Program Files (x86)\GnuPG\bin\gpg-connect-agent.exe' /bye
```

However, that only starts the agent once for your current session. To get it started every time you login you can open a privileged PowerShell like we did with the SSH agent above and run:

```powershell
Register-ScheduledJob -Name GPGAgent -Trigger (New-JobTrigger -AtLogOn) -RunNow -ScriptBlock {
    & "${env:ProgramFiles(x86)}/GnuPG/bin/gpg-connect-agent.exe" /bye
}
```

## Tying the agents to WSL2

First you need your Distro to have the [WSLUtilities](https://github.com/wslutilities/wslu) installed. On Ubuntu these are already present. Follow the steps on the linked GitHub page for your Distro.

Next, we need `socat` if it isn't already installed:

```bash
sudo apt update
sudo apt install -yyq socat
```

Now, place the following code into a file in your Distro at `/etc/profile.d/wsl2-ssh-gpg-agents.sh`. This presumes that your Distro automatically parses files in `/etc/profile.d`:

```bash
NPIPERELAY_URL="https://github.com/NZSmartie/npiperelay/releases/download/v0.1/npiperelay.exe"

if [ -n "$WSL_DISTRO_NAME" ]; then
    APPDATA="$(wslvar appdata)"
    APPDATA="${APPDATA//\\/\/}"
    NPIPERELAY_WIN="$APPDATA/wsl2-ssh-gpg-npiperelay.exe"
    NPIPERELAY="$(wslpath "$NPIPERELAY_WIN")"

    if [ ! -f "$NPIPERELAY" ]; then
        curl -L -q -o "$NPIPERELAY" "$NPIPERELAY_URL"
    fi
    #####
    ## Autorun for the gpg-relay bridge
    ##
    SOCAT_PID_FILE=$HOME/.gnupg/socat-gpg.pid
    SOCAT_PID_FILE2=$HOME/.gnupg/socat-gpg.pid.2

    for GPG_SOCK in "$HOME/.gnupg/S.gpg-agent" "/run/user/$UID/gnupg/S.gpg-agent"; do
        if ! ss -a | grep -q "$GPG_SOCK"; then
            rm -f "$GPG_SOCK"
            mkdir -p "$(dirname "$GPG_SOCK")"
            setsid --fork socat UNIX-LISTEN:"$GPG_SOCK",fork EXEC:"$NPIPERELAY -ei -ep -s -a "'"'"$APPDATA"/gnupg/S.gpg-agent'"',nofork
        fi
    done

    #####
    ## Autorun for the ssh-relay bridge
    ##
    export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock
    if ! ss -a | grep -q "$SSH_AUTH_SOCK"; then
        rm -f "$SSH_AUTH_SOCK"
        setsid --fork socat UNIX-LISTEN:"$SSH_AUTH_SOCK",fork EXEC:"$NPIPERELAY -ei -s //./pipe/openssh-ssh-agent",nofork
    fi
fi 
```

## Finishing up

You're done. Just restart your WSL2 session and you'll be able to use the GPG and SSH agents hosted on Windows from within the Linux environment. This also works for Yubikey-backed PGP keys!

I hope to return to this soon to automate the installation the way that Damion Gans did for the Systemd hack.