WindowsでYubikey5を使ってみる

前提条件

GPGキーを作成し、Yubikeyに移動させた状態とする。

まだの場合は以下を参照してください。 akashisn.hatenablog.com akashisn.hatenablog.com

環境

  • Windows 10 Pro (20H2 - 19042.685)

Gpg4winのインストール

www.gpg4win.org

https://files.gpg4win.org/ から最新版をダウンロードする。

KleopatraGpgEX にチェックを入れてインストールする。

gpg4win install option

text.baldanders.info

  • Kleopatra は GnuPGGUI ラッパーで OpenPGP 鍵および X.509 電子証明書の管理を行う。
  • GpgEX は Windows Explorer拡張機能で, Explorer 上からファイルの暗号化や復号を行うことができる。 個人的に GpgEX はかなり使い勝手がいいのでお勧めである。

公開鍵のインポート

公開鍵のエクスポート でエクスポートした公開鍵をインポートする。

> gpg --import .\gpg-BF8A708B020A19BB-2020-12-09.txt
gpg: 鍵BF8A708B020A19BB: 公開鍵"<名前> <メールアドレス>"をインポートしました
gpg:           処理数の合計: 1
gpg:             インポート: 1

インポートした公開鍵を究極的に信用する(自分の物のため)。

trust -> 5 -> y と入力する。

> gpg --edit-key BF8A708B020A19BB
gpg (GnuPG) 2.2.25; Copyright (C) 2020 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


pub  nistp521/BF8A708B020A19BB
     作成: 2020-12-09  有効期限: 無期限      利用法: C
     信用: 不明の        有効性: 不明の
sub  nistp521/983982062E1BB33D
     作成: 2020-12-09  有効期限: 無期限      利用法: S
sub  nistp521/008734F36B087C1C
     作成: 2020-12-09  有効期限: 無期限      利用法: E
sub  nistp521/26BAE38657860920
     作成: 2020-12-09  有効期限: 無期限      利用法: A
[  不明  ] (1). <名前> <メールアドレス>

gpg> trust
pub  nistp521/BF8A708B020A19BB
     作成: 2020-12-09  有効期限: 無期限      利用法: C
     信用: 不明の        有効性: 不明の
sub  nistp521/983982062E1BB33D
     作成: 2020-12-09  有効期限: 無期限      利用法: S
sub  nistp521/008734F36B087C1C
     作成: 2020-12-09  有効期限: 無期限      利用法: E
sub  nistp521/26BAE38657860920
     作成: 2020-12-09  有効期限: 無期限      利用法: A
[  不明  ] (1). <名前> <メールアドレス>

他のユーザの鍵を正しく検証するために、このユーザの信用度を決めてください
(パスポートを見せてもらったり、他から得たフィンガープリントを検査したり、などなど)

  1 = 知らない、または何とも言えない
  2 = 信用し ない
  3 = まぁまぁ信用する
  4 = 充分に信用する
  5 = 究極的に信用する
  m = メーン・メニューに戻る

あなたの決定は? 5
本当にこの鍵を究極的に信用しますか? (y/N) y

pub  nistp521/BF8A708B020A19BB
     作成: 2020-12-09  有効期限: 無期限      利用法: C
     信用: 究極          有効性: 不明の
sub  nistp521/983982062E1BB33D
     作成: 2020-12-09  有効期限: 無期限      利用法: S
sub  nistp521/008734F36B087C1C
     作成: 2020-12-09  有効期限: 無期限      利用法: E
sub  nistp521/26BAE38657860920
     作成: 2020-12-09  有効期限: 無期限      利用法: A
[  不明  ] (1). <名前> <メールアドレス>
プログラムを再起動するまで、表示された鍵の有効性は正しくないかもしれない、
ということを念頭においてください。

gpg> q

SSHキーとして使う

GPGの認証SubキーをSSHキーの代わりに使うことができる。 そのため、今まで複数の鍵を管理していたのをYubikeyにある取り出せない秘密鍵に集約することが出来るため利便性も向上しセキュリティ的にも良い感じになる。

scdaemonの設定

Windows10には既に仮想スマートカードリーダ(Windows Helloなど)がインストールされているため、scdaemonがちゃんとYubikeyを使用するようにする必要がある。

Yubikeyがささった状態で以下でデバイスを取得することが出来るので、 デバイス名を%APPDATA%\gnupg\scdaemon.conf に設定してあげる。

> Get-PnpDevice -Class SoftwareDevice | Where-Object {$_.FriendlyName -like "*YubiKey*"} | Select-Object -ExpandProperty FriendlyName
Yubico YubiKey OTP+FIDO+CCID 0
reader-port Yubico YubiKey OTP+FIDO+CCID 0

