Skip to content

Adding verifiability proposal #1330

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Adding verifiability proposal #1330

wants to merge 9 commits into from

Conversation

xibz
Copy link

@xibz xibz commented Feb 28, 2025

Description

The "CloudEvents Verifiability" proposal introduces a transport protocol-agnostic mechanism to enhance the security of CloudEvents. It enables event producers to sign the events they emit, allowing consumers to cryptographically verify both the authenticity and integrity of the received events. This ensures that consumers can trust the source of the events and be confident that the events have not been tampered with during transit. The primary threats addressed by this proposal are impersonation of event producers and unauthorized modification of events in transit.

This was a team effort here in writing this proposal between me, @xibz, and @jayniz

Proposed Changes

1. Introduction of Event Signatures

  • Define a standard method for producers to attach digital signatures to CloudEvents.
  • Specify the metadata fields required to store signature information within the event structure.

2. Verification Mechanism for Consumers

  • Outline procedures for consumers to verify the authenticity of an event's origin using the attached signature.
  • Provide guidelines on validating the integrity of the event data to ensure it hasn't been altered.

Release Notes

  • Feature Addition: Introduced a verifiability mechanism allowing event producers to digitally sign CloudEvents, enabling consumers to verify the authenticity and integrity of received events.

  • Security Enhancement: Addresses potential security threats by preventing impersonation of event producers and unauthorized modification of events during transit.

This proposal aims to bolster the security framework of CloudEvents by providing a standardized approach to event verifiability, thereby enhancing trust in event-driven systems.

Fixes #565
Fixes #1302

```
content-length: 209
content-type: application/json
ce-verificationmaterial: ZGM5OGU3MmQwZjk5ODBlODlhZjVmOGU3NjkyZDU4ZDc=
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should appear in the body along-side the other CE attributes, no?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on if it is structured or binary mode.

By along-side, you are meaning within the payload?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it depends, but in this example you're using structured based on what i see in the http body. So these new CE attributes should be in the body too. No?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see what you mean. Yes, that's a mistake on our end. I'll update after today's SIG.

A consumer then receives the this message and in order to verify, they must look at the `ce-erificationmaterialtype` header to determine whether it knows how to perform the verification. The consumer sees that verification material’s type is `md5`, so they will compute the `md5` of the payload to verify the CloudEvent contained in the message:

```
$ echo -n '{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since some CE attributes might be modified by intermediaries, I wonder if there should be a mechanism by which the producer can indicate which CE attributes are part of the verification.

Also, might need to talk about whether the data needs to be normalized (or not)... or do you think that's part of the implementation specific details of the chosen verification algorithm? Kind of related... what if someone sends JSON but an intermediary converts it to XML or protobuf? Do you see this being used for e2e processing even if the format changes or just single-format transmissions?

Copy link
Author

@xibz xibz Mar 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since some CE attributes might be modified by intermediaries, I wonder if there should be a mechanism by which the producer can indicate which CE attributes are part of the verification.

For things like DSSE, that is easily done and possible. The goal is to have an DSSE implementation proposal after this one which will cover headers and how those can be included in verification.

Also, might need to talk about whether the data needs to be normalized

Yes, these would be considered implementation specific because for some signing algorithms like DSSE, it completely avoids normalization.

For ones that requires normalization, like JWT, then it would need to have some form of normalization to work appropriately. I think for those situations, we can either leave it up to the implementation or try to come up with and end all be all way of normalizing if it is relevant for the signing algorithm. However, my example of JWT already defines how it normalizes, hence why having it in the implementation may make sense.

The benefit of having implementation specific is that it allows for the implementing algorithm utilize it's signing procedures to figure out what's best for normalizing. However, this also means we'd have multiple ways of normalizing across implementations. In addition, we should always recommend to not normalize

what if someone sends JSON but an intermediary converts it to XML or protobuf?

For DSSE this isn't an issue as long as the payload isn't touched. If it's just the encoding, then DSSE will be able to handle that. However for other signing algorithms, the implementation would need to specify how it handles normalization. However, if something is being changed like a key or value, then the manipulator needs to re-sign.

@erikerikson
Copy link
Member

A top level comment with only a suggestion. In the past when the group has discussed this sort of thing, we have thought that it would start as an official extension. You may want to consider moving these into the extensions folder because this will provide a lower probability of rejection and a perhaps lower bar for acceptance. We will, of course, do our best to provide sufficient constructive criticism to yield a more useful result.

@duglin
Copy link
Collaborator

duglin commented Mar 20, 2025

@xibz let me know when you think this is ready for another round of discussions in the weekly call OR when you want me to just poke people to review the PR.

@xibz
Copy link
Author

xibz commented Mar 20, 2025

@duglin please poke people - I think we addressed the comments. I did want to ask the group if they were okay making this apart of core given the nature of the proposal, security, and the implementation when we submit could be an extension.

@duglin
Copy link
Collaborator

duglin commented Mar 27, 2025

@xibz if you rebase on the lastest 'main' it might help with the ci stuff

@duglin
Copy link
Collaborator

duglin commented Mar 27, 2025

Also, for:

cloudevents/extensions/verifiability.md: Translation file cloudevents/languages/he/extensions/verifiability.md does not exist
cloudevents/extensions/verifiability.md: Translation file cloudevents/languages/zh-CN/extensions/verifiability.md does not exist

look at the other extensions and you'll how they created a "holding pattern" version for other languages. You should be able to copy those files with the English text changed for your extension

benjamin-j-powell added 6 commits April 2, 2025 10:20
This commit introduces the verifiability proposal which introduces two
new attributes: verificationmaterial and verificationmaterialtype

This only outlines the format for sending verification material, and
does not contain an implementation. At least not yet.

Signed-off-by: benjamin-j-powell <[email protected]>
Signed-off-by: benjamin-j-powell <[email protected]>
Signed-off-by: benjamin-j-powell <[email protected]>
Signed-off-by: benjamin-j-powell <[email protected]>
Signed-off-by: benjamin-j-powell <[email protected]>
Signed-off-by: benjamin-j-powell <[email protected]>
Signed-off-by: benjamin-j-powell <[email protected]>

This proposal introduces a transport protocol agnostic design for verifiable
CloudEvents. It allows producers of CloudEvents to sign the events that they
send—and consumers to cryptographically verify the *authenticity and the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/send-and/send and/

## Attributes

### verificationmaterial (Verification Material)
- Type: `String`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the indent from these sections, otherwise they appear as "code snippets" and not normal text.

verification material can contain information specific to the
implementation such as a sub type, version information, etc.
- Constraints:
- OPTIONAL
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both attributes need to be "REQUIRED" since when the extension is enabled they're both needed, right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See line 36 for more info

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay, I misunderstood this section a little. My impression of what OPTIONAL meant here was whether or not it was required when sending an event, but it looks like it is scoped to the extension proposal itself. Am I understanding that right?

Hence to USE this extension, both would be REQUIRED

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct, when this extension is used then both attributes are REQUIRED.

present

### verificationmaterialtype (Verfication Material Type)
- Type: `String`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a consumer doesn't understand this value, is there any requirement that they reject the event? I'm guessing what they do if they don't understand it, or the validation fails, it's an impl choice, right? Meaning, we can't mandate that they don't accept the event but they're then going to "proceed at their own risk" - is that the intent?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's up to the organization or company. I didn't want to be too heavy handed here, because one company or org may have completely differently security requirements and may want to fail or not fail depending on those requirements. For example, I can see a bank or a government institution would WANT to fail. However, something like a proxying service, would not.


When this extension is used, producers MUST set both the `verificationmaterial`
and `verificationmaterialtype` attributes. Consumers can choose to verify if
the material.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps add this to the end:
..., and can choose how to proceed if the verification fails

maybe?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, yes, exactly what I just insinuated above :) Good call out!


1. SDKs will verify as early as possible which depends on the
verification implementation.
2. Users manage their secrets, e.g. public key infrastructure (PKI).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate on why these assumptions are being made? It'll help people understand the overall proposal.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular, when option 1 is chosen, does it impact assumption 1 ?



The specifics of what the verification material looks like and how the
verification is performed depend on the *verifiability implementation*.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/depend/depends/

private key for producer and public key for consumers) and will create the
verification material on the producer side and also perform the verification on
the consumer side. This is the appropriate choice for any type of tool that is
used by other entities, for example open source.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worth mentioning that each side of the interaction could choose a different option?
I'm assuming neither side would need to know what choice the other side made, right? It becomes an impl/deployment choice.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly. So yes, let me clarify that.


**Note:** If an intermediary party modifies an event, they are considered the
producer of a new event. They MUST create an updated verification material and
the consumer(s) MUST recognize them as a trustworthy producer.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth calling out that the intermediary is also a consumer that needs to verify the incoming message before it does it's own verifiability creation processing, right?

Which begs the question... do we need to worry about nested verification scenarios?

e.g. client and receiving app do their own verify logic, but then the sdks do as well and neither know about each other. Is this a user error or something we should consider in the design to ensure a proper separation of concerns?

Copy link
Author

@xibz xibz Apr 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which begs the question... do we need to worry about nested verification scenarios?

That’s a great question, and an important one to scope clearly.

This proposal intentionally avoids prescribing nested verification logic. The goal is simplicity and clarity: if an intermediary verifies and re-signs an event, downstream consumers can safely assume that all prior verification steps were completed successfully.

If certain use cases require retaining and re-validating upstream signatures (e.g. for compliance or traceability), they can implement that at the application level. However, I believe this behavior is out of scope for the core proposal, and handling it by default could introduce unnecessary complexity for most users.

e.g. client and receiving app do their own verify logic, but then the sdks do as well and neither know about each other. Is this a user error or something we should consider in the design to ensure a proper separation of concerns?

Ideally, verification logic should be explicit and predictable, not something silently enforced at multiple layers (e.g. SDK and application both independently verifying without coordination). That said, I view this as a matter of implementation discipline and documentation, not something that needs to be deeply enforced in the spec.

When the SDKs include built-in verification, that should be clearly documented and ideally exposed as a configurable behavior. Likewise, applications integrating with such SDKs should understand where verification happens to avoid redundant or conflicting logic.

This is not a user error per se, but it is a UX and documentation consideration for implementers of SDKs, not something the event format itself needs to control.

Let me know if I understood that last question right

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This proposal intentionally avoids prescribing nested verification logic. The goal is simplicity and clarity: if an intermediary verifies and re-signs an event, downstream consumers can safely assume that all prior verification steps were completed successfully.

only if we trust the "man in the middle".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, you're right that this assumes the intermediary is trusted once it re-signs.

This proposal offers a baseline model where each hop that re-signs effectively vouches for the previous event state. That model works well for many common deployment scenarios where intermediaries are under control of the same org or within a trusted boundary.

That said, if an implementation operates in a zero-trust or cross-organizational context, then yes—nested signature chains could be introduced to preserve and verify the original event alongside any transformations. I think that should remain an implementation detail, not a requirement of this extension.

I can certainly note this as a pattern for advanced use cases, but our aim is to keep the spec as simple and flexible as possible without precluding stronger models.


