title: WSLでYubikeyを使う
author: Amane Katagiri
summary: my new gear...
date: 2020-07-23T20:12:00+09:00
modified: 2024-02-09T14:48:00+09:00
category: tech
license: CC BY 4.0
og_image: images/yubikey-on-wsl/og.png
rating: sfw
ai_summary: この記事は、WSL1環境でYubikeyをOpenPGPスマートカードとして使用するための設定手順を解説しています。Windows側のgpg-agentとWSL側のソケットをnpiperelayやsocat、wsl-ssh-pageantを用いて連携させることで、WSL上でのGPG操作やSSH認証を可能にします。WSL2とは手順が異なる点に注意を促しつつ、必要なツールの導入から自動起動設定までを詳述しています。
ai_keywords: WSL1, Yubikey, GnuPG, npiperelay, socat, wsl-ssh-pageant, OpenPGP, SSH認証, スマートカード, gpg-agent

/\* この記事ではWSL1（無印）向けの設定手順を記載しており、WSL2では一部または全部の機能が動作しません。最新情報は[WSL2でYubikeyを使う](/post/yubikey-on-wsl2)をお読みください。 \*/

[TOC]

# 概要

![WSLからYubikeyを使う方法について、WSL→WSLのGnuPG→socat→npiperelay→Windowsのgpg-agent→scdaemon→Yubikey、またはssh→ssh-agent→wsl-ssh-pagent→Windowsのgpg-agent→scdaemon→Yubikeyという流れで接続できることを示す図（記事では触れないが、RemoteFXを通すとリモートデスクトップの接続先からでもYubiKeyを使用できることを提示）](/images/yubikey-on-wsl/tldr.png){width=700 height=525}

## before

```shell-session
amane@yakumo:~$ gpg --card-status
gpg: error getting version from 'scdaemon': No SmartCard daemon
gpg: OpenPGP card not available: No SmartCard daemon
amane@yakumo:~$ ssh git@github.com
git@github.com: Permission denied (publickey).
```

かなしいね。

## after

```shell-session
amane@yakumo:~$ gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 0
Application ID ...: ********************************
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: ********************************
Name of cardholder: Amane Katagiri
Language prefs ...: ja
Sex ..............: female
URL of public key : https://keybase.io/amane/pgp_keys.asc
Login data .......: amane
Signature PIN ....: forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: **** **** **** **** ****  **** **** **** **** ****
      created ....: 1970-01-01 00:00:00
Encryption key....: **** **** **** **** ****  **** **** **** **** ****
      created ....: 1970-01-01 00:00:00
Authentication key: **** **** **** **** ****  **** **** **** **** ****
      created ....: 1970-01-01 00:00:00
General key info..: [none]
amane@yakumo:~$ ssh git@github.com
PTY allocation request failed on channel 0
Hi amane-katagiri! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
```

なるほどね。

# 前提

## Yubikey

今回は[PIV](https://www.yubico.com/authentication-standards/smart-card/)ではなく、[OpenPGP](https://support.yubico.com/hc/en-us/articles/360013790259-Using-Your-YubiKey-with-OpenPGP)コンパチブルなスマートカードとして使用します。鍵のセットアップは各自で済ませてください。

最近やっと2本目を買ったのですが、なんか[ed25519が使えるようになってて](https://support.yubico.com/hc/en-us/articles/360016649139-YubiKey-5-2-3-Enhancements-to-OpenPGP-3-4-Support)よかったです。やっぱり2020は最高ですね。

## WSL

![winverで表示したWindowsのバージョン情報（Windows 10, バージョン 1909, OSビルド 18363.900）](/images/yubikey-on-wsl/winver.png){width=536 height=472}

```shell-session
amane@yakumo:~$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
amane@yakumo:~$ uname -a
Linux yakumo 4.4.0-18362-Microsoft #836-Microsoft Mon May 05 16:04:00 PST 2020 x86_64 GNU/Linux
```

# 準備

## gpg

Yubikeyをgpg-agent経由で引き渡す必要があるので、両方にインストールしてください。

### on WSL

```shell-session
amane@yakumo:~$ sudo apt update && sudo apt install -y gpg
amane@yakumo:~$ gpg --version
gpg (GnuPG) 2.2.12
```

### on Windows

[https://www.gpg4win.org/get-gpg4win.html](https://www.gpg4win.org/get-gpg4win.html):
![Gpg4winのダウンロード画面](/images/yubikey-on-wsl/gpg4win_download.png){width=655 height=547}

他のコンポーネントは入れても入れなくてもいいです:
![Gpg4winのインストーラ画面でGnuPG以外のコンポーネントのチェックを外した様子](/images/yubikey-on-wsl/gpg4win_install.png){width=499 height=388}

えっ:

```doscon
C:\Users\amane>gpg --card-status
gpg: selecting card failed: No such device
gpg: OpenPGPカードが利用できません: No such device
```

カードリーダーが複数あると *最初の* デバイス[^first-device]を見に行くらしいので、`%APPDATA%\gnupg\scdaemon.conf`に追記するといい:

[^first-device]: `certutil -scinfo`あたりの順番なのかな。

```text
reader-port Yubico
```

そっか:

```doscon
C:\Users\amane>gpgconf --reload scdaemon

C:\Users\amane>gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 0
Application ID ...: ********************************
Application type .: OpenPGP
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: ********************************
Name of cardholder: Amane Katagiri
Language prefs ...: ja
Salutation .......: Ms.
URL of public key : https://keybase.io/amane/pgp_keys.asc
Login data .......: amane
Signature PIN ....: 強制
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: **** **** **** **** ****  **** **** **** **** ****
      created ....: 1970-01-01 00:00:00
Encryption key....: **** **** **** **** ****  **** **** **** **** ****
      created ....: 1970-01-01 00:00:00
Authentication key: **** **** **** **** ****  **** **** **** **** ****
      created ....: 1970-01-01 00:00:00
General key info..: [none]
```

後で使うので`%APPDATA%\gnupg\gpg-agent.conf`に追記してください:

```text
enable-ssh-support
enable-putty-support
```

## npiperelay

> npiperelay is a tool that allows you to access a Windows named pipe in a way that is more compatible with a variety of command-line tools.
> ["""NZSmartie/npiperelay"""](https://github.com/NZSmartie/npiperelay)

Windowsの名前付きパイプをよしなにUNIXソケットにリレーする。GnuPGが使う[libassuan](https://gnupg.org/software/libassuan/index.html)向けのサポートつき。

[npiperelay.exe](https://github.com/NZSmartie/npiperelay/releases/download/v0.1/npiperelay.exe)を`%HOMEDRIVE%%HOMEPATH%\go\bin`あたりに置いてください。

## wsl-ssh-pageant

> GPG on Windows exposes a Pageant style SSH agent and I wanted a way to use this key within WSL.
> ["""benpye/wsl-ssh-pageant"""](https://github.com/benpye/wsl-ssh-pageant)

PageantをよしなにUNIXソケットにリレーする。どうしてもgpg-agent経由でsshできなかったので入れました。

[wsl-ssh-pageant-amd64.exe](https://github.com/benpye/wsl-ssh-pageant/releases/download/20200408.1/wsl-ssh-pageant-amd64.exe)も`%HOMEDRIVE%%HOMEPATH%\go\bin`あたりに置いてください。

## socat

> Multipurpose relay (SOcket CAT)
> ["""socat(1)"""](https://linux.die.net/man/1/socat)

npipereleyでよしなにしたgpg-agentのソケットを、WSL側のgpg-agentのソケットにつなぐ。

WSLでインストールしてください:

```shell-session
amane@yakumo:~$ sudo apt update && sudo apt install -y socat
amane@yakumo:~$ socat -V
socat by Gerhard Rieger and contributors - see www.dest-unreach.org
socat version 1.7.3.2 on Nov 19 2017 13:56:10
```

# 起動

## on Windows

適当にバッチファイルとして置いてください:

```bat
gpg-connect-agent reloadagent /bye > nul 2>&1

if exist %HOMEDRIVE%%HOMEPATH%\ssh-agent.sock del %HOMEDRIVE%%HOMEPATH%\ssh-agent.sock
%HOMEDRIVE%%HOMEPATH%\go\bin\wsl-ssh-pageant-amd64.exe --systray --wsl %HOMEDRIVE%%HOMEPATH%\ssh-agent.sock
```

タスクスケジューラからVBScript経由で呼び出すと *かわいい* かもしれないです:

```vbscript
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c C:\path\to\start-agent.bat", vbhide
```

## on WSL

`.bashrc`などに追記してください:

```sh
WIN_USERNAME="amane"

GO_BIN_DIR="/mnt/c/Users/${WIN_USERNAME}/go/bin"
WIN_GPG_DIR="C:/Users/${WIN_USERNAME}/AppData/Local/gnupg"
WIN_HOME_DIR="/mnt/c/Users/${WIN_USERNAME}"
WSL_GPG_DIR="$(gpgconf --list-dirs socketdir)"

if ! pgrep -f 'socat.*gpg-agent.*npiperelay' >/dev/null; then
  rm -f "${WSL_GPG_DIR}/S.gpg-agent"
  setsid nohup socat \
    UNIX-LISTEN:"${WSL_GPG_DIR}/S.gpg-agent,fork" \
    EXEC:"${GO_BIN_DIR}"'/npiperelay.exe -ei -ep -s -a "'"${WIN_GPG_DIR}"'/S.gpg-agent",nofork' >/dev/null 2>&1 &
fi
export SSH_AUTH_SOCK="${WIN_HOME_DIR}/ssh-agent.sock"
```

PIDとかを記録すれば、もっと丁寧に二重起動を回避できますね。

++(2020-07-25) スクリプトを *かわいく* する際にミスがあり、そのまま使用すると動作しなかったため修正しました。++

```diff
- WIN_GPG_DIR="/mnt/c/Users/${WIN_USERNAME}/AppData/Roaming/gnupg"
+ WIN_GPG_DIR="C:/Users/${WIN_USERNAME}/AppData/Roaming/gnupg"
```

++(2023-09-04) GPGのバージョンアップに伴う動作ディレクトリの修正を適用しました。++

```diff
- WIN_GPG_DIR="C:/Users/${WIN_USERNAME}/AppData/Roaming/gnupg"
+ WIN_GPG_DIR="C:/Users/${WIN_USERNAME}/AppData/Local/gnupg"
```

++(2024-02-09) ソケットの配置ディレクトリを決め打ちしないようにしました。++

```diff
+WSL_GPG_DIR="$(gpgconf --list-dirs socketdir)"

 if ! pgrep -f 'socat.*gpg-agent.*npiperelay' >/dev/null; then
-  rm -f "${HOME}/.gnupg/S.gpg-agent"
+  rm -f "${WSL_GPG_DIR}/S.gpg-agent"
   setsid nohup socat \
-    UNIX-LISTEN:"$HOME/.gnupg/S.gpg-agent,fork" \
+    UNIX-LISTEN:"${WSL_GPG_DIR}/S.gpg-agent,fork" \
```

# on WSL2

/\* [WSL2でYubikeyを使う](/post/yubikey-on-wsl2)を参照してください。 \*/

# この記事の生い立ち

[ThinkPad X13 Yoga Gen 1](https://www.lenovo.com/jp/ja/notebooks/thinkpad/x-series/ThinkPad-X13-Yoga/p/22TPX13X3Y1)が届いたので、インストール手順をまとめました。今回はデュアルブートなんてせずにゲームや動画を楽しめるといいですね。

最近やりました:

* [Helltaker](https://store.steampowered.com/app/1289310/Helltaker/)
* [魔法の女子高生](https://store.steampowered.com/app/555630/A_Magical_High_School_Girl/?l=japanese)

とりあえずWSL2を使えばそれで終わりだと思うので、終わりです。

# 参考

* [Using a Yubikey for GPG in WSL (Windows Subsystem for Linux) on Windows 10](https://justyn.io/blog/using-a-yubikey-for-gpg-in-wsl-windows-subsystem-for-linux-on-windows-10/)
* [SSH on Windows with private key on Yubikey](https://www.antirandom.com/2020/03/ssh-on-windows-with-private-key-on-yubikey/)
* [How to use GPG with YubiKey (bonus: WSL)](https://codingnest.com/how-to-use-gpg-with-yubikey-wsl/)
