Using gpg-agent Effectively

Using gpg-agent Effectivel

有效的使用gpg代理

Mar 26, 2018

2018年3月26日

I’ve used GnuPG (or “GPG”) for years now, but until recently I had never bothered setting up gpg-agent. I’ve just never needed it. The agent mediates access to private keys. These keys are only required for decryption and signing; encryption and signature verification only require public keys. I’ve mostly used GPG in the past for encrypting backups before uploading them to cloud storage, and this doesn’t require using an agent. When I needed to restore backups or sign Debian and RPM packages I would just enter my password, but this was infrequent enough to make an agent unnecessary.

我已经使用GnuPG(或者GPG)很多年了,但是知道最近,我才开始费心设置gpg代理,我只是从来不需要它,代理中介访问私钥,这些秘钥仅用于解密和签名;加密和签名验证仅需要公钥。在过去,我主要使用gpg对备份进行加密,然后再将他们上传到云存储,这不需要使用代理,当我需要恢复备份或者签署Debian和RPM包是我才需要输入我的密码,但是这也不能影响的代理的重要性。

A few things happened recently that changed this. I recently switched away from the Gmail web UI, and I now access my email using mbsync and mu4e (a topic for a future blog post). My dot files are stored in a private git repository I self-host, and I’m using app passwords for the IMAP and SMTP credentials. Even with all that, I’m not really a fan of adding plaintext passwords to git repositories. The alternative is to store these files in ~/.authinfo.gpg which can be version controlled in git. Using a real email client has also made it easier to work with PGP signed (and encrypted) email, so that was another reason to set up an agent. And finally, I wanted to start signing my git commits, and I don’t want to enter a long password every time I commit.

最近发生的一些事情改变了这一点。我最近 不使用Gmail web UI可,我现在开始用 mbsync 和mu4e(一个未来博客文章的主题)去访问我的邮箱了。我的dot文件储存在我自己托管的私有git存储库中,并且我在使用IMAP和SMTP凭据的时候使用app的密码,尽管如此,我还是不太喜欢在git存储库中添加明文的密码。另一种存储这种文件的方法是将这些文件存储在~/.authinfo.gpg中。后者可以再git中进行版本控制。因此这是设置代理的另一个原因。最后,我想开始签署我的git提交,因为我不想每次提交都要输入长密码。

SSH Agent Functionality

As I started looking at the gpg-agent man page the first thing I noticed was its SSH agent functionality. I’ve been using Ed25519 SSH keys since June 2015, and have had a long and difficult battle with the GNOME keyring, which doesn’t support these keys. I had to employ crazy hacks to work around GNOME when they broke environment variables in Wayland. Then GNOME broke my agent again when they changed how sessions are initialized, and after some serious code spelunking I found out the source of the issue, and asked them to revert their “fix”. The final place I ended up was having an ssh-agent process managed in a systemd user session. This works, but has a serious drawback. Keys aren’t automatically loaded into an agent during login, and need to be manually added. The SSH protocol is very basic and doesn’t have pinentry capabilities. This meant I needed to manually run ssh-add in a terminal every time I logged in to load my keys. If I forgot to run this step, other commands using SSH (e.g. git) would prompt for the key decryption password on their TTY, and the key wouldn’t be loaded into the agent process automatically.

SSH 代理功能

当我开始查看gpg代理手册时,我首先注意到的就是它的SSH代理功能,我曾经在2015年六月到现在一直在使用Ed25519 SSH秘钥,并且经历了与GNOME keyring不支持这些秘钥的漫长又艰难的斗争后,当他们在Wayland中破坏环境变量时,我不得不用疯狂的hack工作在GNOME周围。然后,当GNOME改变了会话的初始化方式时,他再次破坏了我的代理,在一些认真思索的代码编写之后,我发现问题个根源,并且要求他们恢复他们的修复。最后一个结果是在系统用户session中管理的ssh代理进程。这可行,但是有一个严重的后果。秘钥在登录期间不能自动加载到代理中,并且需要去手动添加。这个ssh 协议是分成基础的,没有pinentry功能。这就意味着登录加载我的秘钥时,我需要去手动在终端中实时运行ssh-add。如果我忘记去运行这个步骤,使用其他的命令SSH(例如git)在他们自己的TTY上将需要解密,并且他们的秘钥将不胡被自动加载到代理进程。

I was curious to see how the gpg-agent SSH functionality stacked up. It is really good, and now I’m kicking myself in the foot for not investigating this possibility earlier. GnuPG added Ed25519 support back in in August 2015, as part of the v2.1.7 release. This means that like OpenSSH, and unlike gnome-keyring-daemon (henceforth “GKD”), it can load my Ed25519 SSH keys. That’s pretty awesome. Even better, GnuPG has real pinentry support. It can ask for your decryption phrase using a regular pseudo-TTY (like running ssh-add in a terminal), using a curses application, or using a modal GNOME 3 dialog.

