"I'm not proud of being a congenital pain in the ass. But I will take money for it."

32-bit PGP KeyID Delenda Est!

Mon 11 June 2018 | -- (permalink)

While it's no longer fashionable among the cool kids, some of us still use PGP, generally in its modern incarnation, GPG. I'm not going to defend that here, just observe that PGP is used in a number of bits of critical network infrastructure, so it still matters.

GPG, like many programs, attempts to maintain backwards compatibility with older code. Sometimes this is a mistake: in the case in point, GPG's attempt to support "traditional" 32-bit PGP KeyIDs sure is.

As is usually the case with cryptographic protocols, a PGP KeyID is the output of a cryptographic hash of a public key and a few bits of metadata. The current fingerprint hash algorithm is SHA-1, which is a bit dated at this point, but is still not exactly trivial to spoof. The problem is that even a SHA-1 hash is kind of long, so PGP user interfaces have always offered a truncated version of the hash, called the KeyID.

GPG has keyid-format setting which one can set in one's configuration file to change to a slightly more reasonable 64-bit KeyID format, or even to force the full fingerprint with no truncation, but by default one gets the 32-bit KeyID. As it happens, I set this option to use the 64-bit KeyID so many years ago I had forgotten that it even existed until a couple of friends who had not set it got bitten by the default.

It seems that somebody thought it would be a clever idea to spam the global PGP key servers with fraudulent keys whose 32-bit KeyIDs collide with real keys and whose UID information is copied from the corresponding real keys.

This is pretty clearly not an accident, and we're not talking about just a handful of keys here, we're talking well over ten thousand keys at minimum (this is all visible if one looks, but who thinks to look for something like that?). Furthermore, these fraudulent keys sign each other in what looks at least at first glance like a plausible copy of the real web of trust.

I say "at minimum" because the technique for finding these fraudulent keys is pretty simple, in both senses of the word: start by retrieving a known offender (the fraudulent key pretending to be mine will do), check what other keys signed it, retrieve those keys, lather, rinse, repeat. By the fourth iteration, this process had retrieved more than twelve thousand fraudulent keys and it was taking hours just to regenerate the trustdb, so I stopped there, because it seemed likely that adding another degree of separation would place unacceptable load on the key server I was using.

So I went looking to see what the Net of a Million Lies had to say about this. Didn't find much, which was a bit surprising, given that Evil32 was presented at DefCon four years ago. Apparently that was good for one snarky article in The Register, then everybody went back to sleep (see "no longer fashionable among the cool kids").

I did find one site speculating that this incident was some kind of phishing attack, which would be plausible except for one other oddity: almost all of these fraudulent keys purport to have been created on 2014-06-16 and revoked on 2016-08-16. Revoked keys aren't particularly useful for a phishing attack, so if that's what this was, this particular incident is (mostly) over. Or it might just be some kind of DoS attack on the data in the PGP key server system.

It's important to note that this isn't a failure of the cryptography, or even of the software per se, that's all working as designed. The problem is the user interface, and the humans driving it. GPG's user interface is (in)famously confusing, not that anything else in this space has ever done all that much better. Key management is hard.

It's also worth noting that "vanity PGP keys" have apparently been a thing for years (who knew?) and that there are publicly available tools which will generate PGP keys with a given KeyID to order. This wouldn't matter so much if users:

  • Remembered to use the full untruncated fingerprint when verifying, every damned time; and

  • Remembered that the UID attached to a key is completely worthless until the key has been verified via out-of-band means using the full fingerprint (at least).

But of course users won't remember that. The friends who drew my attention to this problem are highly trained computer security professionals, and they almost missed what was happening here; in the end, we only caught this because of our general paranoia that anything incomprehensible in security software is suspect by definition.

Take-aways from this incident:

  1. If you use GPG and haven't selected one of the long form KeyIDs, do so, NOW. Even keyid-format long is better than the default. keyid-format none, in typical incomprehensible GPG fashion, actually means "don't truncate the fingerprint hash at all, display the whole thing on a separate line", so none is better than long, go figure. Yes, GPG's user interface is a problem.

  2. GPG's default KeyID format really needs to change, backwards compatibility be damned.

  3. The global PGP key server system contains (at least) half a ton of garbage. It'd be nice to clean that out, but those key servers are operated as a public service, and it hardly seems worth the trouble of mucking them out without some kind of plan for how to prevent this from happening again...which is indeed one of the real weak points of the PGP world, by definition there is no central authority, and that's a feature, so who's going to figure out which are the good keys and which are the bad ones?

  4. "If you don't understand it, it's dangerous." --Larry Niven