* avoid depending on canonicalization (and its
[unnecessarily large attack surface](https://github.com/secure-systems-lab/dsse/blob/master/background.md#motivation))
* transport the verification material detached from the event payload
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what this one means. If you mean the material shouldn't be part of data then wouldn't that be covered by the requirement to use the attributes defined by this spec? Or am I missing something?

* transport the verification material detached from the event payload
(this helps avoid canonicalization)

A verifiability implementation **MUST FAIL** on:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm move all of the requirements (in this section) into the core part of the spec (into the "Attributes" section), so everything critical is in one section. Then these other sections are just helper sections to better understand why certain decisions were made and guidance on how to implement it.

* provide test vectors
* provide a verification coverage table (see Verification coverage table)

Test vectors ensure that implementations are consistent which does NOT affect verifiability.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap at 80


## Verifiability Implementation Proposals

A proposal for adding a verifiability implementation to the CE SDK **MUST:**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels a bit odd to use RFC2119 keywords for things sdk authors need to do (here and below).
I'm ok with really strong language (e.g. "it is expected that implementations do ..."), but whether people follow our advice is out of scope for us. All we can mandate is what goes on the wire.

## Example

To illustrate, let’s walk through how to implement a verification
implementation CloudEvents provide test vectors as well as a verification
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this reads funny to me. Is it missing a word (like "and") or a comma?

come up with the most insecure but also most concise verification
implementation imaginable: one based on a reversed digest which we will call
`rev`! The `rev` implementation will only verify whether or not the
payload, `data`, is valid and not additional attributes for the sake of
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and not whether the other context attributes are valid, for the sake of simplicity.

yes?

}
```

A consumer then receives the this message and in order to verify, they MUST
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/MUST/would/

```

A consumer then receives the this message and in order to verify, they MUST
look at the `ce-verificationmaterialtype` header to determine whether it knows
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/ce-//
s/header/attribute/

```

The consumer can then confirm that the `rev` output matches the verification
material and conclude that the CloudEvent’s authenticity and integrity are
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...matches the verification material by ...(add something about sha256'ing it)... and conclude...

|Verifiable information |binary-mode |structured-mode |comment |
|--- |--- |--- |--- |
|data/payload |✅ |✅ | |
|mandatory context attributes |❌ |❌ |The `rev` verification implementation only looks at the payload, not at any headers. |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/headers/context attributes/

|data/payload |✅ |✅ | |
|mandatory context attributes |❌ |❌ |The `rev` verification implementation only looks at the payload, not at any headers. |
|permissive context attributes |❌ |❌ |
|extension attributes |❌ |✅ |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is structured mode checked?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this example implementation ONLY verifies payload, so either structured or binary mode works for this trivial example.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't clear... you have "extension attributes" checked but no other attributes have a check-mark. That seems weird to me since, as you said, you're only checking the data not ANY other attributes.


## Appendix

### Dictionary
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure you need this section but if you keep it I'd prefer if we just point to CE spec that defines most of these terms so we don't run the risk of there being a conflict between the two definitions.

@duglin
Copy link
Collaborator

duglin commented Apr 3, 2025

@xibz does this PR cover #1302 ? If so, can you add "Fixes #1302" to the description of the PR so it'll be automatically closed when the PR is merged?

@jskeet
Copy link
Contributor

jskeet commented Apr 3, 2025

My general feedback is that this feels quite brittle - that it would work for a single-hop CloudEvent, but anything that does any kind of transformation (potentially even "structured to binary" or vice versa? that might be okay) would break the validity. I defer to others in the group as to how much we see multi-hop events with transformation in the wild.

Basically, I can see the usefulness here, but something feels "off". I would be more comfortable with this being thought of as being a bit like auth - something that we'd expect transports to provide rather than it being within CloudEvents.

@xibz
Copy link
Author

xibz commented Apr 3, 2025

@jskeet – Thank you for the thoughtful feedback. I understand the intuition behind something “feeling off,” and while it’s difficult to directly address intuitions, I hope this helps clarify why the approach is not as brittle as it might seem.

Multihop and Transformation

The concern about multihop scenarios is valid, and events are often passed through intermediaries. The proposal is designed to handle this explicitly:

  • If any signed content is modified, the intermediary would indeed need to re-sign the event.
  • Additive changes (e.g., adding extension attributes or transport metadata) do not break verification, assuming the implementation defines a clear scope of what is signed—something that tools like DSSE already support.
  • Crucially, intermediaries can and should verify the signature before forwarding, and their signature (if they re-sign) becomes a new chain of trust. This allows for multihop while still preserving verifiability at each stage.

Comparison to Transport-Level Security

You rightly point out that authentication and integrity are often seen as transport concerns. But I'd argue that transport security shares the same multihop fragility:

  • Each hop terminates the transport security context, so if any intermediary misbehaves, there's no end-to-end guarantee.
  • In contrast, an in-event signature offers end-to-end integrity—the consumer can verify the event’s original state, regardless of the number of hops.
  • For systems that store, replay, or audit events (e.g., CDEvents), trusting each hop retroactively becomes infeasible. You’d need to track what each transport layer authenticated over time, which is far more complex than a signed artifact.

Avoiding Past Mistakes

I completely agree that we don’t want to repeat the complexity or fragility of prior message security efforts (e.g., WS-Security). That’s why this proposal deliberately avoids overreach:

  • It scopes verification to a small, well-defined part of the event.
  • It uses known, proven primitives (e.g., detached signatures, DSSE).
  • It’s designed to be an extension, not a core requirement—offering flexibility for those who need it.

And finally, I’m happy to refine this further, but I do believe this proposal provides a pragmatic foundation for verifiability that complements (rather than replaces) transport security—especially in environments where trust in intermediaries cannot be assumed.

@erikerikson
Copy link
Member

erikerikson commented Apr 3, 2025

[deleted]

Apologies, I haven't done sufficient work to make this comment.

@xibz
Copy link
Author

xibz commented Apr 3, 2025

@erikerikson - No worries, but I always welcome any sort of feedback regardless of any experience, work, etc. I did catch some of your last comment, but I worry about the complexity tbh. Your comment could be a verifiability implementation if we wanted to add that level of complexity. The introduction of the two new attributes and this proposal should be as simple as possible and leave the more implementation side of things to the implementation proposal which is part 2, DSSE proposal coming if this gets accepted :).

@erikerikson
Copy link
Member

The edits are there for posterity. Thank you for your graciousness. Most everything was in the initial comment, I just clarified one part of my hasty, poor writing before my final edit.

Thank you for putting in the effort, this has been needed since the beginning.

- If present, a `verificationmaterialtype` attribute MUST also be
present

### verificationmaterialtype (Verfication Material Type)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Verfication/Verification

benjamin-j-powell added 2 commits April 9, 2025 12:37
Signed-off-by: benjamin-j-powell <[email protected]>
Signed-off-by: benjamin-j-powell <[email protected]>
@xibz
Copy link
Author

xibz commented Apr 10, 2025

@duglin - So talked with security and thought about this on my own regarding an array of signatures.

The thing with the audit trail is it’s not really giving us much. If the intermediary is resigning, we’re already trusting them by design. If they’ve got the signing key, they can write anything they want into the event. Stacking signatures in an array doesn’t change that, and you’re still trusting whoever has the keys at the point of resigning.
If some system cares about auditing, that should live in an external system, like proper logging or transparency mechanisms, and NOT in this proposal. Dumping an audit trail into the event itself just means we’re signing mutable data, which isn’t helpful. If someone is going to tamper, they’ll just rewrite the event and the signature array too.
Also, this adds a lot of overhead. Every hop that modifies the event would now have to process and resign the growing array, which just bloats complexity for no real benefit. And keep in mind, we already have provenance, e.g. source, in the event. So stuffing signatures into an array doesn’t make it more trustworthy, it just clutters the event.
I feel like this is trying to solve an audit problem in the wrong place. If we want proper auditing, we solve it outside the event, where it’s more reliable.

Let me know if this alleviates the need or want of this array of signatures

@duglin
Copy link
Collaborator

duglin commented Apr 17, 2025

Just to document what we talked about on last week's call, the questions wasn't about "audit", it was more about the possibility of a layered solution in which independent entities needed to sign the event w/o knowledge of each other. Thus, needing some kind of multi-signing structure (an array of verifications) rather than just one.

For example, a message goes thru 4 endpoints:
Sender -> middleware1 -> middleware2 -> Receiver

If the sender/receiver pair sign/verify the event, but the middleware1/middleware2 also sign/verify the event because it's their job to do so regardless of what their users (sender/receiver) are doing - then the event flowing between middleware1 and middleware2 might need to have 2 levels of signing attached to it. This becomes really important if the middleware adds new info to the event and needs to protect it.

@clemensv
Copy link
Contributor

I'm nervous about adding/inventing security mechanisms. To make this interoperable for serious usage, this extension will have to slip into that territory and suddenly we speak about hash algorithm options and all that jazz.

RFC7520 illustrates various applications of JOSE. I think of it as inevitable that anything we do here ends up looking a lot like JOSE.

The "coverage table" shows the proposal omitting a tricky piece, which is the handling of attributes and providing integrity protection of those attributes as part of the signature. Once that gets introduced, there also needs to be a selector of which attributes make up the protected set because you will want to allow intermediaries to add to the envelope.

Some level of canonicalization is unavoidable for all of this in CloudEvents because CloudEvents has different event formats and projections into different transport envelopes, all of which make their own encoding choices. A header value in HTTP may be 7-bit ASCII with percent-encoding while the value will be UTF-8 in the AMQP application-properties section and the MQTT "User Properties" section, which means you can't just run a signature algo over the raw headers.

I think it's possible to define a signature model for CloudEvents using the JSON event format as that canonicalization model. It could arguably also be our Avro encoding or the Proto encoding. Verifying the signatures would thus require to render a received CloudEvent in the JSON event format and then compute the signatures.

However, if we were to do that, we'd do JOSE's work again.

I believe an extension that very concretely describes how do apply JOSE to CloudEvents JSON event format would be useful.

@xibz
Copy link
Author

xibz commented Apr 17, 2025

@clemensv - Thanks for your comments. Although, I think there is some confusion, but we strictly, when designing this, decided to not have it behave like JOSE given it's brittleness. I will highlight the key differences below and why this proposal is better suited:

JOSE is a general purpose format that provides MORE than what we need for CloudEvents. It's bringing a hammer when a scalpel is needed.

For example, JOSE does several things that we explicitly avoided:

  1. We do not do encryption, JWE, and is ONLY for verifiability.
  2. We do not need multiplexed claims, e.g. iss, aud, exp
  3. We do not need compact serialization, which destroys readability in logging.
  4. We do not embed verification logic in a way that transforms the cloudevent.

We are a simple, clean, and deterministic solution, and JOSE, imo, does not fit those criteria.
We are protocol agnostic. JOSE is not. JOSE, JWS, does compact serialization as in it wraps the payload in base64.
It can function with DETACHED signatures. We explicitly call out that that should be avoided.
JOSE relies on encoded blobs, as ours does not.

JOSE supports MANY algorithms. However, ours will have a strict set of accepted signature formats, and using something else that isn't supported by the SDKs comes at your own risk. Further JOSE has the famous material type of none which has given rise to many CVEs, along with attackers can specifically DOWNGRADE a signing algorithm.

As opposed to our proposal, MANDATORY fields, only strongly vetted algorithms, like DSSE, and lastly we want to fail fast.
JOSE also relies on canonicalization. We want to avoid that like the plague where we can.

Further the tooling for JOSE requires a lot of libraries, where many of them are insecure. Additionally JOSE can have remote fetching, e.g. kid, jku, x5u, which is a major problem for air gapped regions.

Below is some direct answers to the some questions/statements:

Some level of canonicalization is unavoidable for all of this in CloudEvents because CloudEvents has different event formats and projections into different transport envelopes, all of which make their own encoding choices.
Im going to use DSSE as an example, since this is what we've been looking to use:

Some level of canonicalization, yes, but it's much different than JOSE. We are defining a single known representation of what gets signed with DSSE. We also do not want to guess the normalization which JOSE sometimes tries to do. We're not signing a semantic object like "a JavaScript object in memory", instead we are signing the raw bytes of a known serialization. We do not need field reordering, whitespace stripping, or encoding normalization tools. Let me know if that helps. To be clear with why this isn't typical canonicalization it is important to note we aren't signing things as they appear on the wire, like what JOSE does. DSSE reconstructs avoids this by reconstructing it as JSON to be signed

Here's an example payload to help make sense of what I just said cause I said it poorly haha

ce-id: 1234
ce-type: com.mycustom.type
ce-source: /my/source

Then with the DSSE implementation we would say, JSON restructuring must match, hence why we wanted mention of test vectors in the proposal

{
  "id": "1234",
  "type": "com.mycustom.foo",
  "source": "/my/source",
  "specversion": "1.0",
  "data": { ... }
}

So yes, you are right in that there is SOME canonicalization, but not an over the wire agreement of what it looks like.

However, if we were to do that, we'd do JOSE's work again.

Not necessarily... DSSE handles most of this out of the box. We just need to specify the "JSON", for DSSE case, event format for verification, which is implementation specific.

It could arguably also be our Avro encoding or the Proto encoding.

It could, but those formats come with significantly more tooling burden, binary wire compatibility problems, and cross-platform parsing complexity. JSON is readable, and debuggable. Also, signing Avro or Proto would still require canonicalization at some level (unsure if you were saying other, but in case calling it out) because their encoding is also non-deterministic unless tightly controlled

Verifying the signatures would thus require to render a received CloudEvent in the JSON event format and then compute the signatures.

Again, implementation specific. For DSSE you are correct, and that's by design. I see that more of a strenght tbh.

However, if we were to do that, we'd do JOSE's work again.

This is slippery slope-y

JOSE supports:

  1. Token-based identity flows
  2. Signing + encryption
  3. Federated key distribution

We are only doing one thing. Verifiability.

ugh. I was hoping to make this short, but turned into a wall of text D:

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.

Adding zero trust to cloudevents Message Producer Signature
5 participants