Subject: [openpgp] Key expiration ambiguity in rfc4880

From: Andrew Gallagher <[email-masked]>
Date: Tue, 4 Jan 2022 14:54:27 +0000

FYI I have just opened merge request 113 [1] to clarify an ambiguity in 
the definition of key expiry times. RFC4880 currently states:

   5.2.3.3.  Notes on Self-Signatures	

    ...

    Subpackets that appear in a certification self-signature
    apply to the user name, and subpackets that appear in the subkey
    self-signature apply to the subkey.  Lastly, subpackets on the
    direct-key signature apply to the entire key.

and:

   5.2.3.6.  Key Expiration Time

    (4-octet time field)

    The validity period of the key.  This is the number of seconds after
    the key creation time that the key expires.  If this is not present
    or has a value of zero, the key never expires.  This is found only on
    a self-signature.

Most implementations interpret these paragraphs as meaning that subkey 
expiration times are calculated relative to the subkey's own creation 
time. However, it has been discovered [2] that Hockeypuck (uniquely?) 
uses the primary key creation time to calculate subkey expirations. This 
has led to odd situations where some subkeys appear to expire earlier 
than intended - and in some cases before they were created.

This is merely a cosmetic issue in Hockeypuck, as subkey expiration 
times are only calculated (AIUI) for human-readable display purposes; 
however it does expose a potential ambiguity in the RFC that IMO should 
be tidied up. To this end, I propose to insert the following into 
section 5.2.3.6:

```
For a direct signature, the key creation time is that of the primary key.
For a subkey binding signature, the key creation time is that of the subkey.
```

[1] https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/113
[2] https://github.com/hockeypuck/hockeypuck/issues/140

-- 
Andrew Gallagher

---

From: Andrew Gallagher <[email-masked]>
Date: Sat, 8 Jan 2022 18:55:34 +0000

On 04/01/2022 14:54, Andrew Gallagher wrote:
> the definition of key expiry times.

I have opened a further issue 71 [1] to propose deprecating the tricky 
and redundant "Key Expiration Time" subpacket in V5 signatures. It can 
be substituted in all known use cases by the simpler "Signature 
Expiration Time" subpacket, which has compatible semantics and is much 
easier to work with.

[1] https://gitlab.com/openpgp-wg/rfc4880bis/-/issues/71

-- 
Andrew Gallagher

---

From: Andrew Gallagher <[email-masked]>
Date: Thu, 13 Jan 2022 11:23:08 +0000

On 08/01/2022 18:55, Andrew Gallagher wrote:
> and redundant "Key Expiration Time" subpacket in V5 signatures.

The more often I re-read section 5.2.3.3 the more convinced I am that it 
should be rewritten in its entirety. We may not wish to be prescriptive 
about how signatures should be interpreted in an application context, 
but it is crucial for determining the properties of public keys 
themselves that *self*-sigs convey the intent of the key owner precisely 
and accurately.

These are not crypto-refresh issues, so IMO we should park V5 sigs for 
now and wait for a re-charter so that we can unambiguously define the 
semantics of V5 self-sigs at the first attempt.

Some obvious problems in the existing text include:

```
If the key is located
by Key ID, the algorithm of the primary User ID of the key provides
the preferred symmetric algorithm.
```

What happens if the self-sig over the primary user ID has expired but 
there are other unexpired UIDs? What if the other UID sigs disagree with 
each other? What if there is a direct sig?

```
An implementation that encounters multiple self-signatures on the
same object may resolve the ambiguity in any way it sees fit, but it
is RECOMMENDED that priority be given to the most recent self-
signature.
```

IMO this should be a hard MUST. Further, we should state explicitly that 
multiple self-sigs over the same object MUST NOT have the same creation 
date, to avoid any ambiguity in the interpretation of their subpackets. 
As currently phrased, implementations are free to disagree on critical 
properties such as expiration dates.

It has been argued that a key owner should be able to use multiple 
same-creation-date self-sigs to declare complex future scenarios (e.g. 
that different properties of a signable packet expire at different 
future dates) but IMO this adds significant and needless complexity - if 
you want to change the properties on some future date, then you can 
create a new self-sig on that date. We should also state explicitly how 
to interpret self-sigs with a creation date in the future - if for 
example they were allowed but silently ignored, then this would be a 
*much* more robust means of achieving the same effect.

(Again and to be clear, applications may allow more complex signature 
semantics if it makes sense in the context; I am only talking here about 
self-sigs)

```
Revoking a self-signature or allowing it to expire has a semantic
meaning that varies with the signature type.  Revoking the self-
signature on a User ID effectively retires that user name.  The self-
signature is a statement, "My name X is tied to my signing key K" and
is corroborated by other users' certifications.  If another user
revokes their certification, they are effectively saying that they no
longer believe that name and that key are tied together.  Similarly,
if the users themselves revoke their self-signature, then the users
no longer go by that name, no longer have that email address, etc.
Revoking a binding signature effectively retires that subkey.
Revoking a direct-key signature cancels that signature.
```

This entire paragraph could be more efficiently and clearly expressed as:

```
Revoking a self-signature or allowing it to expire means that the 
self-signature MUST NOT be used after its expiry or revocation date, 
except for the purpose of validating a historical event (for example, to 
determine whether a document signature was valid at the time of its 
creation).
```

And I would consider adding something along the lines of:

```
However, if the Reason for Revocation subpacket of a revocation 
self-signature indicates "Key material has been compromised", then all 
self-signatures over the same packet MUST be treated as if they were 
never valid, even in a historical context.
```

We should also forbid all kinds of certification self-sig other than 
Positive Certification. What does it mean to make a Persona 
self-signature over a UID for example? That we aren't sure what our own 
name is?

IMO there is sufficient ambiguity in the current specification of 
self-signature semantics that it is not always possible to definitively 
validate an arbitrary well-constructed TPK, so implementations are left 
to make their own guesses at how to treat corner cases. We should avoid 
carrying these problems forward into V5 self-sigs, and if we can't 
backport every clarification to V4 sigs due to existing implementation 
differences, at least state that it is RECOMMENDED to interpret V4 
self-sigs in the same way as V5 wherever possible.

-- 
Andrew Gallagher