Subject: [openpgp] [RFC4880bis PATCH] Deprecate "Revocation Key", replacing with full-key "Designated Revoker"

From: Daniel Kahn Gillmor <[email-masked]>
Date: Wed, 31 Jul 2019 16:34:44 -0400

The "revocation key" subpacket is problematic.  It is the the most
fragile piece of the specification wrt the fingerprint (collisions
against a fingerprint can create surprising revocation effects).  And
it is potentially difficult to rely on for clients which might not be
able to find the revoking key (for example, if keyservers are
unavailable).

It is also not currently widely used.

This patch to the spec deprecates the "revocation key" subpacket and
replaces it with a "designated revoker" subpacket that includes the
full key, rather than the fingerprint.

The only cost here appears to be slightly increased size of the new
subpacket type by comparison, which is an entirely reasonable cost
that the (rare) users of this feature should be able to bear.

I've cargo-culted in the "class" octet from "Revocation Key".  I'm not
sure that octet is particularly useful, and i'd be happy to drop it if
folks want to, but i didn't want to muddle the waters with a semantic
change in addition to this mechanical change.

Signed-off-by: Daniel Kahn Gillmor <[email-masked]>
---
 middle.mkd | 61 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 46 insertions(+), 15 deletions(-)

diff --git a/middle.mkd b/middle.mkd
index 51f71a6..a2d3ae6 100644
--- a/middle.mkd
+++ b/middle.mkd
@@ -757,7 +757,7 @@ These meanings are as follows:
       directly on a key.  It binds the information in the Signature
       subpackets to the key, and is appropriate to be used for
       subpackets that provide information about the key, such as
-      the Revocation Key subpacket.  It is also appropriate for
+      the Designated Revoker subpacket.  It is also appropriate for
       statements that non-self certifiers want to make about the
       key itself, rather than the binding between a key and a
       name.
@@ -766,7 +766,7 @@ These meanings are as follows:
   :   Key revocation signature. The signature is calculated
       directly on the key being revoked. A revoked key is not to
       be used.  Only revocation signatures by the key being
-      revoked, or by an authorized revocation key, should be
+      revoked, or by a designated revoker, should be
       considered valid revocation signatures.
 
 0x28
@@ -774,7 +774,7 @@ These meanings are as follows:
       directly on the subkey being revoked. A revoked subkey is
       not to be used.  Only revocation signatures by the top-level
       signature key that is bound to this subkey, or by an
-      authorized revocation key, should be considered valid
+      designated revoker, should be considered valid
       revocation signatures.
 
 0x30
@@ -782,7 +782,7 @@ These meanings are as follows:
       earlier User ID certification signature (signature class
       0x10 through 0x13) or direct-key signature (0x1F).  It should
       be issued by the same key that issued the revoked signature
-      or an authorized revocation key.  The signature is computed
+      or a designated revoker.  The signature is computed
       over the same data as the certificate that it revokes, and
       should have a later creation date than that certificate.
 
@@ -1039,7 +1039,7 @@ The value of the subpacket type octet may be:
            9   Key Expiration Time
           10   Placeholder for backward compatibility
           11   Preferred Symmetric Algorithms
-          12   Revocation Key
+          12   Revocation Key (deprecated)
     13 to 15   Reserved
           16   Issuer
     17 to 19   Reserved
@@ -1058,6 +1058,7 @@ The value of the subpacket type octet may be:
           32   Embedded Signature
           33   Issuer Fingerprint
           34   Preferred AEAD Algorithms
+          35   Designated Revoker
   100 to 110   Private or experimental
 
 An implementation SHOULD ignore any subpacket of a type that it does
@@ -1294,18 +1295,48 @@ description of the syntax is found in [](#regular-expressions) below.
 
 #### Revocation Key
 
-(1 octet of class, 1 octet of public-key algorithm ID, 20 or 32 octets
-of fingerprint)
+(1 octet of class, 1 octet of public-key algorithm ID, 20 octets
+of v4 fingerprint)
 
-V4 keys use the full 20 octet fingerprint; V5 keys use the
-full 32 octet fingerprint
+This mechanism is deprecated.  Applications MUST NOT generate such a
+subpacket.  An application that wants this functionality SHOULD
+instead produce a Designated Revoker subpacket described in
+[](#designated-revoker).  The advantage of the Designated Revoker
+packet is twofold: it can be used unambiguously to validate
+revocations without causing an extra lookup; and it is resistant to
+any flaws found in the fingerprint.
 
-Authorizes the specified key to issue revocation signatures for this
-key.  Class octet must have bit 0x80 set.  If the bit 0x40 is set,
-then this means that the revocation information is sensitive.  Other
-bits are for future expansion to other kinds of authorizations.  This
-is only found on a direct-key self-signature (type 0x1f).  The use on
-other types of self-signatures is unspecified.
+This packet authorizes the specified v4 key to issue revocation
+signatures for this key.  Class octet must have bit 0x80 set.  If the
+bit 0x40 is set, then this means that the revocation information is
+sensitive.  Other bits are reserved and MUST be 0.  This is only found
+on a direct-key self-signature (type 0x1f).  The use on other types of
+self-signatures is unspecified.
+
+If the "sensitive" flag is set, the keyholder feels this subpacket
+contains private trust information that describes a real-world
+sensitive relationship.  If this flag is set, implementations SHOULD
+NOT export this signature to other users except in cases where the
+data needs to be available: when the signature is being sent to the
+designated revoker, or when it is accompanied by a revocation
+signature from that revoker.  Note that it may be appropriate to
+isolate this subpacket within a separate signature so that it is not
+combined with other subpackets that need to be exported.
+
+#### Designated Revoker
+
+(1 octet of class, N octets of public key)
+
+Authorizes the embedded public key to issue revocation signatures for
+this key.  Class octet must have bit 0x80 set.  If the bit 0x40 is
+set, then this means that the revocation information is sensitive.
+Other bits are for future expansion to other kinds of authorizations.
+This is only found on a direct-key self-signature (type 0x1f).  The
+use on other types of self-signatures is unspecified.
+
+The remaining N octets of the of the packet MUST consist of a complete
+Public-Key Packet (tag 6) that can be used to verify revocation
+signatures.
 
 If the "sensitive" flag is set, the keyholder feels this subpacket
 contains private trust information that describes a real-world
-- 
2.20.1

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Wed, 31 Jul 2019 16:37:43 -0400

> full key, rather than the fingerprint.

this is also at https://gitlab.com/openpgp-wg/rfc4880bis/merge_requests/18

     --dkg

---

From: "Neal H. Walfield" <[email-masked]>
Date: Wed, 31 Jul 2019 22:55:11 +0200

Hi Daniel,

Justus proposed an embedded TPK subpacket for cases like this with
this as a motivating example.  See:

  Subject: [openpgp] Embedded TPK subpacket
  From: Justus Winter <[email-masked]>
  Date: Mon, 25 Mar 2019 10:20:45 +0100
  Message-ID: <[email-masked]>

  https://mailarchive.ietf.org/arch/msg/openpgp/F1Wdrldzd3k9tqOos4hmokOV0r0

Do you think a point solution is better?

Thanks,

:) Neal

On Wed, 31 Jul 2019 22:34:44 +0200,
Daniel Kahn Gillmor wrote:
> _______________________________________________
> openpgp mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/openpgp
>

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Wed, 31 Jul 2019 18:01:12 -0400

> Do you think a point solution is better?

sure, i think Embedded TPK is interesting, but it's much more than is
needed for having a designated revoker.  The additional complexity comes
at a cost i'd rather not impose for implementers.

For a designated revoker, we don't care about who the revoking key
belongs to.  we just care that we know it.

once you have an embedded TPK, then you have some kind of potentially
recursive situation (as Marcus pointed out).  it's also strange because
a TPK is not a static entity -- it changes over time as the composable
certificate mutates.  So embedding such a thing in a self-sig is looking
at a particular version, and implies things like expiration, etc.  we
don't want an endpoint that is trying to process a designated revoker to
be distracted by the additional non-public-key packets.

it's also not clear that an embedded TPK subpacket in a self-sig that
also has a "Revoker Key" subpacket is necessarily referring to the
revoker key itself -- the semantics are potentially ambiguous, as an
embedded TPK subpacket in a different signature packet would have
different semantics.  I'm not fond of that kind of ambiguity.

Additionally, what if there are multiple embedded TPK subpackets, or if
the embedded TPK subpacket's primary key fingerprint doesn't match the
"revoker key" fingerprint?

Finally, if a client processes a direct-key signature with a "revoker
key" subpacket that *doesn't* have an embedded TPK, they're just back in
the soup.  I think the deprecation story is clearer to just burn the old
subpacket type entirely (it was originally specified very much in
v4-only mode), and have an unambiguous subpacket for this use case.  It
is at least marginally simpler for an implementation to say "i don't
support 'revoker key' but i do support 'designated revoker'" than it is
to say "i only support 'revoker key' if it is in a direct key signature
that contains exactly one embedded TPK whose primary key fingerprint
matches the 'revoker key' fingerprint". 

In general, i think we should not aim for maximum flexibility in the
format specification, because that flexibility is a major cost for
implementers.  I'd rather identify the specific use cases we want to
support and clearly and unambiguously ensure that the spec meets those
use cases.

        --dkg