davidben / merkle-tree-certs

Other
9 stars 4 forks source link

Add an explicit not_after time to the Proof #92

Open davidben opened 2 months ago

davidben commented 2 months ago

This serves two purposes:

  1. It allows a subscriber to easily know when the certificate is expired, without defining a separate certificate property.

  2. It allows a subscriber to request a shorter expiration time than the batch would otherwise force. Fixes #83.

In looking at this, I realized that the document's organization is a bit all over the place. Maybe we should just pull the generic BikeshedCertificate parts out into their own section. But for now I'm leaving the overall structure as-is.

davidben commented 2 months ago

Some notes and philosophizing:

not_after vs batch expiration time

We could either have not_after be a constraint on top of what the batch would impose, with the relying party checking the minimum of the two, or say that not_after must be consistent with batch expiry, with the relying party rejecting the certificate if inconsistent.

Put another way, is not_after the subscriber-requested expiry, or the effective expiry?

I went with effective expiry because this means the subscriber does not need to know anything about the trust anchor to know when the certificate expires. Either it expires at the not_after time, or it was simply invalid and will be rejected at any time.

Proof vs Assertion vs Certificate

not_after could be part of the Assertion, part of the Proof, or just an extra field in the Certificate.

I think the litmus test for being part of the Assertion is "would you put this in a CSR?", and the answer is I think no. "example.com's key is 1234" is a fact about the world. A certificate is the CA making a point-in-time claim that the fact about the world is true.

Now, it being a point-in-time claim is kind of interesting. A CA that issues 14 day certificates and a CA that issues 1 year certificates do not actually perform different validation procedures. It's not like either CA has any better ability to make predictions about the future. So that might suggest that expiration times are all nonsense and maybe we should just say when the certificate was issued, with expiry being a relying party policy?

Except that's not only impractical but also doesn't capture some things. While expiry doesn't tell you anything about the validation process, it tells you how the whole ecosystem will manage this lifecycle of this certificate:

But that further reenforces that expiry is not inherent to the fact itself, but is specific how one certificate is managed.

Proof vs extra field in the Certificate is kind of meaningless right now. I think the litmus test is, if we end up doing #88, would it be a per-Proof or per-Certificate value? Because this is an effective expiry, I think the answer is per-Proof. Different MTC CAs may force different not_after dates, etc.

davidben commented 2 months ago

Another random thought / justification

Opaque vs part of framework

We could either make it part of the BikeshedCertificate framework, or make it something that you put in the specific proof type. Ultimately these are mostly isomorphic. If something is specific to the proof type, subscribers can't read it generically, but then we can define a certificate property that they do know how to read.

But since subscribers should always be able to read this, and these kinds of offline assertions are inherently related to time, putting it in the framework made sense.

bwesterb commented 2 months ago

Some more things to ponder:

  1. How does a subscriber request the earlier expiration? Previously, the client would just send an assertion as assertion-publishing-request. Now we need a AssertionSigningRequest different from an Assertion that contains the expiry.

  2. Do we need a timestamp or can we use batches are granularity?

  3. Maybe also good to ponder revocation again. Depending on how we solve that, we might achieve what we want, by issuing and then immediately revoking for a set time. #41

davidben commented 2 months ago

How does a subscriber request the earlier expiration? Previously, the client would just send an assertion as assertion-publishing-request. Now we need a AssertionSigningRequest different from an Assertion that contains the expiry.

Oh ACME already has this. That was the original inspiration for this. https://www.rfc-editor.org/rfc/rfc8555.html#section-7.1.3

Not sure how much CAs actually pay attention to this today but, in principle, it seems reasonable for a subscriber to say "however long you issue certs for, I don't want to be vulnerable to this key for more than 24 hours, so please cap the lifetime accordingly".

Do we need a timestamp or can we use batches are granularity?

Isn't batches granularity just not landing this PR? I think the subscriber will need a timestamp at least, because the subscriber doesn't know the CA's parameters. Of course, if it's just for the subscriber, we could put it in CertificatePropertyList and leave the certificate format alone.

Maybe also good to ponder revocation again. Depending on how we solve that, we might achieve what we want, by issuing and then immediately revoking for a set time.

Well revocation only works in clients that have picked up the revocation instruction. In applications like the web, that's not perfectly reliable. Hence short-lived certificates and everything else. I don't think revocation removes the need for both subscriber and CA to contribute upper bounds on the lifetime.

On that note, the PR should probably include a sentence to allow CAs to shorten the lifetime beyond the batch too.

bwesterb commented 2 months ago

There is an issue: if you don't store not_after in the abridgedassertion, then the trust service can't compute HashAssertion and thus verify the tree.

davidben commented 2 months ago

Ah nice catch! I forgot about the HTTP interface.

AbridgedAssertionAndTimestamp is a mouthful. It is annoying that probably every proof type will need a family of "[abridged] assertion and not after" structures and we don't good a word for that. Should it actually go in the assertion?? Trouble is this makes it harder to staple multiple proofs a la #88 if the proofs happen not to be clocked similarly, or have other lifetime constraints, and I kinda like the freedom to build PKIs out of that.