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

What payload should we send to the TSA in Sigstore? #116

Closed
znewman01 opened this issue Nov 2, 2022 · 19 comments · Fixed by #188
Closed

What payload should we send to the TSA in Sigstore? #116

znewman01 opened this issue Nov 2, 2022 · 19 comments · Fixed by #188
Labels
question Further information is requested

Comments

@znewman01
Copy link

Is it going to be the same thing we send to Rekor? Something simpler?

I think I've heard folks chatting about this and maybe there are docs around but would love a place to centralize discussion.

@znewman01 znewman01 added the question Further information is requested label Nov 2, 2022
@hectorj2f
Copy link
Contributor

I'm currently sending the signature e.g. (sig.Payload()) as the payload to use in the TSA. Happy to hear better suggestions because that would help me with my current development.

@asraa
Copy link
Collaborator

asraa commented Nov 2, 2022

I'm currently sending the signature e.g. (sig.Payload()) as the payload to use in the TSA. Happy to hear better suggestions because that would help me with my current development.

@hectorj2f For attestations, sig.Payload() works, but for blobs, that's going to be insecure and suspect to replay attacks. If someone gets just payload signed by the TSA to produce Timestamp1, then if you sign again, you would be able to pass in the same Timestamp1 for a "valid signature" The timestamp needs to ensure the signature was created during the validity period, not the payload. For attestations it only works because the signature is contained in the payload.

@asraa
Copy link
Collaborator

asraa commented Nov 2, 2022

@cdris I think when users supply their own timestamp to Rekor its on the client to figure out the correct logic. It's hard to figure out the canoniclization. When Sigstore has it's own TSA I believe it can use the canonicalized Rekor body as the timestamp payload, since it always contains the sig.

@cdris
Copy link

cdris commented Nov 2, 2022

@asraa Agreed, the logic for client-provided timestamps should be on the side of the client. Eventually when Rekor is using the TSA itself, we had discussed Rekor requesting timestamps over the leaf identity hash.

@hectorj2f
Copy link
Contributor

hectorj2f commented Nov 2, 2022

@asraa For blobs, What would you suggest to use as payload if you decided to use the TSA server, as a replacement of Rekor ?

@asraa
Copy link
Collaborator

asraa commented Nov 2, 2022

sig.Base64Signature()

@haydentherapper
Copy link
Contributor

+1 to @asraa's comment about using the signature. This is in line with other code-signing mechanisms like Authenticode, that describe timestamping as a countersignature (a signature over a signature).

This is a great point, let's add this to the README.

@znewman01
Copy link
Author

sig.Base64Signature()

Why base64?

