I'm quite paranoid and absolutely want my privacy. Hence I use encryption pretty much everywhere: disks, backups, email etc. On the other hand I'm a sysadmin and as such lazy: I want things efficient and elegant. This post is a quick rundown on how (& how far) I personally manage to combine those somewhat incompatible goals on a technical level.

As an example of what I consider sufficient and fairly elegant use of crypto let's have a look at ssh.

One of the IMHO really nice features of ssh is the ssh-agent and forwarding connections to it via ssh: I always have an agent running on the box I'm sitting in front of and clear that thing when I go home/to work. With the agent I can connect to my work/home systems (which I admin myself and thus trust) and hop further without my passphrases travelling across the network: the local agent does all the crypto and only supplies that result to the requesting remote machine.

Also the agent fully pulls in the key when loading it: all my keys live only on a USB stick (gpg-encrypted in addition to the ssh key passphrase), and I never have that connected longer than it takes to load the key. The key enters the agent, resides in memory only and all is good. That way not even the encrypted key is stored on a disk on a remote machine ever (need I mention that swap on my machines is encrypted?).

So far, so good. However, working from home a fair bit means that I want access to my work email from at home. More precisely, I need to be able to handle my email on the workbox from at home. (The other possible solutions are not good enough for me: keeping things on an IMAP server that I access from at home would cover the reading side, but I also need to send stuff within the work environment. I also don't trust the work mail sewers much, and want full control over my mails: local storage, indexing and backup, exmh/mh-e on top of that etc. pp.)

The main items of interest here are signing and/or decrypting mails, but with the same behaviour regardless of being physically present or using a box remotely.

Now of course I could run gpg interactively but that sucks: I don't want to type in my passphrases repeatedly; they are long and hard to type. So what I'd like to do is using some ssh-agent-like thingie for gpg as the sole keeper of passphrases, which ideally would live only on the machine I'm sitting in front of. The remote-same-as-local requirement means that I need to switch the place passphrase prompts show up depending on where I am physically.

There is gpg-agent, but it doesn't work.

First problem I've had with gpg-agent: it uses unix-domain sockets to talk to gpg. Second: gpg-agent doesn't load the full key but only passphrase, so one needs to have the secret ring available on the remote box. Third problem: DISPLAY.

The first problem means I'd need a forwarder for unix-domain sockets. ssh does offer that only for ssh-agent's own and general X11 sockets, not for others. There is a more forwarding patch which adds this functionality to ssh, and it works quite nicely.

Still the gpg-agent gums up the works badly: gpg-agent can't be told to switch the display it shows a passphrase query on. You can nail it down to :0.0 but that doesn't help with remote connection; alternatively it can use what gpg tells it dynamically as the appropriate display, but gpg cannot be told to use a particular one either: it always passes on the current DISPLAY, which in my case is inherited from a long-running kuvert process that is by design unaware of me being connected remotely.

This sucks IMnsHO.

My overall solution: forget about gpg-agent, use the kernel key storage system with a pinentry program (borrowed from gpg-agent) and a small bit of glue of my own design.

The pinentry programs are nice, but they don't pass info via stdin. The kernel key storage system is great and request-key rocks, but I still needed a way to dynamically switch the display that things show up on.

The fix is simple: the key storage system gets one extra key, _display, which contains a |-separated list of environment variables. For local operation this is usually something like DISPLAY=:0.0|XAUTHORITY=/home/az/.Xauthority. This key is set to reflect my preferred current display (ssh-forwarded if I'm using this remotely).

/etc/request-key.conf refers to that key:

create  *       *               *               |/usr/local/bin/askkey %u %g %d %{user:_display}

This tells request-key to run my askkey glue with the appropriate arguments, including the dynamic display variables. (If the kernel key storage already holds that key, then that is returned without any interaction.) The askkey program then primes an environment suitable for the pinentry protocol and runs pinentry. Pinentry prompts me on the appropriate display and returns a passphrase, askkey feeds that to request-key which caches it in the kernel key storage and supplies it at the same time to the original requester. Done.

Neat, simple, efficient. I believe that's a quite decent solution.

Here is the source of the trivial askkey glue program. Share and enjoy.

[ published on Wed 08.04.2009 15:52 | filed in interests/crypto | ]
Debian Silver Server
© Alexander Zangerl