Page MenuHome GnuPG

GnuPG: Accept revocation certificates without UserID
Closed, WontfixPublic

Description

From @andrewgdotcom in T4393: GnuPG should always accept key updates even if the update does not contain UIDs:

In hockeypuck, we wish to distribute UID-less revoked TPKs, for the following reasons:

  1. A key owner has the legal right to delete their UIDs, since they are personal data.
  2. A key owner's revocation certificate should always be distributed, so that RTBF does not open a security hole.
  3. A revocation certificate cannot be verified without its primary key.

This means that keyservers must be able to store and distribute UID-less revoked TPKs. Further, in order to serve key material over HKP it must be in the form of a TPK, not a bare revocation certificate. While it may be possible to update the HKP spec, and require clients to implement support for bare revocations in their HKP handlers, this is complex on both the server and client side because it requires changes to parsing and request handling routines. On the other hand, relaxing the structural constraints involves less intrusive code changes, and has been implemented in many clients already.

Hockeypuck is a distributed keyserver on the same model as sks-keyserver, but addressing most of its design flaws. The proposed change is not specific to a centralised keyserver model, it just so happens that at the time it was proposed, keys.openpgp.org was the only example available.

I agree that primary keys without any signature on them at all are a potential abuse vector, but equally so are revocation certificates with no primary key. If the concern is that keys without certification signatures are easy to fake, surely a direct revocation signature provides a similar level of abuse protection? It is in some ways less resource-intensive to handle a revocation sig together with its primary key, as the sig can be verified and potentially discarded without looking up the local copy.

Event Timeline

aheinecke raised the priority of this task from Normal to Needs Triage.
aheinecke created this task.

Just to clarify, above ticket does not reflect my Opinion. It is a direct quote from a different ticket. It is my expert opinion that a combination of "Name <email> + Cryptographic Data" is not a personalised dataset since anyone can create it. But let us please not argue about that.

From a technical standpoint I think the most minimal revocations which are technically possible should be accepted and thus I endorse the feature request.

werner claimed this task.
werner added a subscriber: werner.

Actually the public key is personalized data as much as a mail address. In any case this is technically required and users take an informed decisions when they distribute their public key to a site not controlled by them.

In any case this is technically required

Can you elaborate on this? (Or give a pointer where the arguments can be found?)

From a technical standpoint I think the most minimal revocations which are technically possible should be accepted and thus I endorse the feature request.

@werner: I think you misunderstood the issue. This request was just about revocation. I also do not understand why a UserID should be required to revoke the primary key. I think it would be even possible to create such a revocation with GnuPG and then combine it with your new public key. To have a most minimal revocation + key update.

Hi,
so I talked to werner about this, and of course GnuPG accepts minimal revocations.
A revocation certificate. So that was my point. As he understood you, you wanted to revoke not the whole key but only a single user id but without the user id packet? Sorry I am not really the protocol expert. But for me a revoked key without any user ids sounds to me just like a "standard" revocation certificate revoking the whole key. And as said, that is well within the the Standard and accepted, and even used by GnuPG. E.g. in case of a keyrollover we attach such a minimal revocation certificate to WKD keys when we deliver key updates.

Maybe you could attach an example file of what you would like to send out and what GnuPG should in your opinion accept. And then we can see if we can maybe solve this issue or see if it is not already solved and just a misunderstanding? Tbh. I am a bit confused.

Thanks,
Andre

Hi, Andre.

Individual UID revocation sigs are not particularly useful, because they cannot be validated without the original UID. Such things are out of scope.

This particular feature is following a suggestion by Werner here: https://lists.gnupg.org/pipermail/gnupg-devel/2019-July/034427.html

in the case of a compromised key it might make sense to delete everything but the primary key and the revocation signature

A "revocation certificate" as currently handled by GnuPG is just the revocation packet and nothing else. Unfortunately without the primary key it is impossible for keyservers to validate a submitted revocation certificate, and so to prevent abuse we have to store at least the revocation packet and the primary key. Also, it is not clear from the current HKP spec whether a bare revocation certificate is a valid response - so it is doubtful whether all clients would accept us serving one. On the other hand, most clients already accept UID-less keys, so serving UID-less revoked TPKs (while not strictly valid) is much more likely to be interoperable.

It would also be very useful if we could serve subkeys attached to a revoked primary, so that lookups for subkey fingerprints would return a definitively verifiable revocation. We already have to handle such subkeys internally in order to maintain the search indexes, and it would be very convenient if we could continue with the common keyserver practice of serving up exactly what we store.