我很想知道gpg-agent SSH 功能是如何堆积起来的。这真的很棒,现在我为我自己没有早点调研这种可能性而十分伤心。GnuPG作为版本2.1.7的一部分,在2015年添加Ed25519支持,这就意味着像OpenSSH,而不是像gnome keyring daemon(以下简称gkd).可以加载我的Ed25519 SSH秘钥,这真的很棒啊,甚至更好,GnuPG有真正的pinentry支持。它能使用常规的pseudo-TTy(就像在终端中运行了ssh-add)使用一个curses应用,或者使用一个GNOME 3 对话框模型去解密语句。

Ironically, gpg-agent also has full GKD integration, meaning that it works as a better GNOME SSH agent than the one GNOME ships. The way this works is that the pinentry-gnome3 input method can optionally store your key decryption passphrase in GKD.1 If you choose to store your passphrase this way your SSH key will be unlocked automatically when it’s first needed, without manually entering the passphrase. This reduces security, but it’s probably what many people want and expect.

讽刺的是,gpg-agent 还具有完整的gkd集成,意味着它作为GNOME ssh 代理比 作为GNOME  发布更好。其工作方式是pinentry-gnome 3输入方法可以选择将秘钥解密密码语句存储在gkd.1中,当他第一次被需要的时候,没有手动输入密码语句时,你选择这种方式去存储你的密码秘钥,你的SSH秘钥将会不自动解锁。这降低了安全性,但是这可能是很多人想要的和期望的。

Running gpg-agent A Systemd User Service

运行gpg-agent 代理系统用户服务

I’m a really big fan of systemd user services. This is a feature in systemd that allows you to run services under the systemd instance managing your login session. In my opinion this is about 1000x better than the traditional way of managing user session daemons like ssh-agent and gpg-agent. The advantages of using systemd user services are:

我真的是系统用户服务的超级粉丝,这是一个在systemd中的一个功能,允许在你的管理登录会话中去运行服务。这在我看来,这比管理用户会话手环进程例如ssh-agent 和gpg-agent的传统方式要好1000倍。使用systemd用户服务的有点是:

  • There’s a single consistent way to manage services, check the status of services, enable or disable services, start and stop services, etc.
  • 管理服务,检查服务状态,启用活禁用服务,启动和停止服务等只有一种一致的方法。
  • Units can be easily version controlled along with your other dot files. It’s much easier to version control things like systemd timer units than user crontabs.
  • Units可以很容易的版本控制与您的其他dot文件。用户crontabs 要比版本控制像systemd 定时器units 要容易的多。
  • Log data from these services is handled by journald, which means you never need to guess where log files are, and you can use all of the powerful journalctl features to search these logs.
  • 这些服务中日志数据的处理由journald负责,这就意味着你将无需去猜测log文件在哪里,你可以使用强大的journalctl功能去检索这些文件
  • In the non-systemd world user daemon processes get parented to the system init process. This causes problems if you want the daemons to terminate when you logout. It also makes it difficult to ensure that you don’t have duplicate instances of the daemon processes after logging in and then logging back out. Systemd user services solve this problem completely, and you can control whether you want the services to “linger” or not.
  • 在非system的世界中,用户守护进程将会成为system innit 进程的父进程,如果希望在注销是终止进程的重复实例,systemd用户服务完全可以解决的掉这个问题,您可以控制是否希望服务延时。

I already manage a number of session services and timers using systemd, so naturally I set about to write systemd user services to manage my gpg-agent process. I was pleasantly surprised to see that GnuPG 2.1.16 (released in November 2016) added native support for systemd user services, meaning I didn’t need to write my own unit files. The process to use the official systemd user units isn’t very well documented, so I’ll explain it here.

我已经使用systemd管理了很多的session服务,和定时器,所以很自然的我开始编写我的systemd用户服务来管理我的gpg代理进程。我惊喜的看到了,GnuPG 2.1.1.6(在2016年11月发布),增加了对systemd 用户的本地支持,这意味着我不需要编写自己的单元文件。使用官方systemd用户单元过程并没有很好的文档记录,所以我将在这里解释它。

The basic idea is that GnuPG includes a number of .socket and .service files. The sockets are managed by a systemd user service, and a gpg-agent or dirmngr process can be started on-demand when a socket is used. The agent process stays in the foreground and sends log output to stdout/stderr where it’s intercepted by journald. You need to copy these files to ~/.config/systemd/user to activate and use them.2

这个基本思想是GnuPG 包含了很多的。socket 和。service文件。这套接字被systemd用户服务管理,而gpg-agent 或者dirmngr进程可以在套接字被使用时启动,这个代理进程保持在前台,并将log日志输出到stdout/stderr目录,在哪里将被journald截获。你需要复制这些文件到~/.config/systemd/user目录下,并且激活和使用他们。

On Fedora the gnupg2 package will put these files in /usr/share/doc/gnupg2/examples/systemd-user. If you’re building from source you can find these files in the doc/examples/systemd-user directory. You should see the following files:

在Fedora 上这个gnupg2包将会放入这些文件到这个/usr/share/doc/gnupg2/examples/systemd-user中。如果你是从源代码开始构建的,可以在doc/examples/systemd-user 目录中找到这些文件。您应该看到以下文件:

# On Fedora you'll find the files here.
$ ls -l /usr/share/doc/gnupg2/examples/systemd-user
total 32
-rw-r--r--. 1 root root  212 Aug 28  2017 dirmngr.service
-rw-r--r--. 1 root root  204 Aug 28  2017 dirmngr.socket
-rw-r--r--. 1 root root  298 Aug 28  2017 gpg-agent-browser.socket
-rw-r--r--. 1 root root  281 Aug 28  2017 gpg-agent-extra.socket
-rw-r--r--. 1 root root  223 Aug 28  2017 gpg-agent.service
-rw-r--r--. 1 root root  234 Aug 28  2017 gpg-agent.socket
-rw-r--r--. 1 root root  308 Aug 28  2017 gpg-agent-ssh.socket
-rw-r--r--. 1 root root 2274 Aug 28  2017 READMEjavascript:void(0)

Copy them to your systemd user directory:

复制他们到你的systermd用户目录下

# Create the directory if it doesn't already exist.
$ mkdir -p ~/.config/systemd/user

# Copy the files.
$ cd /usr/share/doc/gnupg2/examples/systemd-user
$ cp *.{socket,service} ~/.config/systemd/user

# This will save a lot of typing. I have it in my .bashrc.
$ alias sysu='systemctl --user'

# Refresh systemd.
$ sysu daemon-reload

# Enable and start the sockets.
$ sysu enable *.socket
$ sysu start *.socket

There’s one final required step: you need to tell gpg-agent where to ask for pinentry input. For pinentry in X11 or Wayland you can add the following line to your agent config:

最后一个需要的步骤就是:你需要告诉gpg-agent 你在哪里需要输入pinentry。对于X11或者Wayland中的pinentry ,你可以将以下行添加到代理配置中去:

# Set a default display for gpg-agent.
$ echo "display :0" >> ~/.gnupg/gpg-agent.conf

You can also set the GPG_TTY environment variable if you’re not using a graphical session.

如果你不使用图形会话,你也可以设置这个GPG_TTY环境变量

Using The SSH Agent

使用ssh代理

To get the SSH agent to work you need to point SSH_AUTH_SOCK at the new SSH socket. The simplest way is to add this to your shell profile:

获取SSH代理去工作则你需要在新的SSH套接字中指向SSH_AUTH_SOCK。

# Add this to ~/.profile or ~/.bash_profile
export SSH_AUTH_SOCK="/run/user/$(id -u)/gnupg/S.gpg-agent.ssh"

If you want to be really fancy you can inject the variable into your session using the set-environment command. There’s not really any advantage to doing it this way, but if you want to see what that looks like you’d change the gpg-agent-ssh.socket file like this.

如果你真的很想使用set-environment 命令将变量注入到会话中,这样这并没有什么好处,但是如果你想看到他的样子,你可以像这样改变gpg-agent ssh.socket文件

There’s one final gotcha: the agent will only act delegate SSH keys with keygrips listed in ~/.gnupg/sshcontrol. You can also use this file to set caching policies on a per-key basis, which could be useful if you have multiple SSH keys and wanted to cache some of the keys longer or shorter than the others. The first time you use an SSH key with the agent you need to manually run ssh-add in a terminal. This should update the sshcontrol file and afterwards you should see something like this:

最后一个问题是:代理将只使用~/.gnupg/sshcontrol列出keygrips来代理ssh秘钥。您还可以使用此文件一每个秘钥为基础设置缓存策略,如果您有多个ssh秘钥,则这可以能非常有用,第一次在代理中使用ssh秘钥时,需要在终端中手动运行ssh-add。这将更新sshcontro文件,然后你将看到如下内容:

$ cat ~/.gnupg/sshcontrol
# List of allowed ssh keys.  Only keys present in this file are used
# in the SSH protocol.  The ssh-add tool may add new entries to this
# file to enable them; you may also add them manually.  Comment
# lines, like this one, as well as empty lines are ignored.  Lines do
# have a certain length limit but this is not serious limitation as
# the format of the entries is fixed and checked by gpg-agent. A
# non-comment line starts with optional white spaces, followed by the
# keygrip of the key given as 40 hex digits, optionally followed by a
# caching TTL in seconds, and another optional field for arbitrary
# flags.   Prepend the keygrip with an '!' mark to disable it.

# Ed25519 key added on: 2018-03-21 03:03:49
# Fingerprints:  MD5:39:fe:2b:cf:54:3a:c2:db:e4:b1:d2:70:a2:bc:82:fe
#                SHA256:LKeBCI5/EDJDMKzH4qBBhzJFJaBObn+APfoOzpLRpCI
A8BB036E2A737F56BB0D0B4F9700BC3DC4A9137F 0
发布了88 篇原创文章 · 获赞 33 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/ccmedu/article/details/101544660
gpg