gpg-agentの設定

gpg-agentはssh-agentとしても動作することが出来るので、 %APPDATA%\gnupg\gpg-agent.confに設定する。

enable-ssh-support
enable-putty-support

設定を適応するためにagentを再起動する

> gpg-connect-agent killagent /bye
OK closing connection

> gpg-connect-agent /bye
gpg-connect-agent: gpg-agentが実行されていません - 'C:\Program Files (x86)\GnuPG\bin\gpg-agent.exe'を開始します
gpg-connect-agent: agent の起動のため、5秒待ちます...
gpg-connect-agent: agent への接続が確立しました。

認識しているかを確認する。

> gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 0
Application ID ...: Dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: xxxxxxxx
Name of cardholder: <名><姓>
Language prefs ...: ja
Salutation .......:
URL of public key :
Login data .......: <Email等>
Signature PIN ....: 強制なし
Key attributes ...: nistp521 nistp521 nistp521
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 9
KDF setting ......: off
Signature key ....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
      created ....: 2020-12-09 14:35:35
Encryption key....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
      created ....: 2020-12-09 14:36:18
Authentication key: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
      created ....: 2020-12-09 14:37:21
General key info..: sub  nistp521/983982062E1BB33D 2020-12-09 <名前> <メールアドレス>
sec#  nistp521/BF8A708B020A19BB 作成: 2020-12-09 有効期限: 無期限
ssb>  nistp521/983982062E1BB33D 作成: 2020-12-09 有効期限: 無期限
                                 カード番号: 0006 xxxxxxxxx
ssb>  nistp521/008734F36B087C1C 作成: 2020-12-09 有効期限: 無期限
                                 カード番号: 0006 xxxxxxxxx
ssb>  nistp521/26BAE38657860920 作成: 2020-12-09 有効期限: 無期限
                                 カード番号: 0006 xxxxxxxxx

SSH形式の公開鍵に変換する

> gpg --export-ssh-key BF8A708B020A19BB > ~/.ssh/gpg-BF8A708B020A19BB.pub

作成した公開鍵は普通のSSHの公開鍵と同じように扱う。 つまり、接続先の~/.ssh/authorized_keysに追記する。

agent socketのproxyを行う

Windows 10にネイティブにあるOpenSSHではGnuPGが出力するsocketをうまく扱えないようなので、 github.com

socketファイルをWindowsの名前付きパイプにプロキシしてくれるプログラムを使用する。

github.com

最新版の wsl2-gpg-agent.exe を適当なところ(今回は C:\tools\utils\wsl2-gpg-agent\wsl2-gpg-agent.exe においた) にコピーする。

> wsl2-gpg-agent.exe --winssh ssh-pageant

と実行するとpageant\\.\pipe\ssh-pageantにプロキシした状態でシステムトレイに常駐するようになる。

この状態で、SSH_AUTH_SOCK=\\.\pipe\ssh-pageantという環境変数をセットすることによりsshクライアントはプロキシされたgpg-agentを参照するようになる

接続テストをするために既存の ~/.ssh/configでの設定をコメントアウトしておく。

> ssh git@github.com
PTY allocation request failed on channel 0
Hi AkashiSN! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.

github.comにsshをすると、このようにPINを聞かれてちゃんと接続できることが確認できる。

設定の永続化

自動起動の設定

