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

Add UTF-8 encoding option to the envelope document and proto. #64

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions envelope.md
Copy link
Collaborator

Choose a reason for hiding this comment

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

This probably needs a version bump and a note about backwards compatibility.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks so much for all the editing suggestions!

Regarding versioning, I don't think it is originally versioned; and also there is no field defined in the envelope to reflect versions. I guess we will need to add a version field in the envelope, don't we?

Assuming we embrace Semantic Versioning, do we start (current) from 1.0 and bump to 1.1?
Or start from 0.1 and bump to 1.0, like in-toto? But the latter is a major version bump...
Or maybe start from 0.1 and bump to 0.2, to keep this a minor version bump?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry, I meant versioning of the spec itself. It's currently v1.0. I lean towards calling this v1.1 rather than v2.0 since the signature is still backwards compatible and contains the string DSSEv1. Then again, I could be convinced to call it v2.0 since newly created envelopes would be unreadable by old clients.

I personally don't think a version number is needed in the envelope. Instead of going by version, you can go by what fields are present. A v1.1/v2.0 envelope with payload looks just the same as v1.0. I worry that a version field will lead to unnecessary incompatibility or worse, bugs or vulnerabilities.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for clarifying. I bumped up the version in envelope.md and added the "change history" section.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@MarkLodato Not sure that a version field would lead to vulnerabilities: at least, I don't see why that is necessarily more insecure than conditionally parsing fields. At least a version field would give you an unauthenticated hint you don't need to blindly trust, but for which you know you need to double-check by looking for other, expected fields.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

March 03, 2021

Version 1.0.0
Version 1.1.0

This document describes the recommended data structure for storing DSSE
signatures, which we call the "JSON Envelope". For the protocol/algorithm, see
Expand All @@ -16,9 +16,12 @@ to define the schema. JSON is the only recommended encoding.)
The standard data structure for storing a signed message is a JSON message of
the following form, called the "JSON envelope":

```json
```jsonc
{
"payload": "<Base64(SERIALIZED_BODY)>",
// Exactly one of the following must be set:
"payload": "<Base64Encode(SERIALIZED_BODY)>",
"payloadUtf8": "<Utf8Decode(SERIALIZED_BODY)>",
// End oneof
"payloadType": "<PAYLOAD_TYPE>",
"signatures": [{
"keyid": "<KEYID>",
Expand All @@ -29,9 +32,22 @@ the following form, called the "JSON envelope":

See [Protocol](protocol.md) for a definition of parameters and functions.

Base64() is [Base64 encoding](https://tools.ietf.org/html/rfc4648), transforming
a byte sequence to a unicode string. Either standard or URL-safe encoding is
allowed.
Exactly one of `payload` or `payloadUtf8` MUST be set:

- `payload` supports arbitrary SERIALIZED_BODY.
[Base64Encode()](https://tools.ietf.org/html/rfc4648) transforms a byte
sequence to a Unicode string. Base64 has a fixed 33% space overhead but
supports payloads that are not necessarily valid UTF-8. Either standard or
URL-safe encoding is allowed.

- `payloadUtf8` only supports valid
[UTF-8](https://tools.ietf.org/html/rfc3629) SERIALIZED_BODY. `Utf8Decode()`
converts that UTF-8 byte sequence to a Unicode string. Regular JSON string
escaping applies, but this is usually more compact and amenable to
compression than Base64.

Note: The choice of `payload` vs `payloadUtf8` does not impact the
[the signing or the signatures](protocol.md#signature-definition).

### Multiple signatures

Expand All @@ -54,8 +70,8 @@ envelopes with individual signatures.

### Parsing rules

* The following fields are REQUIRED and MUST be set, even if empty: `payload`,
`payloadType`, `signature`, `signature.sig`.
* The following fields are REQUIRED and MUST be set, even if empty:
exactly one of {`payload` or `payloadUtf8`}, `payloadType`, `signature`, `signature.sig`.
* The following fields are OPTIONAL and MAY be unset: `signature.keyid`.
An unset field MUST be treated the same as set-but-empty.
* Producers, or future versions of the spec, MAY add additional fields.
Expand All @@ -73,3 +89,10 @@ invalidating the signature:

At this point we do not standardize any other encoding. If a need arises, we may
do so in the future.

## Change history
* 1.1.0:
* Added support for UTF-8 encoded payload and `payloadUtf8` field.

* 1.0.0: Initial version.

11 changes: 8 additions & 3 deletions envelope.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ package io.intoto;

// An authenticated message of arbitrary type.
message Envelope {
// Message to be signed. (In JSON, this is encoded as base64.)
// Message to be signed.
// REQUIRED.
bytes payload = 1;

oneof payload_encoding {
// Raw bytes. In JSON, this is encoded as base64.
bytes payload = 1;
// Unicode string, where the signed byte stream (SERIALIZED_BODY) is the UTF-8 encoding of `payloadUtf8`. In JSON, this is a regular string.
string payloadUtf8 = 4;
}

// String unambiguously identifying how to interpret payload.
// REQUIRED.
string payloadType = 2;
Expand Down
4 changes: 4 additions & 0 deletions protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,7 @@ Result (using the recommended [JSON envelope](envelope.md)):
[JWS]: https://tools.ietf.org/html/rfc7515
[PASETO]: https://github.com/paragonie/paseto/blob/master/docs/01-Protocol-Versions/Version2.md#sig
[TUF]: https://theupdateframework.io

## Change history
* 1.0.0: Initial version.