I recently started using an OpenPGP smartcard for my PGP keys. If you don’t know what one of these is, it’s a credit card sized card which you store your PGP keys on. It is very different from storing them on a USB drive. You can write your PGP keys onto the card, but they can not be read back off. When you want to sign or decrypt some data, GnuPG sends the data to the card, which performs the crypto operations on board, and sends the results back. The main reason this is good, is because an attacker who compromises your laptop and installs a trojan and a keylogger, still can’t get access to your keys.

One of the problems with this setup is that observation attacks like shoulder surfing or keylogging suddenly become much easier. Previously my keys were stored, password protected, in a keyring on my hard drive. If you observed me entering my password, you’d still need to compromise my laptop in order to access the keyring. When I’m not using my laptop, it is either locked or turned off, and my keyring is protected by full disk encryption. So unless you manage to steal it whilst I’m using it and logged in, it’s no use to you. However, my smartcard is never “off”. If you watch me enter my passphrase when using my smartcard, all you need to do is steal my smartcard in order to get access to my keys. You can just mug me or pick pocket me as I’m walking down the street.

To get around this problem, I’ve implemented a solution that adds a second layer of password protection. Now, when you observe me entering my password, what you’re actually observing is my password which decrypts the smartcards password from my laptops disk. I implemented this at the pinentry layer, so it is completely transparent. Pinentry is a program that gpg-agent calls when it wants to prompt the user for the password. I wrote a custom pinentry application which wraps around your normal system pinentry application, and intercepts the password response, using it to decrypt the real password, before passing that back to gpg-agent. I use gpg’s “–symmetric” option for this.

So now, to compromise my PGP keys, you need to observe me entering a password, then compromise my laptop to get the “real” smartcard password, and steal the smartcard too.

The application is written in Perl, is free, open source and can be fetched from my github repository. You just use it exactly like a normal pinentry program. Add an entry to your ~/.gnupg/gpg-agent.conf like this:

pinentry- program /path/ to /pinentry-passpin.pl

If you run it with the “–add-key” option, you are prompted for your real password, and the password which you would like to use instead. Your real password is encrypted and stored in ~/.pinentry-passpin