$UserProperty = $(Get-ItemProperty 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders')
$WsShell = New-Object -ComObject WScript.Shell
$Shortcut = $WsShell.CreateShortcut($UserProperty.Startup+"\wsl2-gpg-agent.exe.lnk")
$Shortcut.TargetPath = "C:\tools\utils\wsl2-gpg-agent\wsl2-gpg-agent.exe"
$Shortcut.Arguments = "--winssh ssh-pageant"
$Shortcut.WorkingDirectory = "C:\tools\utils\wsl2-gpg-agent"
$Shortcut.IconLocation = "C:\tools\utils\wsl2-gpg-agent\wsl2-gpg-agent.exe"
$Shortcut.Save()

環境変数の設定

環境変数も設定しておく

SSH_AUTH_SOCK=\\.\pipe\ssh-pageant

SSHの設定

~/.ssh/config で何か設定するときは、

Host github.com
    HostName        github.com
    IdentityFile    ~/.ssh/gpg-BF8A708B020A19BB.pub
    IdentitiesOnly  yes

このように、IdentityFile に先ほど作成した公開鍵を設定すると良い。

Git for Windowsの設定

Git for Windowsにはsshコマンドが付属しているため、WindowsネイティブのSSHを使うように設定しないとうまく動かない。

> git config --global core.sshCommand 'C:/Windows/System32/OpenSSH/ssh.exe'

GitHubでのコミット署名

gpg-BF8A708B020A19BB-2020-12-09.txt の公開鍵を https://github.com/settings/keys に設定する。

Gitの設定を行う。

> git config --global user.signingkey BF8A708B020A19BB
> git config --global gpg.program 'C:/Program Files (x86)/gnupg/bin/gpg.exe'

デフォルトで署名するには以下を実行する。

> git config --global commit.gpgsign true

手動でコミットに署名をするときは -S オプションを加える。

$ git commit -S -m your commit message

このときOpenPGPのPINを求められる。

ちゃんと署名できていればこんな感じにVerifyマークがつく

WSL2で使う

WSL2ではUSBシリアルをサポートしていないため直接Yubikeyに接続することは出来ない。

そこで、Windowsの名前付きパイプをUnixソケットへプロキシしてAgent転送を行うことでWSL2でもYubikeyを使うことが出来る。

先ほどの wsl2-gpg-agent.exe を使う。

公開鍵のインポート

Windowsで行ったのと同様に公開鍵をインポートして、信用しておく。

WSL2側の設定

socat, lsof のインストールをする

$ sudo apt update
$ sudo apt install socat iproute2

.zshrcに以下を追加してログイン時に起動するようにする

wsl2_ssh_pageant_bin="/mnt/c/tools/wsl2-ssh-pageant/wsl2-ssh-pageant.exe"
if test -x "$wsl2_ssh_pageant_bin"; then

  export SSH_AUTH_SOCK="$HOME/.gnupg/S.gpg-agent.ssh"
  if ! ss -a | grep -q "$SSH_AUTH_SOCK"; then
    rm -f "$SSH_AUTH_SOCK"
    (setsid nohup socat UNIX-LISTEN:"$SSH_AUTH_SOCK,fork" EXEC:"$wsl2_ssh_pageant_bin --ssh" >/dev/null 2>&1 &)
  fi

  export GPG_AGENT_SOCK="$HOME/.gnupg/S.gpg-agent"
  if ! ss -a | grep -q "$GPG_AGENT_SOCK"; then
    rm -rf "$GPG_AGENT_SOCK"
    (setsid nohup socat UNIX-LISTEN:"$GPG_AGENT_SOCK,fork" EXEC:"$wsl2_ssh_pageant_bin --gpg S.gpg-agent" >/dev/null 2>&1 &)
  fi

  export GPG_AGENT_EXTRA_SOCK="$HOME/.gnupg/S.gpg-agent.extra"
  if ! ss -a | grep -q "$GPG_AGENT_EXTRA_SOCK"; then
    rm -rf "$GPG_AGENT_EXTRA_SOCK"
    (setsid nohup socat UNIX-LISTEN:"$GPG_AGENT_EXTRA_SOCK,fork" EXEC:"$wsl2_ssh_pageant_bin --gpg S.gpg-agent.extra" >/dev/null 2>&1 &)
  fi

else
  echo >&2 "WARNING: $wsl2_ssh_pageant_bin is not executable."
fi
unset wsl2_ssh_pageant_bin

再度ログインしてYubikeyが認識しているかを確認する。

$  gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID 0
Application ID ...: Dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: xxxxxxxx
Name of cardholder: <名><姓>
Language prefs ...: ja
Salutation .......:
URL of public key :
Login data .......: <Email等>
Signature PIN ....: 強制なし
Key attributes ...: nistp521 nistp521 nistp521
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 9
KDF setting ......: off
Signature key ....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
      created ....: 2020-12-09 14:35:35
Encryption key....: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
      created ....: 2020-12-09 14:36:18
Authentication key: xxxx xxxx xxxx xxxx xxxx xxxx xxxx
      created ....: 2020-12-09 14:37:21
General key info..: sub  nistp521/983982062E1BB33D 2020-12-09 <名前> <メールアドレス>
sec#  nistp521/BF8A708B020A19BB 作成: 2020-12-09 有効期限: 無期限
ssb>  nistp521/983982062E1BB33D 作成: 2020-12-09 有効期限: 無期限
                                 カード番号: 0006 xxxxxxxxx
ssb>  nistp521/008734F36B087C1C 作成: 2020-12-09 有効期限: 無期限
                                 カード番号: 0006 xxxxxxxxx
ssb>  nistp521/26BAE38657860920 作成: 2020-12-09 有効期限: 無期限
                                 カード番号: 0006 xxxxxxxxx

これでWSL2でも使用することができたので後は普通のLinuxと同様にコミット署名とかを設定する。

トラブルシューティング

WSL2でいきなり動かなくなったら、

> wsl --shutdown

でwslの再起動を行えばたいてい治る

参考