secure-systems-lab / dsse

A specification for signing methods and formats used by Secure Systems Lab projects.
https://dsse.dev
Apache License 2.0
68 stars 18 forks source link

Extending DSSE to accept optional signature specific metadata #39

Open shizhMSFT opened 3 years ago

shizhMSFT commented 3 years ago

Is it possible to extend the DSSE spec to have optional fields in order to support signature specific metadata like TSA (discussed in #33)?

The signature specific metadata includes authenticated signature metadata and unauthenticated ones. For example, TSA data are unauthenticated by the signing key as it is authenticated using other keys. Authenticated signature metadata can contains signature expiry, signature revocation information, etc..

References: Notary V2 - Signature Format

shizhMSFT commented 3 years ago

/cc @gokarnm

MarkLodato commented 3 years ago

This seems to be the same request as #36, which we have closed as "wontfix". Adding arbitrary header support would essentially be reinventing JWS. If those features are needed, could your application use JWS instead? Or am I misunderstanding the request?

It seems fine to consider specific headers on a case-by-case basis, but we should set the bar high for doing so. The whole idea of a "dead simple signing envelope" is that it's simple and hard to screw up. The more complexity we add, the more room for mistakes. Again, the simplicity is a differentiator from JWS.

For the specific features listed:

mnm678 commented 3 years ago

Also, as discussed in #35, metadata about signatures, including the algorithm and expiry, should be distributed alongside the key using a secure mechanism (such as delegation, etc), and not protected by the key itself.

shizhMSFT commented 3 years ago

Also, as discussed in #35, metadata about signatures, including the algorithm and expiry, should be distributed alongside the key using a secure mechanism (such as delegation, etc), and not protected by the key itself.

Here the expiry means the signature expiry not the key expiry. Literally, the signature expiry controls the expriy of the signature, not the key.

gokarnm commented 3 years ago

Hi @MarkLodato, I'll add some more context for this request. We are considering if DSSE can be used for container signing using Notary V2 and here are the draft requirements - Notary V2 - Signature Format. The basic payload is an OCI descriptor.

There is another ask, we want to store the x.509 certificate or certificate chain of the signing entity in the envelope, KeyID does not seem to be the correct attribute to store it, can this be supported through another top level attribute?

/cc: @shizhMSFT , @mnm678 , @dlorenc

dlorenc commented 3 years ago

IMO this doesn't need a top-level field, and we can do all of this inside the "payload", by adding another level of indirection. Here's roughly how I would structure it:

image

gokarnm commented 3 years ago

I agree we could use a wrapped payload that has the descriptor and other metadata fields (signature expiry, custom metadata etc.)

What about the certificate chain, it will contain the public key and will be used to validate the signature.

dlorenc commented 3 years ago

We discussed storing this in a separate blob on Friday.

shizhMSFT commented 3 years ago

IMO this doesn't need a top-level field, and we can do all of this inside the "payload", by adding another level of indirection. Here's roughly how I would structure it:

image

It is less optimal solution, rendering the envelope can only contain 1 signature if the payload contains signature specific metadata.

If we wrap the signature specific metadata for signature A in the payload. Later, we cannot add another signature to the envelope since we cannot wrap the signature specific metadata for signature B in the payload as the payload is immutable.

TomHennen commented 3 years ago

@dlorenc do you have any more details about storing the certificate chain as a separate blob?

trishankatdatadog commented 3 years ago

@dlorenc do you have any more details about storing the certificate chain as a separate blob?

I don't understand this comment either. Dan, do you mean distributing the PKI metadata inside the signed payload, ala TUF?

trishankatdatadog commented 3 years ago

It is less optimal solution, rendering the envelope can only contain 1 signature if the payload contains signature specific metadata.

If we wrap the signature specific metadata for signature A in the payload. Later, we cannot add another signature to the envelope since we cannot wrap the signature specific metadata for signature B in the payload as the payload is immutable.

There is some confusion here, I believe.

We need to strictly separate signature-specific metadata (such as #33) from signature-agnostic metadata (such as public key distribution and revocation). Please see the TUF specification (for example, the root role) to see how you may distribute and revoke keys inside signed payloads without signature-specific metadata.

dlorenc commented 3 years ago

I don't understand this comment either. Dan, do you mean distributing the PKI metadata inside the signed payload, ala TUF?

Sorry! This was about the notary use case specifically. The PKI metadata does not actually need to be stored in the DSSE envelope, it can be stored somewhere else. In Notary/OCI use cases, we have no real limitation to get everything into one envelope, we can use multiple "blobs" that are all within the same image.

gokarnm commented 3 years ago

We need to strictly separate signature-specific metadata (such as #33) from signature-agnostic metadata (such as public key distribution and revocation)

@trishankatdatadog, the X.509 certificate chain is for the party that produced the signature, similar to PKCS#7 (CMS) cert_info or JWS x5c attribute. Would that fall under signature-agnostic metadata? In Notary V2 usecases consumers of the signed image who use a PKI will probably configure trusted keys/roots (which the signing party may chain to) and revocation information through an out of band mechanism.

@dlorenc, it may be simpler for a specific signing component (say a PKCS#11 provider, or a signing service which knows about the certificate chain/PKI metadata) to produce a single DSSE envelope which includes all the information including PKI metadata, and Notary V2 CLI or Docker CLI (which offloads the sign operation to the signing component and does not know about the certificate chain) to create the signature manifest for the signature envelope (blob). At least that's the way I've been thinking about this.

TomHennen commented 3 years ago

I thought I'd replied to this earlier today, but it seems to have gotten lost. :(

What if we defined another format that could carry the cert-chain along with a bundle of attestations (https://github.com/in-toto/attestation/issues/38).

E.g.

# Both <in-toto provenance> and <container native provenance> are likely built by the same
# builder and so would very likely use the same cert chain.
{
  "payloadType": "application/vnd.in-toto+json",
  "payload": "<in-toto provenance>",
  "signatures": [{"keyid": "certchain://my-cert-chain-name", "sig": "<Base64(Signature)>"}]
}
{
  "payloadType": "application/vnd.in-toto+json",
  "payload": "<container native provenance>",
  "signatures": [{"keyid": "certchain://my-cert-chain-name", "sig": "<Base64(Signature)>"}]
}
{
  "payloadType": "application/vnd.dsse-cert-chain+json",  # Or maybe this could just go in an in-toto Statement, /shrug
  "payload": "<encoded cert chain>",
   # No DSSE signatures necessary since I gather that's handled by X.509 cert chains.
  "signatures": []
}
might look something like this before encoding ``` { "_type": "certchain" # or whatever "name": "my-cert-chain-name" "chain": "" } ``` This would allow the chain to be propagated with all attestations (after we get bundling figured out) and remove duplication of chains. People that don't care or want it stored in a separate place (like Notary/OCI) could easily grab the chain payload and then stick it in the place they want without impacting anything else. Thoughts?
trishankatdatadog commented 3 years ago

@shizhMSFT @gokarnm @TomHennen I think we all have different use cases here. For example, Shiwei has Notary v2 in mind, whereas Tom has in-toto in mind. But DSSE is completely agnostic to all of these use cases. It would at least be helpful to discuss more concretely your uses cases the way Tom did, but I'm still missing some context about his particular use case.

It looks like Tom has his own way of bootstrapping trust for a bunch of in-toto attestations, and something has to cover a signature over the chain cert and the attestation bundle, but how is this a DSSE problem? The way I see it, it already lets you do what you want to do, no?

gokarnm commented 3 years ago

That is correct, @shizhMSFT and me are working on Notary V2. And it's clear and awesome that DSSE is agnostic of payload details. You can define the payload format as you wish and include information for your use case in it.

From Notary V2 requirements, TSA and certificate chain are the two envelope level requirements. TSA is already being discussed and seems like there is consensus to add it. I'd like to continue discussion on adding signing party's certificate chain in the envelope.

The signing party's certificate chain is authenticated against a trust store the consumer configures (out of band), so the signing party's cert chain itself does not need to signed. The leaf cert in the chain has the public key that is used to verify the signed payload. The signing cert needs to be distributed with the signed artifact as consumers trust store cannot be assumed to contain every (leaf) publisher cert in all cases, consumer may choose to use a issuing cert or root cert as trust anchor in their trust store. This is specially true in cases where short lived signing certificates are used to generate signatures.

trishankatdatadog commented 3 years ago

The signing party's certificate chain is authenticated against a trust store the consumer configures (out of band), so the signing party's cert chain itself does not need to signed. The leaf cert in the chain has the public key that the is used to verify the signed payload. The signing cert needs to be distributed with the signed artifact as consumers trust store cannot be assumed to contain every (leaf) publisher cert in all cases, consumer may choose to use a issuing cert or root cert as trust anchor in their trust store. This is specially true in cases where short lived signing certificates are used to generate signatures.

I see, thanks for the clarification! Hmm, interesting, this does go against the DSSE philosophy. I don't think anything prevents you from making extensions to DSSE that contain such unauthenticated headers, but I'm afraid this specific use case is out of its purview. Thoughts, @MarkLodato and @dlorenc?

gokarnm commented 3 years ago

Glad to provide more context. Signing party's cert are supported in PKCS#7 (CMS) and JWS envelope, would like to know more about aspects of DSSE philosophy this would go against.

TomHennen commented 3 years ago

@trishankatdatadog

Regarding

It looks like Tom has his own way of bootstrapping trust for a bunch of in-toto attestations, and something has to cover a signature over the chain cert and the attestation bundle, but how is this a DSSE problem? The way I see it, it already lets you do what you want to do, no?

Our use case isn't in-toto related specifically (but I think in-toto would have the same problem). There's a desire to have a policy engine trust a previously distributed root-cert. Users would then generate ~ephemeral (daily/weekly/monthly) keys and have the root-cert sign them. They then sign the DSSE message using the ephemeral keys and distributed the DSSE message.

We'd like some way to communicate the cert-chain to the policy engine so that it can know that the key used to sign the DSSE message was vouched for by the trusted root-cert. I don't think there's a prescribed way to distribute the cert-chain yet?

TomHennen commented 3 years ago

And now that I've read more closely it seems like this is very similar, if not exactly the same as what @gokarnm expressed much more precisely.

trishankatdatadog commented 3 years ago

And now that I've read more closely it seems like this is very similar, if not exactly the same as what @gokarnm expressed much more precisely.

Exactly, it's meant to be application-specific. I don't think it's meant to be solved on the DSSE level, which aims simply to be a dead-simple signing envelope.

TomHennen commented 3 years ago

How would you recommend the certificate chain be communicated?

trishankatdatadog commented 3 years ago

How would you recommend the certificate chain be communicated?

As I recommend to @gokarnm, a few options:

  1. As part of this payload or some other payload verified before this payload.
  2. As part of the unsigned header, which requires an extension to DSSE, but not DSSE itself (not meant to solve this problem).
  3. Somewhere else out of band, above the DSSE layer.
shizhMSFT commented 3 years ago
  1. As part of this payload or some other payload verified before this payload.

This option is not optimal to be as a part of the payload since

  1. The payload should not be parsed before being verified.
  2. The cert chain is usually base64 encoded. If it is put in the payload, it will be encoded twice.
MarkLodato commented 3 years ago

To reiterate my previous comment, I have concerns with adding adding generic metadata support (which is what this thread is about). The question comes up often enough that we need add a FAQ about it.

Let's discuss specific use cases in individual issues:

As for signature expiration, signature revocation, and custom metadata, I agree with @dlorenc that these would fit better inside the payload. The Notary V2 docs talk directly about "signatures," but it sounds like what Notary V2 really wants is in-toto attestations. That is, when Notary V2 says "signature", it really means "signed statement about an artifact".

Think about an example in English. If I sign a document saying, "Dan may borrow my car for a week from today", my statement does not become invalid after a week. Rather, it's just that the permission does not extend past then. Suppose it is now a month later and we want to know whether Dan's use of my car was allowed. We can look back at the record and know that he indeed had permission. Had the document been repudiated, we would have no way of doing such after-the-fact analysis. So it is with attestations.

IMO this doesn't need a top-level field, and we can do all of this inside the "payload", by adding another level of indirection. Here's roughly how I would structure it: image

It is less optimal solution, rendering the envelope can only contain 1 signature if the payload contains signature specific metadata.

If we wrap the signature specific metadata for signature A in the payload. Later, we cannot add another signature to the envelope since we cannot wrap the signature specific metadata for signature B in the payload as the payload is immutable.

Is this more than a theoretical concern? Can you not just produce multiple attestations, one per signatory? Think about my car example: if I give permission for a week but you give permission for a day, we don't both sign the same document.