把 Gpg4win 的 gpg-agent 转发到 WSL 中

因为个人大部分的工作在 WSL 环境下进行,但是 WSL 下又用不了 YubiKey ,所以每次用到 GPG 都得把资料弄到 Windows 环境下,很麻烦。

后来知道 gpg-agent 跟 ssh-agent 一样是可以被转发的,可以用转发的方式在其他的机器上调用本机的 gpg-agent 。如果转发到 WSL 里面,那么 WSL 里触发的各种 GPG 操作实际上会在 Windows 下的 GPG 中执行,也就可以用到 YubiKey 了。

不过这东西转发起来比较麻烦,主要由于 Gpg4win 自己折腾了一套 Socket(其实就是用 TCP 来模拟 Unix Socket )。翻了一些文档之后,了解到这个假的 Socket 的工作原理是 Socket 文件中写了端口号和一串类似 Key 的东西,连上对应的 TCP 端口并且把这串 Key 丢过去,就相当于连上了这个 Socket 。

因此写了如下 Shell 脚本,在 WSL 下模拟这个连接过程然后转成 WSL 下的 Unix Socket ,丢在 ~/.gnupg/S.gpg-agent 下面让 GPG 自己连上。

#!/bin/bash
if [ ! -S "$HOME/.gnupg/S.gpg-agent" ]
then
	GPG_AGENT="/mnt/c/Users/csl/AppData/Roaming/gnupg/S.gpg-agent.extra"
	PREPEND_FILE="/tmp/gpg_agent_prepend"
	WINDOWS_GPG_AGENT_PORT=$(head -n1 "$GPG_AGENT")
	tail -n+2 "$GPG_AGENT" > "$PREPEND_FILE"
	socat "UNIX-LISTEN:$HOME/.gnupg/S.gpg-agent,fork" \
		"SYSTEM:cat \"$PREPEND_FILE\" - <&3 | socat STDIO \"TCP\:127.0.0.1\:$WINDOWS_GPG_AGENT_PORT\" >&4,fdin=3,fdout=4"
fi

如上脚本修改一下 Windows 的帐户名,然后存成 ~/gpg_agent.sh ,然后在 .bashrc 中加:

~/gpg_agent.sh & >/dev/null 2>&1

实际使用的时候还遇到了如下几个坑:

  1. apt install gnupg 装的是 GPG 1.4 ,然而现在都用上 2 了。需要 apt install gnupg2 ,而且 Gpg4win 下面的 gpg 默认就是 GPG 2 ,然而 Ubuntu ( WSL ) 下面的 GPG 2 是 gpg2 ……
  2. 转发之后在 WSL 下的 GPG 也需要有你的 public key ,要 import 一下或者直接从 keyserver 拉。
编辑于 2017-12-07