Last month the debian package for gnupg was changed in the unstable branch from providing version 1.4 to providing 2.1. Users of debian jessie and even stretch in principle shouldn't be concerned by this change. But for sid users this is a major change and some ppl might need a bit of guidance through the process... well at least I needed some. Here's a post about what issues I encountered and how I fixed them or my comprehension of their cause.

The change needs some readjusting, but it is for good reasons. The use of agents is interesting for some security reasons, and the storage format is way faster than it was in gpg 1.4. This and the codebase for 2.1 is apparently in a way better shape.

First and foremost, ppl who read this post should probably familiarize themselves with the changes that the version brings.

Auto-migration of keys happened long ago

First thing that I got sorted out was this: I had had gnupg2 installed on my computer for quite a while already. It was installed automatically as a dependency to password-store. Normally gpg2 automatically migrates your public and secret keyrings automatically for you to the new storing format. This is super neat, but it happened automatically when I first used password-store, and then I didn't migrate to using gpg2 (oops).

Re-importing secret keyring

During the time I persisted in using 1.4, I created a new authentication subkey for use with monkeysphere. This subkey was not automatically migrated when I finally switched to gpg 2.1 thanks to the package change. This is normal: the automatic migration happened a bunch of time ago.

The fix was easy, reimport secret key material:

gpg --import ~/.gnupg/secring.gpg

Using the new, faster public key storage

You also probably want to move your public keyring to the new storage format which is way faster. As described in the GnuPG 2.1 release notes linked above, you can achieve this with the following series of commands:

cd ~/.gnupg
gpg --export-ownertrust >otrust.lst
mv pubring.gpg publickeys
gpg --import-options import-local-sigs --import publickeys
gpg --import-ownertrust otrust.lst
mv pubkeys pubring.gpg

This will create a file named pubring.kbx which is the new storage file. The above commands ensure that you properly import all public keys, public and local signatures and keep your ownertrust intact. The file pubring.gpg is then kept in place so that you can still use it with gpg1.

Agents

GnuPG 2.1 now relies heavily on agents. This is actually nice since only one process is holding onto your key material and the others just ask for it to the agent. It also means that network access is totally segmented off to a process of its own. So you have at least two agents: gpg-agent and dirmngr. Those two agents are started automatically by gpg commands, which is convenient.

Dirmngr configuration

In order to contact the wild, wild, Internet, gpg will ask a new agent called dirmngr to access the network and report its findings. You'll be using it among other things to search for keys and to publish your newly updated key for those signatures you've acquired, or UIDs you added.

For this you need to configure dirmngr, see man (8) dirmngr for a list of options. You can set the same options in ~/.gnupg/dirmngr.conf. For example you can set the keyserver to hkps://hkps.pool.sks-keyservers.net.

If the dirmngr doesn't want to start, the only info you'll get when trying to search for keys with gpg is that connection to the dirmngr timed out. This is pretty annoying: you'll get no detail of why it just won't work.

In order to debug what's happening, you can run the dirmngr manually and it should tell you what's wrong. For example, here we have a syntax error on a config option:

$ dirmngr
dirmngr[29289.0]: /home/gabster/.gnupg/dirmngr.conf:13: invalid option

Once it starts and tells you OK Dirmngr 2.1.15 at your service then you can quit and try doing that gpg network operation you wanted to do.

gpg-agent and SSH keys

I've been using Monkeysphere for some time now to provide access to servers. With gpg 1.4 in order to be able to use the key material, it was necessary to export it to the ssh-agent process. Now it's possible to ask gpg-agent to expose the keys you want to SSH and be used as the ssh-agent process. This means there's no need to use monkeysphere s anymore!

In order to do this you first need to enable this support for the agent. In ~/.gnupg/gpg-agent.conf, add the line:

enable-ssh-support

