2022-03-23
YubiKey resident SSH keys on Windows+WSL
This is a guide that documents how to use YubiKey resident SSH keys on Windows, with passthrough to WSL2 via npiperelay
and socat
.
It’s important to understand that with this setup, WSL is using the ssh-agent service running on Windows, not WSL. However, because of the magic of Unix pipes+sockets, you shouldn’t notice any functional differences.
Download OpenSSH
As of writing, OpenSSH 8.1p1 (the default on Windows 10), does not support importing resident SSH keys from YubiKeys via ssh-add
or ssh-keygen
. So first we need to update OpenSSH for Windows:
- Download the latest .zip from the Win32-OpenSSH GitHub releases page. (OpenSSH-Win64.zip in my case).
- Unzip it, and run the
install-sshd.ps1
script as Administrator.
This script will update the appropriate Windows system services (sshd
and ssh-agent
) to use the executables in the current directory instead of the default ones. The script will not, however install the the executables into your PATH (of which ssh-add
and ssh-keygen
we’ll need later on) so remember where you’ve unzipped it.
Next restart the ssh-agent
Windows service:
- Open
services.msc
from Run (Win+R
). - Find “OpenSSH Authentication Agent”, right click and select “Restart”.
Configuring WSL2
Install
socat
using your package manager (e.g.sudo apt install socat
).Download the latest npiperelay from the GitHub releases page. Unzip it, and copy npiperelay.exe to somewhere in your WSL’s
$PATH
(~/bin/npiperelay.exe
in my case).In your
~/.profile
, or~/.bashrc
shell startup script add the following (adapted from thewsl-ssh-agent
README):export NPIPE_CMD=$(command -v npiperelay.exe) export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock # setup socat ss -a | grep -q $SSH_AUTH_SOCK if [ "$?" -ne "0" ]; then rm -f $SSH_AUTH_SOCK ( setsid socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"$NPIPE_CMD -ei -s //./pipe/openssh-ssh-agent",nofork & ) >/dev/null 2>&1 fi # add your ssh private key paths here ... ssh-add ~/.ssh/id_ed25519 ~/.ssh/id_rsa
Importing resident SSH keys
Importing resident ssh private keys from the YubiKey via ssh-keygen -K
isn’t supported on the default version of OpenSSH installed on Windows 10. However, we can make use of the updated binaries we downloaded previously, which do support importing resident ssh keys:
- Open a privileged Administrator PowerShell window. It must be a privileged PowerShell window, otherwise it will fail with an “invalid format” error.
cd
to the directory the previously downloaded OpenSSH binaries reside (the path I told you to keep a not of).- Run
.\ssh-keygen -K
, and follow the prompts:
There is another method that requires a second device running anything that isn’t Windows (Linux, *BSD, etc). I did this way before realising I could use the updated ssh-keygen
binary:
- Import the resident keys to a file;
ssh-keygen -K -f ./id_ed25519_sk
, (make sure to set a password). - Either copy the resulting file to a USB drive, or upload it somewhere private (this is, after all, your private key).
- Copy/download the file onto your Windows machine, and add it to the authentication agent via
ssh-add c:\path\to\file
.
Adding keys to the agent
Adding keys to the agent is fairly simple, whether in WSL or Windows. Just use the ssh-add
command.
In WSL2:
$ ssh-add /path/to/file
In Windows (PowerShell):
PS C:\Windows\system32> ssh-add C:\path\to\file
Automating
If like me you have named your SSH keys in a non-standard way, or for some other reason ssh-agent won’t load your keys on startup, we can write a simple PowerShell one-liner that runs at login:
C:\Users\zzz\Documents\bin\OpenSSH-Win64\ssh-add.exe "$env:USERPROFILE\.ssh\id_yubikey" "$env:USERPROFILE\.ssh\id_something_nonstandard"
You will need to replace C:\Users\zzz\Documents\bin\OpenSSH-Win64\
with the path to where you unzipped Win32-OpenSSH previously (hope you didn’t forget!).
Save this script as ssh-keys.ps1
in: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
, and it should run at startup, prompting you for a password in a PowerShell window if your keys are password protected.
Similarly, for adding the private keys in WSL2 you can add a ssh-add /path/to/key1 /path/to/key1
line to your shell rc.