使用 GPG 密钥进行 SSH 认证

之前了解到可以将 GPG 的密钥用于 SSH 的身份认证,最近进行了一些尝试。

在创建 GPG 密钥的时候可以看到类似于如下的信息让人选择新建的密钥的用途:

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection?

由于在创建密钥的时候并没有太注意,并且有些时候可能并不会创建一个 Authenticate 用途的密钥,所以一直很好奇设置为 Authenticate 的 GPG 密钥究竟应该怎么用。只是看到一些地方一笔带过说将 GPG 的密钥用于 SSH 的身份认证,所以最近查找资料进行了尝试。以下的简称的「认证」指的都是 Authenticate。

首先要理解的是 SSH 的身份认证可以通过多种方式,除了直接使用 Unix 用户的密码进行认证,也可以基于公钥进行认证,在与网友的交流中也了解到甚至可以通过 X.509 证书体系进行认证。所以, GPG 本身就是公钥密码学的一种实现,从理论上来说完成 SSH 的认证过程没有问题。常见的公钥认证是通过 SSH 内置的 ssh-keygen 生成的密钥对。

如果使用过 SSH 内置的公钥认证,你可能会发现,在一些默认安装图形界面 GNU/Linux 的发行版上,在图形界面的终端模拟程序下使用 SSH 登录到远程主机的时候,公钥认证时输入密码的提示是通过图形界面完成的。并且有些时候在完成一次认证之后,再登录使用同一密钥对的其他远程主机,并不需要重新输入密码。这里就引出了 Agent 程序的概念。

Agent 程序会介入公钥的认证过程,并将已经解锁的私钥理论上安全地保存在内存中,其他的程序便不需要重新去实现一遍读取私钥并解锁的功能,直接通过套接字与 Agent 程序进行交互便可以完成认证。这一套接字具体绑定在哪个程序上,我们可以通过打印 SSH_AUTH_SOCK 环境变量来查看和确认

echo $SSH_AUTH_SOCK

对于 SSH 来说其自带的 Agent 程序就是 ssh-agent ,并通过 ssh-add 与 Agent 程序交互。但是在刚才提到的图形界面的例子中,之所以认证通过图形界面进行,是因为桌面环境所自带的 Keychain 应用则替代了 SSH 自带的 ssh-agent 程序。对于 GPG 来说,其也是一个公钥密码学的实现,同样也有自己的 Agent 程序,那就是 gpg-agent

到这里其实我们要做的事情其实已经很明确了,那就是我们需要用 gpg-agent 介入 SSH 的认证过程。方法也很明确,就像桌面环境的 Keychain 应用那样设置 SSH_AUTH_SOCKgpg-agent 所创建的套接字即可。接下来就是具体的设置过程。以下默认使用的 gpg 为 GPG 2.1+ 的版本。并且确认你已经对 GPG 的使用有一定程度的了解。

首先,需要确认你拥有一个用途设置为 Authenticate 的 GPG 密钥或者子密钥。用以下的命令确认并获取该密钥或子密钥的指纹(40位 HEX)

gpg --with-keygrip -K

将该指纹放入 ~/.gnupg/sshcontrol 文件中。

配置gpg-agent,在 ~/.gnupg/gpg-agent.conf 中加入下面的行

# Enable the OpenSSH Agent protocol
enable-ssh-support

以开启 gpg-agent 对 SSH 认证的支持。

接着,确认 gpg-agent 运行情况,可以通过 ps aux 打印进程列表进行查看。如果已在运行,将其关闭

gpgconf --kill gpg-agent

或者 kill -9 [pid] ,其中 [pid] 为刚才获取到的 gpg-agent 的 PID。

然后以下面的命令启动 gpg-agent

gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf

这时,gpg-agent 会有类似于以下的输出

SSH_AUTH_SOCK=/path/to/auth/sock; export SSH_AUTH_SOCK;

复制并执行这行命令。以后再需要使用 gpg-agent 进行 SSH 认证的时候都需要执行这一命令,所以如果嫌麻烦,可以将此行命令放置于 Shell 的启动脚本中。

此时,检查 SSH_AUTH_SOCK 环境变量,确定为 gpg-agent 的内容。执行 ssh-add -l 应该就会输出刚才添加到 sshcontrol 中的密钥条目。

接着,用刚才的命令,获取对应于得到指纹的密钥的 ID

gpg --with-keygrip -K

其具有类似于 0xFFFFFFFF 的格式,以下以之为例。接着用下面的命令导出 SSH 公钥

gpg --export-ssh-key 0xFFFFFFFF

最后,将输出的公钥放到 SSH 目标主机的 ~/.ssh/authorized_keys 中即可。

《使用 GPG 密钥进行 SSH 认证》上有2条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注