Then restart the gpg-agent. (you can kill the process and then start it again with gpgconf --launch gpg-agent. If you're using systemd, see below)

Once this is done, you should see a socket file in /var/run/user/$uid/gnupg/S.gpg-agent.ssh. We want to point ssh to this socket so that it communicates directly with the gpg-agent. Add this to your preferred shell initscript; in my case ~/.bashrc:

if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
  export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi

The if block is there because if you run gpg-agent --daemon /bin/bash for example, the environment will be set by the agent itself and the variable that we're checking against will be set. The SSH_AUTH_SOCK variable tells SSH to talk to this socket for communicating with the ssh-agent.

Since SSH also doesn't communicate the current TTY name to gpg-agent, we need to set another variable in order to communicate the current TTY name to gpg-agent. This is useful so that gpg-agent knows where to send prompts for passwords. Again in your favorite shell initscript, add the following:

export GPG_TTY=$(tty)

Now we only have two more details to sort out.

Configure which keys/subkeys are exposed to SSH

The gpg-agent doesn't expose all of your key material to the SSH process. In fact you need to specify which sub-keys should be exposed. For this you need to find the subkey's keygrip. Run this to find it:

$ gpg -k --with-keygrip <your@uid.com>
pub   rsa4096/0xC4ADA67875247FCF 2011-04-25 [SC] [expires: 2016-11-03]
      Key fingerprint = 5F73 EFCB 02FC E345 C107  7477 C4AD A678 7524 7FCF
      Keygrip = BF3DB7C51C596974DF58DC5860BE9F88A12CA19F
uid                   [ unknown] Perception <perception@rt.koumbit.net>
uid                   [  undef ] Network operations center <noc@koumbit.org>
uid                   [  full  ] Koumbit frontdesk <info@koumbit.org>
uid                   [  full  ] Koumbit support <support@koumbit.org>
uid                   [ unknown] Production <prod@rt.koumbit.net>
uid                   [ unknown] Services <services@rt.koumbit.net>
uid                   [ unknown] Koumbit sales <ventes@koumbit.org>
uid                   [ unknown] Facturation <facturation@rt.koumbit.net>
sub   rsa4096/0x32873884B600AD97 2011-04-25 [E] [expires: 2016-11-03]
      Keygrip = CD56911C4CE3173BD4D0AE5DCDBA29F738F14B39
sub   rsa4096/0xDC837CFBE0D1124E 2015-08-20 [A]
      Keygrip = C87589642DE00D1306350DD5C20F35C409427D45

In this example the key has one subkey with authentication capability (A). We'll expose it to SSH by dropping the hexadecimal keygrip value on a line in ~/.gnupg/sshcontrol:

echo "C87589642DE00D1306350DD5C20F35C409427D45 0" >> ~/.gnupg/sshcontrol

The trailing 0 in the echo above is the TTL of the key before SSH needs to revalidate with gpg-agent. In this case, we set it to 0 so that it doesn't expire: you'll get prompted for the key's password only upon first use.

Once this is done, you can verify that the key is exposed by listing keys with ssh-add:

$ ssh-add -l
4096 SHA256:7mb85m/biclOdJ4JB62rmrWe8nfV/Nwcmwop/Svdo3k (none) (RSA)

Success!

Once configuration is correctly established, you can also import ssh keys from default files (e.g. id_ed25519) by using ssh-add without parameters.

Automatically starting the gpg-agent

When using gpg-agent for provide SSH with key material, you need to somehow automatically start the gpg-agent by yourself. GnuPG commands will auto-start the agent for you, but SSH doesn't know (and probably doesn't care) how to do this.

The simplest method is to call gpg-connect-agent /bye in your shell initscript.

But you can also use systemd to do this for you which means the agent will be started even if you don't have a terminal open. First you need to ensure you have a package installed, since without it communication between gpg-agent and your X session will be impossible:

sudo apt install dbus-user-session

With this in place, you can enable the service for your user:

gpgconf --kill gpg-agent
systemctl --user enable gpg-agent.service
systemctl --user start gpg-agent.service

This is not the terminal you are looking for

Now that you have a gpg-agent process running, you might notice that if you move around from your X session to an SSH connection towards your computer (some ppl do weird things... hey! my laptop is crashing all the time, but if I ssh in it doesn't... don't judge!) then the password prompts will not show up, or will show up in the wrong place. gpg commands normally pass the display and tty information to the agent so that things just work, but SSH doesn't pass this information. In such a case you'll probably end up getting this utterly useless message:

sign_and_send_pubkey: signing failed: agent refused operation

So you might need to call this command to make the gpg-agent point to the right place for the prompts:

gpg-connect-agent updatestartuptty /bye

After this you should get prompted for passwords and you should be able to connect to hosts with your keys.