I'm also generally confused about the divergence from Rekor. One of the nice things about having (even unauthenticated) extra metadata in the log entry is that it's somewhat less malleable: I can't take a binary with metadata that says it's "cowsay" and then serve it to you later and call it "openssl". (Though, counterpoint: I can currently take someone's Rekor entry and resubmit it with the unauthenticated metadata changed around while the cert is valid.)

I do think that signing only the signature is a reasonable decision overall, but I'd like to spell out the motivations.

Maybe with a move towards timestamps over naked signatures instead of signatures + metadata, we should start recommending that in most cases signatures should be over attestations about an artifact, and move some of the metadata inside the signed payload. This feels prudent anyway; I think that directly signing a binary is semantically confusing in general.

@asraa
Copy link
Collaborator

asraa commented Nov 3, 2022

Why base64?

No real reason except that's the only thing offered by the interface. You could decode it but it's one more step (which I think the interface should have just given the isgnature bytes)

@asraa
Copy link
Collaborator

asraa commented Nov 3, 2022

This is also super related to: sigstore/protobuf-specs#9

Basically, if the payload sent to the TSA is too complicated, it puts an unncessary burden on clients to reproduce that payload. In the Rekor case the "payload" was the canonicalized entry.

@kommendorkapten
Copy link
Member

Agree on sending the signature, this is also how I envisioned it for the Sigstore bundle: https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_bundle.proto#L35

@znewman01
Copy link
Author

No real reason except that's the only thing offered by the interface. You could decode it but it's one more step (which I think the interface should have just given the signature bytes)

ACK.

IMO we should decode it rather than propagate an accidental decision of one particular library in one particular language, or even better try to get it fixed upstream (this method comes from go-containerregistry IIUC).

@bobcallaway
Copy link
Member

bobcallaway commented Nov 4, 2022

Though, counterpoint: I can currently take someone's Rekor entry and resubmit it with the unauthenticated metadata changed around while the cert is valid.

@znewman01 Can you provide an example of this?

@asraa
Copy link
Collaborator

asraa commented Nov 4, 2022

we should start recommending that in most cases signatures should be over attestations about an artifact, and move some of the metadata inside the signed payload.

I think binaries/blobs and attestations are both relatively easy, and in fact attestation signatures can be detached to look basically like a blob signature. The complicated parts is actually the other types of signatures: JARs, PKCS7 objects, etc.

@kommendorkapten
Copy link
Member

Trying to combine what has been discussed so far, I would think of this like this:

  1. An actor prepares something to sign, e.g an attestation that contains info on the artifact, and some other related metadata.
  2. The actor signs the attestation, producing a signature S, which is an octet stream.
  3. To get a signed timestamp, the actor prepare a TSA request with S as the payload.
  4. The TSA response is kept as a counter signature.

To re-state what @haydentherapper said, this is compatible with Authenticode.
Also, this will not couple any of the canoncialization, pre-auth encoding, metadata gathering etc to the signed timestamp, that is only done when the artifact/attestation signature is constructed. The signed timestamp is only a counter signature over the initial signature S.
The benefit of this is that the solution will be much simpler to implement, manage and verify.

Also, as this is decoupled from any of the preparation of a signature creation, it will be easy to adopt regardless on what data the signature is made over, we are only interested in the signature, which is a finite octet-stream.

If we want to tie this with Rekor, we can create a counter signature over the SET, without caring how Rekor canonicalizes the entry, all that logic is only related to verifying the SET. I think this provides a nice separation of concerns for the different signatures, and what needs to be verified where.

@haydentherapper
Copy link
Contributor

If we want to tie this with Rekor, we can create a counter signature over the SET

I would say it should always be over the artifact signature, not over the SET, because we're timestamping the creation of the artifact, not the SET's creation. For Rekor, it would look something like:

  • Fetch a signed timestamp over the artifact signature at artifact signing time
  • Upload an artifact/signature/cert to Rekor (hashedrekord, rekord, etc)
  • Upload a second entry to Rekor, as an rfc3161 record

For verification, you must look up both the artifact in Rekor and the 3161 record. Obviously the user experience here isn't ideal because you have to upload two records rather than one, but this is something that @cdris is working on improving by adding support for uploading signed timestamps when uploading an artifact.

@kommendorkapten
Copy link
Member

Yeah, the signature over the SET was just a crazy idea I got when I was about to publish the comment. The signature over the artifact's signature is of course the most important one.

@kommendorkapten
Copy link
Member

For verification, you must look up both the artifact in Rekor and the 3161 record. Obviously the user experience here isn't ideal because you have to upload two records rather than one...

If the client is using the bundle format, the signed timestamp can be added to that. It won't go on Rekor though, but I think this is a reasonable tradeoff.

Another use-case is that the request to Rekor for adding an entity can take the signed timestamp as an optional parameter. We won't get the rfc3161 record though, but not sure if that's relevant?

@haydentherapper
Copy link
Contributor

haydentherapper commented Nov 7, 2022

Another use-case is that the request to Rekor for adding an entity can take the signed timestamp as an optional parameter. We won't get the rfc3161 record though, but not sure if that's relevant?

Correct, the idea would be we replace the integrated_time field in the response with the provided signed timestamp (or fetch a signed timestamp automatically from the Sigstore-operated TSA). And the signed timestamp becomes a part of the leaf hash calculation so we get immutability, rather than the current state where the integrated_time is just stored in the Rekor DB and could be mutated without detection.

haydentherapper added a commit that referenced this issue Dec 15, 2022
This includes a security model and how to do timestamping with Sigstore.

This includes more details on how to operate the TSA in production also.

Fixes #17

Fixes #116

Signed-off-by: Hayden B <hblauzvern@google.com>
haydentherapper added a commit that referenced this issue Dec 20, 2022
* Update README with more details

This includes a security model and how to do timestamping with Sigstore.

This includes more details on how to operate the TSA in production also.

Fixes #17

Fixes #116

Signed-off-by: Hayden B <hblauzvern@google.com>

* Update from comments

Signed-off-by: Hayden B <hblauzvern@google.com>

* Fix link

Signed-off-by: Hayden B <hblauzvern@google.com>

Signed-off-by: Hayden B <hblauzvern@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants