Category Archives: pgp

Pretty Good Phishing

PGP is not broken.  It has long been the best framework most of us have for digital identity, and a secure means of communication.

Sadly the same cannot be said for certain popular PGP tools, nor for vast numbers of tutorials out there.  The usage we enjoyed and became accustomed to for a quarter century will now lead at best to confusion, and at worst to mistakes that could defeat the entire purpose of PGP and leave users wide open to spoofing.  That applies both to longstanding users who understand it well, and to the newbie who has read and understood a tutorial.

The underlying problem is that 32-bit (8 hex character) key IDs are comprehensively broken.  The story of that is told at, by (I think) the people who originally demonstrated the issue.  It’s developed further since I last paid attention to it (and drew my colleagues’ attention to the need to stop using those 32-bit key IDs), in that an entire ‘shadow strong set’ has now been uploaded to the keyservers.  Those imposters were revoked by the evil32 folks, but with the idea being out there, anyone could now repeat that exercise and generate their own fake identities and fake Web of Trust.  And when a real malefactor does that, they’ll have the private keys, so there’ll be no-one to revoke them.

Let’s take a look at a recent sequence of events, when I rolled a release candidate for an Apache software package, and PGP-signed it.  Bear in mind, this is all happening in a techie community: people who have been happily using PGP for years.

[me] Signs a software bundle, upload it with the signature to web space.
[colleague] Checks the software, comes back with a number of comments.  Among them:

- Key B87F79A9 is listed as "revoked: 2016-08-16" in key server

Where does that come from?  I take great care of my PGP keys, and I certainly don’t recollect revoking that one.  To have revoked it, someone needs to have had access to both my private key and my passphrase, which is kind-of equivalent to having both the chip and the PIN to use my bank card (and that’s ignoring risks like someone tampering with my post on its way from the bank).  This is … impossible … alarming!

Yet this is exactly what happens if you RTFM:

% gpg --verify bundle.asc
gpg: Signature made Sun 16 Apr 2017 00:00:14 BST using RSA key ID B87F79A9
gpg: Can't check signature: public key not found

We don’t have the release manager’s public key ( B87F79A9 ) in our local system. You now need to retrieve the public key from a key server.

% gpg --recv-key B87F79A9
gpg: requesting key B87F79A9 from HKP keyserver
gpg: key B87F79A9: public key "Nick Kew <me>" imported
gpg: Total number processed: 1
gpg:           imported: 1

That’s a paraphrased extract from a real tutorial (which I intend to update, if noone else gets there first).  It was fine when it was written, but now imports not one but two keys.  Here they are:

$ gpg --list-keys B87F79A9
 pub 4096R/B87F79A9 2011-01-30
 uid Nick Kew <niq@apache...>
 uid Nick Kew (4096-bit key) <nick@webthing...>
 sub 4096R/862BA082 2011-01-30

pub 4096R/B87F79A9 2014-06-16 [revoked: 2016-08-16]
 uid Nick Kew <niq@apache...>

Both appear to be me; one is really me, the other an imposter from the evil32 set.  It’s easy to see when we know what we’re looking for, but could be confusing if unexpected!

The problem goes away if we use 64-bit Key IDs, or (nowadays strongly recommended) the full 160-bit (40 character) fingerprint.  It is computationally infeasible anyone could impersonate that, and indeed, they haven’t.

$ gpg --fingerprint B87F79A9
 pub 4096R/B87F79A9 2011-01-30
 Key fingerprint = 3CE3 BAC2 EB7B BC62 4D1D 22D8 F3B9 D88C B87F 79A9
 uid Nick Kew <niq@apache...>
 uid Nick Kew (4096-bit key) <nick@webthing...>
 sub 4096R/862BA082 2011-01-30

pub 4096R/B87F79A9 2014-06-16 [revoked: 2016-08-16]
 Key fingerprint = C74C 8AA5 91CB 3766 9D6F 73C0 2DF2 C6E4 B87F 79A9
 uid Nick Kew <niq@apache...>

The imposter’s fingerprint is completely different from mine.  It’s not PGP that’s broken, it’s the use of 32-bit/8-character key IDs in our tools, our tutorials, and our minds, that’s at fault.

However, the problem is a whole lot worse than that.  It’s not just my key (and everyone else in the Strong Set at the time of the evil32 demo) that has an imposter, it’s the entire WoT.  Let’s see if WordPress will let me present these side-by-side if I truncate the lines a bit.  The commandline used here is

$ gpg --list-sigs [fingerprint] |egrep ^sig|cut -c14-50|sort|uniq|head -5

which lists me:

My Key Imposter
010D6F3A 2012-04-11  dirk astrath (mo
02D1BC65 2011-02-07  Peter Van Eynde 
0AA3BF0E 2011-02-06  Christophe De Wo
16879738 2011-02-07  Markus Reichelt 
1DFBA164 2011-02-07  Bernhard Wiedema
010D6F3A 2014-08-05  dirk astrath (mo
02D1BC65 2014-08-05  Peter Van Eynde 
0AA3BF0E 2014-08-05  Christophe De Wo
16879738 2014-08-05  Markus Reichelt 
1DFBA164 2014-08-05  Bernhard Wiedema

The first field there is the culprit 8-hex-char Key IDs for my signatories and their evil32 doppelgangers.  The only clue is in those dates, which would be easy to overlook.  Otherwise we have a complete imposter WoT.   Those IDs offer no more security than a checksum (such as MD5 or SHA) if used without due care, and without a chain of trust right back to the user’s own signature (which is something you probably don’t have if you’re not a geek).

There are a lot of tools and tutorials out there that need updating to prevent this becoming yet another phisher’s playground.  Tools should not merely stop displaying 8-character key IDs, they shouldn’t even accept them.  I don’t think mere disambiguation is enough when an innocent user might thoughtlessly just select, say, the first of competing options.

I’ve already been diving in to some of those tutorials where I have write access to update them, but the task is complicated by having to work in the context of a document that deals with more than just the one thing, and without adding too much complexity for readers.  So I decided to work through the story here first!

Scripting with gpg

I have a build script that may, as a matter of convenience, download and build a third-party software package.  Before the build script goes into any release, I want to tighten up its security to ensure it verifies the PGP signature on the package.

OK, I can do that in a Makefile using two separate targets: the tarball, and the verified tarball.  I thought I could make the latter a link to the former, using something like:

gpg –verify $(TARBALL).asc $(TARBALL) \
|| (echo “### Please verify $(TARBALL) ###” && exit 1)

However, this is failing me, because gpg is too trusting:

$ gpg –verify nginx-1.7.3.tar.gz.asc nginx-1.7.3.tar.gz
gpg: Signature made Tue 8 Jul 14:22:56 2014 BST using RSA key ID A1C052F8
gpg: Good signature from “Maxim Dounin <email.suppressed>”
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: B0F4 2533 73F8 F6F5 10D4 2178 520A 9993 A1C0 52F8

$ echo $?

(OK, now you know the identity of $(TARBALL))

It has not verified that the signature is trusted, but it still thinks all’s well.  Ouch!  I can verify the signature manually (if rather weakly) but I’d rather not try to script that.  Nor do I want to concern myself with issues that might change with each new nginx release, or with changes of pgp keys.

A bit of googling finds this message, from which it appears this was a known bug but fixed in GnuPG version back in 2006 (and yes, my gpg version is more recent than that)!  Was that a non-fix that only tells you if it’s a BAD signature or no PGP data at all?  That would be no more useful than an MD5 or SHA checksum!

OK folks, what am I missing?  What do you use to script the verification of a package?


I’ve got around to the most tedious post-FOSDEM chore: keysigning.  Last night I signed 89 keys verified at the keysigning, and this morning I imported a bunch of signatures people have mailed me (though I expect the latter may continue arriving for a while).  All great for building a web of trust, especially in terms of bootstrapping the new 4096-bit key.

The FOSDEM keysigning event itself was … different.  It took place outdoors, with a gusting wind that made wielding a wodge of paper quite challenging, let alone writing on it, all the while with an extra hand required to exchange identity documents with everyone.  At least it didn’t rain!

This year’s FOSDEM weekend was quite mild for early February – in contrast to the past two years.  I was fine in just my middling-weight fleece and good layer of natural organic insulation, but then I’m always fine when others are shivering.  It was evidently a bit more of an ordeal for some from warmer climes, leaving one with a hint of a moral dilemma.  Surely as a gentleman I should go to the aid of the (very attractive) spanish girl who was visibly suffering from cold/wind?  But alas, that defeats the purpose of being out there in the first place, not to mention being open to …. interpretation.  Maybe I’ll take Don Quixote to next year’s FOSDEM, to be mentally prepared for chivalrous folly 😉

If anyone thinks I should have signed their key but haven’t, feel free to drop me a line.  If it’s because I didn’t in fact make a note of having verified your identity, then sorry, no deal.  But it could also be that I overlooked someone when reviewing my notes last night, in which case I’ll be happy to re-check the notes for the tick against your key.

FOSDEM, and new PGP key

I’ve booked my travel and hotel for FOSDEM.  Arriving Friday early evening, leaving Monday after lunch, so I have a few hours beyond the core event.  Hope to meet some of my readers in person next weekend in Brussels!

In preparation for FOSDEM, I uploaded my PGP key to FOSDEM’s server for the keysigning – assuming I make it this year!  And in doing so, I found a spare round tuit to generate a new 4096-bit key in anticipation of a time when Moore’s law overtakes my existing 1024-bit key.  My new key has number B87F79A9 and fingerprint
3CE3 BAC2 EB7B BC62 4D1D  22D8 F3B9 D88C B87F 79A9
and should by now be propagating its way around the keyservers, along with my signature with the old key.

This year I’ll be actively looking at the jobs desk, for anyone whose needs might fit my expertise and aspirations.


We had a very small keysigning last Wednesday at ApacheCon (thanks Jean-Frederic Clere for organising it). I exchanged identity details with about 20 others, many of whom I already know.

Today I got around to digging up my list of details, and signing 11 keys I hadn’t already signed from some earlier event. If you were there and I got your details, my signature on your key should now appear on the keyservers.


As ever at ApacheCon, Sander Temme organised a PGP keysigning party. This year (unlike last) I got my arse into gear in time to make it. There are some new signatures on my key. And I’ve just been through signing keys of people whose identities I confirmed, and who I hadn’t already signed. A few of them were surprising: people whose keys I’d have guessed I’d already signed. And one who needed a new key signing, as the one I’d signed previously was on a laptop that got stolen, so he revoked it.

The keys I’ve signed, I’ve uploaded to the keyservers. Generating ascii-armoured signatures and mailing them to people is more faff than I want to engage in just now