使用YubiKey做SSH认证

完整步骤 1. 安装GPG2 2. 生成主密钥以及子密钥 3. 备份密钥以及撤销用证书 4. 发送公钥到公共服务器 5. 在私有服务器上安装GPG2 6. 在私有服务器上下载自己的公钥 7. 在私有服务器上导出自己的公钥为OpenSSH公钥 8. 配置客户端电脑(难点) 9. 转移子密钥到YubiKey

周一下单YubiKey 4,周二到货,当晚就开始折腾,总计搞了三天,也算是折腾明白了。
先说一下完整步骤

  1. 安装GPG2
  2. 生成主密钥以及子密钥
  3. 备份密钥以及撤销用证书
  4. 发送公钥到公共服务器
  5. 在私有服务器上安装GPG2
  6. 在私有服务器上下载自己的公钥
  7. 在私有服务器上导出自己的公钥为OpenSSH公钥
  8. 配置客户端电脑(难点
  9. 转移子密钥到YubiKey

安装GPG2

打开 官方网站

Windoge 平台下载 Gpg4win,Mac 平台下载GnuPG for OS X

然后自行安装,过程几乎就是一路下一步。
Mac 平台自行在 .profile 中添加 alias gpg='gpg2'

生成主密钥以及子密钥

生成主密钥

gpg --gen-key

接着输入一堆身份信息,这个密钥就生成了,然后输入 gpg -k 就能看到你当前的密钥,这里包含一个主密钥和一个子密钥。主密钥功能是 SC 也就是 signcertificate。一般而言,sign 功能是文件签名用,certificate 功能是证书签名用。子密钥功能是 E,也就是 encrypt,用于加密解密文件用。

通常主密钥被称作 private keysecret keymaster key,我们取master key之意。

生成子密钥

生成签名子密钥

gpg --expert --edit-key 1A2B3C4D # 此处更换为你的主密钥 id
addkey
4 # RSA (sign only)
4096 # 密钥长度,2048 兼容好也足够安全,我是因为 YubiKey 4 支持4096
2y # 有效期分别为一直有效、天数、周数、月数、年数,按需选择
y # 是否正确
y # 再次确认是否创建

这样就创建了一个签名专用的子密钥(subkey)。

生成认证子密钥

gpg --expert --edit-key 1A2B3C4D # 此处更换为你的主密钥 id
addkey
8 # RSA (set your own capabilities)
S # 反选 Sign
E # 反选 EncryptE
A # 选择 Authenticate
Q # 完成功能选择
4096 # 密钥长度,2048 兼容好也足够安全,我是因为 YubiKey 4 支持4096
2y # 有效期分别为一直有效、天数、周数、月数、年数,按需选择
y # 是否正确
y # 再次确认是否创建

这样认证专用的子密钥也创建了。三个子密钥完成。

备份密钥以及撤销用证书

备份密钥

gpg --armor --output secret-key.txt --export-secret-keys

这会生成 secret-key.txt 文件,包含你的主密钥和所有子密钥,你也可以使用 export-secret-subkeys 指令来只导出单个/几个/所有子密钥,参数为至少一个密钥 id,以空格分开参数,如果 id 后跟感叹号,则表示单个导出,如果不跟则这个子密钥的所属的主密钥的下属所有子密钥都会导出(很拗口,就是所有同一主密钥的子密钥都会导出)。

备份撤销用证书

gpg --armor --output revoke.txt --gen-revoke 1A2B3C4D # 此处更换为你任一密钥 id

这会生成 revoke.txt 文件,包含撤销此主密钥的证书。

至此,密钥和撤销用证书的导出了,将它们存在一个安全的地方,譬如锁进柜子的u盘里面。

发送公钥到公共服务器

gpg --keyserver keyserver.ubuntu.com --send-key 1A2B3C4D # 此处更换为你的主密钥 id

目前测试 ubuntu 的密钥服务器国内可用。

在私有服务器上安装GPG2

我的服务器是 ubuntu 所以安装如下

sudo apt-get install gnupg2 -y

在私有服务器上下载自己的公钥

gpg2 --keyserver keyserver.ubuntu.com --recv-key 1A2B3C4D # 此处更换为你的主密钥 id

因为 gpg 是包含在大部分 linux 发行版中的,所以我们自己装的 gpg2 需要区别开来。

在私有服务器上导出自己的公钥为OpenSSH公钥

gpg2 --export-ssh-key 1A2B3C4D >> ~/.ssh/authorized_keys # 此处更换为你的主密钥 id

这个操作会将你认证用的子密钥转换成 OpenSSH 公钥,并添加到 ssh 公钥文件中。

配置客户端电脑

这算是整个流程中最耗费我时间的一点了,主要在于 Win7 上我的 gpg-agent 出错,原因从日志中找到了,但是没找到解决方案,最后在 Win10 上测试成功;再之后是因为 Mac 平台上我用的是 GnuPG for OS X 而不是常见的 GPGTools

Windoge 平台

前提条件

  • Gpg4win
  • putty

操作步骤

  1. 开始菜单打开 GPA
  2. Edit->Backend Preference->GPG-Agent
  3. 勾选 enable-putty-support,确定或者应用
  4. 命令行内输入 gpg-connect-agent reloadagent /bye,这会重新载入 gpg-agent
  5. 打开 putty,登陆之前配置的私有服务器,输入密钥的解密密码

Mac 平台

安装 pinentry-mac

brew install --cask pinentry-mac

配置 gpg-agent.conf 文件

文件路径:~/.gnupg/gpg-agent.conf
文件内容:

pinentry-program /usr/local/gnupg-2.1/bin/pinentry-mac.app/Contents/MacOS/pinentry-mac
enable-ssh-support
default-cache-ttl 600
max-cache-ttl 7200

配置 sshcontrol

配置要用的认证key

gpg2 -K --with-keygrip
echo 00112233445566778899AABBCCDDEEFF00112233 >> ~/.gnupg/sshcontrol

配置 .profile

先判断是否从客户端接入,如果不是则启用本地的agent,否则会自动采用客户端的转发过来的agent

新增内容:

# GNUPG
if [ -z "$SSH_CLIENT" ] ; then
    export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
    gpgconf --launch gpg-agent # 主要作用在于确保 gpg-agent 已经启动
fi

新开 shell 窗口,输入命令 gpg-connect-agent reloadagent /bye 重新载入 gpg-agent(如果 gpg-connect-agent 不在环境变量中,那么你需要使用绝对路径,或者添加对应环境变量,或者建立软连接)。

导出ssh公钥

gpg --export-ssh-key 11223344

然后把公钥输入到目标服务器的.ssh/authorized_keys

测试:

ssh you@your.server

弹出 pinentry 界面,输入密钥的解密密码

转移子密钥到YubiKey

  1. 设置你的 YubiKey 已经设置好 admin pin 和 pin
  2. 进入密钥编辑模式
gpg --edit-key 1A2B3C4D # 此处更换为你的主密钥 id
  1. 进入编辑模式后,依次选择 key 并使用 keytocard 转移 subkey 到智能卡对应的槽位

  2. ssh 到你的私有服务器,弹出 pin 输入框即表示成功