如何在 Debian 10 上使用 gpg-agent 和钥匙串缓存 gpg 密钥密码?

Zig*_*obs 6 debian gpg gpg-agent keychain

我有一个 Debian 10 服务器。我想使用 msmtp 发送电子邮件,并且需要缓存 gpg 密钥的密码。msmtp 所需的 smtp 密码使用此 gpg 密钥加密在文件中。msmtp将使用gpg解密该文件以获取smtp密码。

\n

此行存在于 /etc/msmtprc 文件中:

\n
passwordeval gpg --no-tty -q -d /etc/.msmtp-password.gpg\n
Run Code Online (Sandbox Code Playgroud)\n

我正在尝试使用 gpg-agent 和 keychain 来缓存秘密 gpg key 的密码。这样系统就可以发送电子邮件而无需询问密码。

\n

我希望每次启动服务器时只提交一次 gpg 密钥的密码,该密钥的密码将被缓存,直到下次重新启动。(如果我注销并再次登录,则在下次重新启动之前我不需要提交 gpg 密钥的密码)。

\n

我没有成功,因为当我从远程主机(Debian 服务器)注销时,gpg-agent 停止了。如果我通过 SSH 钥匙串建立新连接,则使用新 PID 启动新代理,并且密钥的密码会丢失。

\n

下面您将看到我所做的事情,希望能提供有用的信息。如果你能帮助我,我会很高兴。

\n

我的Linux版本

\n
cat /etc/issue\nDebian GNU/Linux 10 \\n \\l\n
Run Code Online (Sandbox Code Playgroud)\n

GP版本

\n
gpg --version\ngpg (GnuPG) 2.2.12\nlibgcrypt 1.8.4\n
Run Code Online (Sandbox Code Playgroud)\n

我们创建一个秘密的 gpg 密钥,将询问该密钥的密码

\n
gpg --gen-key\n...\nNom r\xc3\xa9el\xc2\xa0: user@mdomain.tld\nAdresse \xc3\xa9lectronique\xc2\xa0: user@mdomain.tld\nVous avez s\xc3\xa9lectionn\xc3\xa9 cette identit\xc3\xa9\xc2\xa0:\n    \xc2\xab\xc2\xa0user@mdomain.tld <user@mdomain.tld>\xc2\xa0\xc2\xbb\n...\nles clefs publique et secr\xc3\xa8te ont \xc3\xa9t\xc3\xa9 cr\xc3\xa9\xc3\xa9es et sign\xc3\xa9es.\n\npub   rsa3072 2020-10-15 [SC] [expire\xc2\xa0: 2022-10-15]\n      3C82AB1E9384F4A92CEBCE7077B1EDA25A942746\nuid                      user@mdomain.tld <user@mdomain.tld>\nsub   rsa3072 2020-10-15 [E] [expire\xc2\xa0: 2022-10-15]\n
Run Code Online (Sandbox Code Playgroud)\n

我们检查密钥

\n
gpg --list-secret-keys --with-keygrip\n...\nsec   rsa3072 2020-10-15 [SC] [expire\xc2\xa0: 2022-10-15]\n      3C82AB1E9384F4A92CEBCE7077B1EDA25A942746\n      Keygrip = 47CF9E2C933761CF1021731F72603B8291BB211C\nuid          [  ultime ] user@mdomain.tld <user@mdomain.tld>\nssb   rsa3072 2020-10-15 [E] [expire\xc2\xa0: 2022-10-15]\n      Keygrip = 4133708B3FA225C4732A0F9FBD0053DEF937B46A\n
Run Code Online (Sandbox Code Playgroud)\n

我们查看gpg-agent进程的PID

\n
ps aux | grep gpg-agent\nroot       738 17.1  0.0  81204  3864 ?        SLs  16:55   0:04 /usr/bin/gpg-agent --supervised\nroot       745  0.0  0.0   6092   824 pts/0    S+   16:56   0:00 grep gpg-agent\n
Run Code Online (Sandbox Code Playgroud)\n

我们检查 gpg-agent 已知的密钥

\n
gpg-connect-agent 'keyinfo --list' /bye\nS KEYINFO 47CF9E2C933761CF1021731F72603B8291BB211C D - - - P - - -\nS KEYINFO 4133708B3FA225C4732A0F9FBD0053DEF937B46A D - - - P - - -\nOK\n
Run Code Online (Sandbox Code Playgroud)\n

我们检查 gpg-agent 选项

\n
gpgconf --list-options gpg-agent\nMonitor:1:0:Options contr\xc3\xb4lant la sortie de diagnostique:0:0::::\n...\ndefault-cache-ttl:24:0:oublier les codes personnels apr\xc3\xa8s N\xc2\xa0secondes:3:3:N:600::\ndefault-cache-ttl-ssh:24:1:oublier les clefs SSH apr\xc3\xa8s N\xc2\xa0secondes:3:3:N:1800::\nmax-cache-ttl:24:2:d\xc3\xa9finir la dur\xc3\xa9e maximale du cache de code personnel \xc3\xa0 N\xc2\xa0secondes:3:3:N:7200::\nmax-cache-ttl-ssh:24:2:d\xc3\xa9finir la dur\xc3\xa9e maximale du cache de clef SSH \xc3\xa0 N\xc2\xa0secondes:3:3:N:7200::\n...\npinentry-timeout:24:1:set the Pinentry timeout to N seconds:3:3:N:0::\n
Run Code Online (Sandbox Code Playgroud)\n

default-cache-ttl 和 max-cache-ttl 太低,gpg-agent 只会缓存密码 10 分钟。如果您打算使用钥匙串,这段时间太短了。我们还可以添加一个日志文件。可以通过添加 gpg-agent.conf 文件来更改默认选项。

\n
cat ~/.gnupg/gpg-agent.conf\ndefault-cache-ttl 31536000\nmax-cache-ttl 31536000\nlog-file /var/log/gpg-agent\ndebug-level basic\n
Run Code Online (Sandbox Code Playgroud)\n

我们检查是否添加了新的 gpg-agent 选项

\n
gpgconf --list-options gpg-agent\n\nMonitor:1:0:Options contr\xc3\xb4lant la sortie de diagnostique:0:0::::\n...\ndefault-cache-ttl:24:0:oublier les codes personnels apr\xc3\xa8s N\xc2\xa0secondes:3:3:N:600::31536000\ndefault-cache-ttl-ssh:24:1:oublier les clefs SSH apr\xc3\xa8s N\xc2\xa0secondes:3:3:N:1800::\nmax-cache-ttl:24:2:d\xc3\xa9finir la dur\xc3\xa9e maximale du cache de code personnel \xc3\xa0 N\xc2\xa0secondes:3:3:N:7200::31536000\nmax-cache-ttl-ssh:24:2:d\xc3\xa9finir la dur\xc3\xa9e maximale du cache de clef SSH \xc3\xa0 N\xc2\xa0secondes:3:3:N:7200::\n...\npinentry-timeout:24:1:set the Pinentry timeout to N seconds:3:3:N:0::\n
Run Code Online (Sandbox Code Playgroud)\n

我们重新加载 gpg-agent 配置以激活新选项

\n
gpg-connect-agent reloadagent /bye\nOK\n
Run Code Online (Sandbox Code Playgroud)\n

知道我们安装钥匙扣

\n
apt install -y keychain\n
Run Code Online (Sandbox Code Playgroud)\n

钥匙扣版本

\n
keychain -V\n\n * keychain 2.8.5 ~ http://www.funtoo.org\n
Run Code Online (Sandbox Code Playgroud)\n

我们使用钥匙串缓存解密的 GPG 密钥

\n
keychain --eval --agents gpg 3C82AB1E9384F4A92CEBCE7077B1EDA25A942746\n\n * keychain 2.8.5 ~ http://www.funtoo.org\n * Inheriting gpg-agent (738)\nGPG_AGENT_INFO=/run/user/0/gnupg/S.gpg-agent:738:1; export GPG_AGENT_INFO;\n\n * Adding 1 gpg key(s): 3C82AB1E9384F4A92CEBCE7077B1EDA25A942746\n
Run Code Online (Sandbox Code Playgroud)\n

因为我们输入了密码,所以解密的 GPG 密钥现在由 gpg-agent 缓存(看 1)

\n
gpg-connect-agent 'keyinfo --list' /bye\nS KEYINFO 47CF9E2C933761CF1021731F72603B8291BB211C D - - 1 P - - -\nS KEYINFO 4133708B3FA225C4732A0F9FBD0053DEF937B46A D - - - P - - -\nOK\n
Run Code Online (Sandbox Code Playgroud)\n

我们修改.bashrc文件。下次登录时钥匙串将找到由 gpg-agent 缓存的解密的 GPG 密钥。下次重新启动时,钥匙串将询问一次密钥的密码,直到下次重新启动为止

\n
cat ~/.bashrc\n...\n# Note: PS1 and umask are already set in /etc/profile. You should not\n# need this unless you want different defaults for root.\n# PS1='${debian_chroot:+($debian_chroot)}\\h:\\w\\$ '\n# umask 022\n...\neval $(keychain --agents gpg)\n
Run Code Online (Sandbox Code Playgroud)\n

为了检查default-cache-ttl和max-cache-ttl,我们等待700秒,超过gpg-agent默认配置

\n
jeudi 15 octobre 2020, 16:56:32 (UTC+0200)\n\njeudi 15 octobre 2020, 17:08:12 (UTC+0200)\n
Run Code Online (Sandbox Code Playgroud)\n

我们检查 gpg-agent 已知的密钥,解密的 GPG 密钥仍然由 gpg-agent 缓存(看 1)

\n
gpg-connect-agent 'keyinfo --list' /bye\nS KEYINFO 47CF9E2C933761CF1021731F72603B8291BB211C D - - 1 P - - -\nS KEYINFO 4133708B3FA225C4732A0F9FBD0053DEF937B46A D - - - P - - -\nOK\n
Run Code Online (Sandbox Code Playgroud)\n

我们创建一个文件并使用密钥对其进行加密(加密不需要密码)

\n
touch file.txt && gpg -e -r user@mdomain.tld file.txt\n
Run Code Online (Sandbox Code Playgroud)\n

我们解密该文件。不需要密码,因为解密的 GPG 密钥在 700 秒后仍由 gpg-agent 缓存

\n
gpg --decrypt file.txt.gpg > file.txt\ngpg: chiffr\xc3\xa9 avec une clef RSA de 3072\xc2\xa0bits, identifiant 4E40A1918B514393, cr\xc3\xa9\xc3\xa9e le 2020-10-15\n      \xc2\xab\xc2\xa0user@mdomain.tld <user@mdomain.tld>\xc2\xa0\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

我们注销并通过 ssh 再次登录远程主机。在新登录时,钥匙串找不到带有缓存密钥的先前 gpg-agent。然后钥匙串启动一个新的 gpg-agent 但缓存的密钥丢失了......

\n
* keychain 2.8.5 ~ http://www.funtoo.org\n* Starting gpg-agent...\n
Run Code Online (Sandbox Code Playgroud)\n

问候

\n

Zig*_*obs 7

最终我找到了解决方案。

\n

gpg-agent 在从 bash 会话注销后关闭,因为它处于受监督模式

\n

查看文件:

\n
/usr/share/doc/gpg-agent/README.Debian\n
Run Code Online (Sandbox Code Playgroud)\n
\n

系统\n========

\n

自 2.1.17 起,具有 systemd 的计算机上的用户将在首次访问任何预期的 gpg-agent 套接字(包括 ssh\nsocket)时,由 systemd 的用户会话自动启动其 gpg-agent 进程。systemd 还将在会话\n注销时彻底终止此进程。

\n
\n

因此,我们需要以守护进程模式启动 gpg-agent ,以便在会话中保持 gpg-agent 的 PID 相同。

\n

在执行此操作之前,我们需要从 systemd 中“屏蔽”gpg-agent

\n
systemctl --user mask --now gpg-agent.service gpg-agent.socket gpg-agent-ssh.socket gpg-agent-extra.socket gpg-agent-browser.socket\n
Run Code Online (Sandbox Code Playgroud)\n

这可以通过“unmask”选项撤消(请参阅 README.Debian 文件)。

\n

下次请求 gpg-agent 时(例如,创建密钥或使用钥匙串时),它将以守护程序模式启动并跨会话运行。

\n
ps aux | grep gpg-agent\nroot       816  0.2  0.0  81356  3624 ?        Ss   17:19   0:04 gpg-agent\n--homedir /root/.gnupg --use-standard-socket --daemon\n
Run Code Online (Sandbox Code Playgroud)\n

在 .bashrc 文件中只需添加:

\n
eval $(keychain --eval --agents gpg secretkey)\n
Run Code Online (Sandbox Code Playgroud)\n

注销后,如果您再次登录,钥匙串会找到正确的 gpg-agent(查看 PID),不会询问密码。

\n
keychain 2.8.5 ~ http://www.funtoo.org\nFound existing gpg-agent: 816\nKnown gpg key: 677AAEB080C1045F3D3D3532B5AE92F1F49350D1\n
Run Code Online (Sandbox Code Playgroud)\n

并且您仍然可以在没有密码的情况下解密文件

\n
gpg --decrypt file.txt.gpg > file.txt\ngpg: chiffr\xc3\xa9 avec une clef RSA de 3072\xc2\xa0bits, identifiant F1B9BB72AAECF1C7,\ncr\xc3\xa9\xc3\xa9e le 2020-10-16\n\xc2\xab\xc2\xa0user@domain.tld <user@domain.tld>\xc2\xa0\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

希望这有帮助。

\n