Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to offline Sigstore verification #2120

Closed
wants to merge 1 commit into from

Conversation

haydentherapper
Copy link

As discussed in previous PRs, the v0.1 bundle format that's being used does not contain inclusion proofs. However, it does contain SignedEntryTimestamps (https://github.com/sigstore/sigstore-go/blob/main/examples/oci-image-verification/main.go#L388), which assert a similar property - The log signs a commitment to include an entry. An inclusion proof is the same, a signed commitment (hash + checkpoint), with the additional benefit being we can verify consistency (append-only) of the log.

It is sufficient to check only the SET, that's what we've been doing in Cosign since adding Rekor support.

This will improve latency since no request to Rekor will be made. This also improves privacy since the log is not aware of every time a signed event is verified.

As discussed in previous PRs, the v0.1 bundle format that's being used does not contain inclusion proofs. However, it does contain SignedEntryTimestamps (https://github.com/sigstore/sigstore-go/blob/main/examples/oci-image-verification/main.go#L388), which assert a similar property - The log signs a commitment to include an entry. An inclusion proof is the same, a signed commitment (hash + checkpoint), with the additional benefit being we can verify consistency (append-only) of the log.

It is sufficient to check only the SET, that's what we've been doing in Cosign since adding Rekor support.

This will improve latency since no request to Rekor will be made. This also improves privacy since the log is not aware of every time a signed event is verified.
@haydentherapper haydentherapper requested a review from a team as a code owner January 12, 2024 17:55
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@haydentherapper
Copy link
Author

Hey @rdimitrov, I realized after our conversation that you do have a commitment from the log persisted in the v0.1 bundle (SignedEntryTimestamp) and so you shouldn't need online verification. An inclusion proof gives you the same property as a SignedEntryTimestamp, that the log commits to adding an entry. The benefit of an inclusion proof is that you can also verify the log remains append-only if you have log witnesses, but this is something we don't have in the v0.2 bundle either, we just wanted to make progress towards it, hence requiring inclusion proofs.

It is sufficient to just check the SET. I would recommend dropping online verification, it's far more performant to do it offline.

@rdimitrov
Copy link
Member

@haydentherapper - Oh, this is nice! Thanks for this update and for providing the context around it. Not having to check this online is nice and I did not know sigstore also logs the verifications being done, so that's also helpful. Thanks again! 🙏

I'll merge it but I see that you have to complete the CLA process before I can do that.

@haydentherapper
Copy link
Author

Would you be able to recreate this PR to merge? Sorry for having to ask, otherwise it’s going to take me quite a while before I can get approval to sign the CLA.

@rdimitrov
Copy link
Member

Would you be able to recreate this PR to merge? Sorry for having to ask, otherwise it’s going to take me quite a while before I can get approval to sign the CLA.

@haydentherapper - apologies, just saw the Slack chat where you mention this.

Yeah, of course, I'll recreate it and also address the issue you mentioned there! Thanks! 👍

BTW I hope it's not too much to ask, but it'll be interesting if you can share a bit more about how doing this offline actually does not sacrifice any potential security benefits? For example, how does sigstore-go still makes sure this is indeed signed without checking the Rekor log? Is it by using the trusted root keys to verify this entry is signed by a key from there (rekor?) or something else?

@haydentherapper
Copy link
Author

Happy to explain! tl;dr is that the SignedEntryTimestamp is verified using Rekor's public key.

Rekor provides a SignedEntryTimestamp (SET) for each upload, which is a signature over 1) the log entry index, 2) the timestamp of inclusion of the entry in the log, 3) the log ID (just an identifier for the log), 4) the canonicalized entry. The SET is a commitment by the log that an entry was uploaded at a given time. The key that signs the SET is shipped with the trust root.

For some background, the SET design took inspiration from Certificate Transparency (CT). CT logs provide a SignedCertificateTimestamp (SCT) as a "promise" of inclusion. Roughly, it's a signature over a certificate that states the log promises to upload an entry in a given time window. The SET improves on this because it signs over the log index - It's better than a promise, because it actually states the log has uploaded the entry (The bundle calls it a promise because I have referred to it as such - Probably shouldn't have, but oh well 😛)

The other commitment from the log is an inclusion proof, a list of hashes that links a log checkpoint (a merkle tree root signed by the log, the same key that signs the SET) to an entry. Like an SET, the inclusion proof commits to an entry at a given point in time in the log (point in time = checkpoint roughly). The inclusion proof and SET are effectively the same commitment - If you trust the log, you trust what it signs, so you can trust either the SET or the inclusion proof.

(Everything in this paragraph is a WIP) The reason the bundle requires an inclusion proof is because we want to start moving towards also bundling consistency proofs, which are proofs that a log is append-only. Given a consistency proof between two checkpoints, we can verify that the log remains append-only, so given an inclusion proof and its checkpoint, we know the log is consistent still. We can do even better with "witnesses", where an independent verifier also verifies consistency and staples a countersignature over a checkpoint. It improves upon the current state so that the verifier doesn't have to trust the log at all. And all of this can be done offline!

So tl;dr - An SET provides the same guarantee as an inclusion proof, as both include a signature from Rekor over a log index.

@rdimitrov
Copy link
Member

Happy to explain! tl;dr is that the SignedEntryTimestamp is verified using Rekor's public key.

Rekor provides a SignedEntryTimestamp (SET) for each upload, which is a signature over 1) the log entry index, 2) the timestamp of inclusion of the entry in the log, 3) the log ID (just an identifier for the log), 4) the canonicalized entry. The SET is a commitment by the log that an entry was uploaded at a given time. The key that signs the SET is shipped with the trust root.

For some background, the SET design took inspiration from Certificate Transparency (CT). CT logs provide a SignedCertificateTimestamp (SCT) as a "promise" of inclusion. Roughly, it's a signature over a certificate that states the log promises to upload an entry in a given time window. The SET improves on this because it signs over the log index - It's better than a promise, because it actually states the log has uploaded the entry (The bundle calls it a promise because I have referred to it as such - Probably shouldn't have, but oh well 😛)

The other commitment from the log is an inclusion proof, a list of hashes that links a log checkpoint (a merkle tree root signed by the log, the same key that signs the SET) to an entry. Like an SET, the inclusion proof commits to an entry at a given point in time in the log (point in time = checkpoint roughly). The inclusion proof and SET are effectively the same commitment - If you trust the log, you trust what it signs, so you can trust either the SET or the inclusion proof.

(Everything in this paragraph is a WIP) The reason the bundle requires an inclusion proof is because we want to start moving towards also bundling consistency proofs, which are proofs that a log is append-only. Given a consistency proof between two checkpoints, we can verify that the log remains append-only, so given an inclusion proof and its checkpoint, we know the log is consistent still. We can do even better with "witnesses", where an independent verifier also verifies consistency and staples a countersignature over a checkpoint. It improves upon the current state so that the verifier doesn't have to trust the log at all. And all of this can be done offline!

So tl;dr - An SET provides the same guarantee as an inclusion proof, as both include a signature from Rekor over a log index.

Thank you for this thorough explanation!! 🙏 Really appreciate it! 💯

@rdimitrov
Copy link
Member

Closing in favour of #2131

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants