我想让 pinentry 在本地使用 GUI 并在 SSH 上使用 CLI

Chi*_*aba 11 linux ssh terminal gnupg gpg-agent

我需要能够在两个不同的 Linux 环境中对 git 提交进行 GPG 签名。

  1. 在使用基于 GUI 的密码对话框的完整 GUI X-Window 设置中

  2. 在 SSH 中,没有 X 转发,仅使用命令行密码输入

在这两种情况下,我都需要能够使用不同的 UID 进行签名,所有这些都在我的密钥环中。本地和远程访问在一台计算机上使用相同的用户帐户,并且可能同时处于活动状态。该计算机运行 openSUSE Leap 15 (4.12.14),使用 GnuPG 2.2.11 和 libgcrypt 1.8.4。我典型的远程连接在 Android v5.1.1 上使用 ConnectBot v1.9.5,尽管我也经常在 iOS 12.1.1 上使用 Terminus v4.3.12,有时我也可以使用公共 Win 10 PC。

我不想要一个迫使我在本地使用 CLI 方法的“永久”解决方案。这样做会影响 gpg 的所有其他用途,包括电子邮件。

阅读这个问题,我尝试了几种似乎暗示自己的变体。尽管那里的解决方案,包括已接受的解决方案,都是为了永久解决方案。我希望他们能在我的用例中找到解决方案。

pinentry-command我已经尝试了在我的文件中设置的几种变体gpg-agent.conf。在所有情况下,该gpg-connect-agent reloadagent /bye命令都会在更改配置文件后执行。进行任何更改后,远程会话将按原样重新启动,并在执行以下每个命令后按顺序进行测试:

  1. export GPG_TTY=$(tty)
  2. unset DISPLAY
  3. gpg-connect-agent updatestartuptty /bye

三个命令前后的结果是相同的,如下所示:

  • 使用pinentry在本地提供 GUI 方法 - 无论我是在本地还是远程执行命令(远程屏幕只是挂起,直到对话框超时。)
  • 在所有情况下都使用pinentry-tty强制 CLI。(远程使用在远程终端中提示,本地使用在本地终端中提示。)
  • 使用pinentry-gtk-2重复的结果pinentry
  • 使用pinentry-qt也会重复以下结果pinentry
  • 使用pinentry-curses提供了诅咒框,但否则会重复以下结果pinentry-tty

在所有情况下,如果设置导致本地出现命令行提示符,则所有非 CLI 使用(例如 Thunderbird)都会失败并出现错误。

不会在命令行或文本文件中包含密码(--passphrase-*GnuPG 没有选项)。

不会使用无密码密钥。

对任何一个键进行硬编码都没有什么好处,因为我经常在短时间内使用多个键。

如果可能的话,我将使用命令行选项来强制选择正确的 pinentry。我不确定是否可以gpg通过 传递选项git

我希望能够让 pinentry 自动“选择”正确的选项。我还希望命令行 pinentry 适用于所有命令。然而目前,我只需要它与 git 使用相关的工作。(签名通常是一个密钥,而推/拉操作需要不同的密钥。)目前,我的主要远程 SSH 客户端可以在登录时执行自定义命令,因此仅影响当前会话/tty 的脚本也是可以接受的,尽管并不理想。文件的每个连接修改gpg-agent.conf(手动或脚本化)是不可接受的。

让这项工作在 Mac 上运行有一个充满希望的答案。然而,尝试使用上述选项并没有产生不同的结果。(我也尝试过="USE_TTY=1",以防万一它有效。)

如果存在可能有效但无法在我的环境之外进行测试的可能性,我可以根据建议努力找到真正的解决方案(可以说是团队努力) 。


目前的解决方法

作为我的问题的“修复”,我开发了一种解决方法,虽然不是最优的,但确实有效。我还制作了一些包装脚本,以半自动的方式利用该解决方法。

解决方法要求我有两个版本的gpg-agent.conf,在我的例子中gpg-agent.localgpg-agent.remote,它们只有一行不同。本地版本有pinentry-program /usr/bin/pinentry,远程版本有pinentry-program /usr/bin/pinentry-ttygpg-agent.conf是其中一个的符号链接,通常是本地版本。要切换到远程,我执行:

rm ~/.gnupg/gpg-agent.conf
ln -s ~/.gnupg/gpg-agent.remote ~/.gnupg/gpg-agent.conf`
gpgconf --kill gpg-agent
gpg-connect-agent reloadagent /bye
gpg-connect-agent updatestartuptty /bye
Run Code Online (Sandbox Code Playgroud)

也许所有三个命令都太过分了,但我无法准确确定哪个子集将保证完整的切换,而且我知道这三个命令总是有效的。

返回本地版本是相同的过程,本地版本替换符号链接中的远程版本。

在 SSH 时我做的最多的两件事是 git commit 和 push,所以我有一个包装脚本,这两个脚本将切换到远程conf,执行 git 操作,并将conf切换回本地版本,以便它准备好从本地机器使用。其他一切都要求我记得在尝试使用 GPG 之前切换到远程,并在完成后切换回本地。

如果我碰巧忘记切换到远程,暂停后,我意识到什么也没有发生,因为 GPG 正在主机上显示 GUI 对话框,并且可以CTRL+C退出,执行切换并重新运行命令。如果我忘记返回到本地版本,则在本地计算机上使用命令会在 CLI 中提供密码提示,我可以输入密码,然后在会话的剩余时间内将配置重置为本地。

我认为这种解决方法不是最佳的原因是所有这些都是手动完成的。用于进行切换的脚本或应用和重置切换的其他命令的包装器会有所帮助,但不会由系统或配置自动处理。总是需要我的干预来实现它,并在我完成或切换终端会话时解除所做的事情。

用户Michele使用的建议可能会对我必须做的事情产生很大的影响,但仍然需要我将该命令设置手动执行的命令。我可以将它添加到我当前的 SSH 客户端作为“第一个”命令,但是如果/当我使用不同的客户端时,我仍然必须记住使用该命令,并记住它是什么。export DBUS_SESSION_BUS_ADDRESS=/dev/null

也许通过我的解决方法以及Michele的想法,其他人可能会找到“可行”的解决方案。

小智 0

作为一种解决方法,可以使用替换/别名gpg2

#!/bin/bash

if [ -n "$DISPLAY" ] ; then
  echo "gui |$DISPLAY|"
  /usr/bin/gpg2 $@
else
  echo "no gui"
  /usr/bin/gpg2 --pinentry-mode loopback $@
fi
Run Code Online (Sandbox Code Playgroud)

但令人烦恼的部分是 GUIpinentry仍然显示在远程计算机上(“远程”是指我正在 ssh 访问的计算机,因此它是不可见的。

强制执行时pinentry-tty我仍然遇到问题,在某些情况下没有提示(可能取决于代理的启动方式/位置)并且失败了。所以现在我求助于添加.gnupg/gpg.conf

pinentry-mode loopback
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

8377 次

最近记录:

2 年,6 月 前