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.