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

Fully specify all fields within signatures #11

Merged
merged 7 commits into from
Dec 14, 2020
Merged
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
64 changes: 49 additions & 15 deletions specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ The signature format is a JSON message of the following form:
"payload": "<Base64(SERIALIZED_BODY)>",
"payloadType": "<PAYLOAD_TYPE>",
"signatures": [{
,
"keyid": "<KEYID>",
"sig": "<Base64(Sign(PAE([UTF8(PAYLOAD_TYPE), SERIALIZED_BODY])))>"
}, …]
}]
}
```

where:
Empty fields may be omitted. [Multiple signatures](#multiple-signatures) are
allowed.

Parameters:

* SERIALIZED_BODY is the byte sequence to be signed.

Expand All @@ -54,6 +57,14 @@ where:
- https://theupdateframework.com/Root/v1.0.5
- etc...

* KEYID is an optional, unauthenticated hint indicating what key and algorithm
was used to sign the message. As with Sign(), details are agreed upon
out-of-band by the signer and verifier. It **MUST NOT** be used for security
decisions; it may only be used to narrow the selection of possible keys to
try.

Functions:

* PAE() is the
[PASETO Pre-Authentication Encoding](https://github.com/paragonie/paseto/blob/master/docs/01-Protocol-Versions/Common.md#authentication-padding),
where parameters `type` and `body` are byte sequences:
Expand All @@ -63,7 +74,7 @@ where:
le64(n) := 64-bit little-endian encoding of `n`, where 0 <= n < 2^63
```

* Sign() is an arbitrary digital signature format. Details must be agreed upon
* Sign() is an arbitrary digital signature format. Details are agreed upon
out-of-band by the signer and verifier. This specification places no
restriction on the signature algorithm or format.

Expand All @@ -81,6 +92,7 @@ To sign:
- Serialize BODY according to PAYLOAD_TYPE. Call the result SERIALIZED_BODY.
- Sign PAE([UTF8(PAYLOAD_TYPE), SERIALIZED_BODY]), base64-encode the result,
and store it in `sig`.
- Optionally, compute a KEYID and store it in `keyid`.
- Base64-encode SERIALIZED_BODY and store it in `payload`.
- Store PAYLOAD_TYPE in `payloadType`.

Expand All @@ -94,33 +106,34 @@ To verify:
fails.

Either standard or URL-safe base64 encodings are allowed. Signers may use
either, and verifiers must accept either.
either, and verifiers **MUST** accept either.

### Backwards compatible signatures

To convert existing signatures from the current format to the new format,
`"backwards-compatible-json"` must be added to the payload type URI to indicate
that the signature is over the raw payload. This allows the signatures to remain
`"backwards-compatible-json"` is added to the payload type URI to indicate that
the signature is over the raw payload. This allows the signatures to remain
valid while avoiding the verifier from having to use [Canonical JSON].

```json
{
"payload": "<Base64(CanonicalJson(BODY))>",
"payloadType": "<URI>/backwards-compatible-json",
"signatures" : [{
,
"sig" : "<Base64(Sign(CanonicalJson(BODY)))>"
}, …]
"keyid": "<KEYID>",
"sig": "<Base64(Sign(CanonicalJson(BODY)))>"
}]
}
```

Support for this backwards compatibility mode is optional.

To sign:

- BODY **must** be an object type (`{...}`).
- BODY **MUST** be an object type (`{...}`).
- Serialize BODY as [Canonical JSON]; call this SERIALIZED_BODY.
- Sign SERIALIZED_BODY, base64-encode the result, and store it in `sig`.
- Optionally, compute a KEYID and store it in `keyid`.
MarkLodato marked this conversation as resolved.
Show resolved Hide resolved
- Base64-encode SERIALIZED_BODY and store it in `payload`.
- Store `"<URI>/backwards-compatible-json"` in `payloadType`.

Expand All @@ -134,16 +147,35 @@ To verify:
decoding or the signature verification fails.
- Parse SERIALIZED_BODY as a JSON object. Reject if the parsing fails or if
the result is not a JSON object. In particular, the first byte of
SERIALIZED_BODY must be `{`. Verifiers **must not** require SERIALIZED_BODY
SERIALIZED_BODY **MUST** be `{`. Verifiers **MUST NOT** require SERIALIZED_BODY
to be Canonical JSON.

Backwards compatible signatures are not recommended because they lack the
authenticated payloadType indicator.

This scheme is safe from rollback attacks because the first byte of
SERIALIZED_BODY must be 0x7b (`{`) in backwards compatibility mode and 0x02 in
SERIALIZED_BODY is 0x7b (`{`) in backwards compatibility mode and 0x02 in
regular mode.

### Multiple signatures

A file may have more than one signature, which is equivalent to separate files
with individual signatures.

```json
{
"payload": "<Base64(SERIALIZED_BODY)>",
"payloadType": "<PAYLOAD_TYPE>",
"signatures": [{
"keyid": "<KEYID_1>",
"sig": "<SIG_1>"
}, {
"keyid": "<KEYID_2>",
"sig": "<SIG_2>"
}]
}
```

### Optional changes to wrapper

The standard wrapper is JSON with an explicit `payloadType`. Optionally,
Expand Down Expand Up @@ -278,9 +310,9 @@ used by TUF and in-toto has a BODY that is a regular JSON object and a signature
{
"signed": <BODY>,
"signatures": [{
,
"keyid": "<KEYID>",
"sig": "<Hex(Sign(CanonicalJson(BODY)))>"
}, …]
}]
}
```

Expand All @@ -299,11 +331,13 @@ To convert an existing signature to the new format:
- `new.payload = base64encode(CanonicalJson(orig.signed))`
- `new.payloadType = "<URI>/backwards-compatible-json"`
- `new.signatures[*].sig = base64encode(hexdecode(orig.signatures[*].sig))`
- `new.signatures[*].keyid = orig.signatures[*].keyid`

To convert a backwards compatible signature to the old format:

- `old.signed = jsonparse(base64decode(new.payload))`
- `old.signatures[*].sig = hexencode(base64decode(new.signatures[*].sig))`
- `old.signatures[*].keyid = new.signatures[*].keyid`

## Testing

Expand Down