I'll be back later with some test artifacts. Thanks for your help!

Well, the quoted paragraph ended with a

But that's up to discussion.

;-).

If you need the fingerprint, why don't you take it from the revocation certificate - for many years it is in subpacket 33.

In fact a distributed database to lookup revocations by their fingerprint would be quite usefule. I assume you want the primary key to be able to verify that it is a valid revocation. What would you do if the revocation does not belong to the primary key - don't store the revocation? How does this help? Anyone could upload a revocation certificate with a non-matching primary key.

I'm curious about the parsing implications of this bit:

in case of a keyrollover we attach such a minimal revocation certificate to WKD keys when we deliver key updates.

Is that prepended to the key or appended? Most parsers (including the one in hockeypuck) assume that a keyring contains primary keys followed by certifications over the last-seen primary key. A bare revocation packet at a non-initial position in the stream would be interpreted as a corrupted signature over the previous signable packet (most likely a subkey) and discarded. Including the primary key before its revocation removes this ambiguity.

Hi, Andre.
...

Thanks for the explanation. To me this sounds very reasonable and I think that I am starting to better understand your use case in Hockeypuck.
Having a test example key + the intended revocation update would help at least me to dig into it a bit and see how this might conflict with RFC4880.

Hi, Werner.

If you need the fingerprint, why don't you take it from the revocation certificate - for many years it is in subpacket 33.

Yes, this is what we do when processing a submitted bare revocation. If we cannot find the primary key in the database though, the revocation is discarded.

What would you do if the revocation does not belong to the primary key - don't store the revocation? How does this help? Anyone could upload a revocation certificate with a non-matching primary key.

Yes, exactly. It would be trivially cheap to flood a keyserver with fake "revocation signatures" containing all-zeros or random noise, so we need to store the primary keys and verify the revocation packet is genuine. Otherwise it goes in the bitbucket...

Appended. Yes, it is considered an invalid signature and ignored. Anyone can insert an invalid signature. The trick here is that during import gpg tracks those invalid signatures and then tries to apply them to other keys. The use case here is this:

  • You create a key with address foo@example.org and publish it in the WKD
  • The key expired or for other reasons you don't want to use it anymore
  • You create a new key for foo@example.org and publish it to the WKD which overwrites the old one.
  • Another user _forcefully_ looks up foo@exmple.org and gets the new key.
  • However the user might still have the old key and did not get a revocation, so the old key might still be used.

With the revocation certificate for the old key attached to the new key, the old key will be reliable revoked.
This is actual real world problem of our customers which shows up from time to time.

The trick here is that during import gpg tracks those invalid signatures and then tries to apply them to other keys.

Yeah, that is the real trick. We can't do that on the keyservers - the next release will discard them, and that's a vast improvement over the current behaviour which is to blindly attach them to the preceding subkey, or maybe the previous primary key, it depends which serde lib they pass through first (data validation FTW! 😱). It's even more unclear how to handle designated revocation sigs - hockeypuck just treats them as vanilla third-party sigs and leaves the interpretation up to the client, but again this depends on them getting attached to the correct primary key in the first place...

I see no problem to return only revocation packets. Clients must verify them anyway against their public keys and the fingerprint makes this easy. Verification against a primary key delivered along the revocation is more or less useless because that primary key must anyway been looked up in the client's keyring and th local existance of a primary key is anyway required to ask a keyserver for a revocation.

I would suggest to just return the revocation certificate and handle your internal storage as you like. This has always worked on the client site since we implemented keyserver access.

This has always worked on the client site since we implemented keyserver access.

That's good to know, thanks.

Unfortunately we have no idea how common such support is among other clients. It's not in the HKP spec, so it's unknown whether it will be acceptable to return bare revocations to an arbitrary request - the keyservers have never done it before so it may or may not break on the toss of a coin. On the other hand, most clients have implemented support for UID-less keys in general, which would cover the more limited case here of UID-less revocations. I don't want to put the keyservers in the position where they have to detect/guess which client is making the request and tailor the response accordingly, as this would be extremely fragile.

@aheinecke as promised, attached some test vectors:

  1. test-key.asc: original test key with one uid and one subkey (from the hockeypuck test suite)
  2. test-key-revoke.asc: bare revocation sig for the above
  3. test-key-revoked-with-primary.gpg.asc: revoked key with primary key and revocation sig
  4. test-key-revoked-with-subkey.gpg.asc: revoked key with primary key, revocation sig, subkey and sbind

Number 3 at least should definitely be processed. It would be preferable if number 4 could also be processed, but we may be able to live without it for now.