diff --git a/specification.md b/specification.md index 360b0ec..fc9d8b2 100644 --- a/specification.md +++ b/specification.md @@ -40,24 +40,28 @@ The signature format is a JSON message of the following form: ``` Empty fields may be omitted. [Multiple signatures](#multiple-signatures) are -allowed. +allowed. Note that an optional `signature.sigType` field may be present but +empty for compatibility with [backwards compatible signature] mode. Parameters: * SERIALIZED_BODY is the byte sequence to be signed. -* PAYLOAD_TYPE is a URI indicating how to interpret SERIALIZED_BODY. It - encompasses the content type (JSON, Canonical-JSON, CBOR, etc.), the - purpose, and the schema version of the payload. This obviates the need for - the `_type` field within in-toto/TUF payloads. This URI does not need to be - resolved to a remote resource, nor does such a resource need to be fetched. - Examples: +* PAYLOAD_TYPE is an authenticated(*) URI indicating how to interpret + SERIALIZED_BODY. It encompasses the content type (JSON, Canonical-JSON, + CBOR, etc.), the purpose, and the schema version of the payload. This + obviates the need for the `_type` field within in-toto/TUF payloads. This + URI does not need to be resolved to a remote resource, nor does such a + resource need to be fetched. Examples: - https://in-toto.io/Link/v0.9 - https://in-toto.io/Layout/v0.9 - https://theupdateframework.com/Root/v1.0.5 - etc... + (*) Exception: PAYLOAD_TYPE is unauthenticated if `signature.sigType == + "raw-json-no-payload-type"`. + * 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 @@ -105,6 +109,9 @@ To sign: To verify: +- If `sigType == "raw-json-no-payload-type"`, use + [backwards compatible signature] instead. Reject if `sigType` is any other + non-empty value. - Base64-decode `payload`; call this SERIALIZED_BODY. Reject if the decoding fails. - Base64-decode `sig` and verify PAE(UTF8(PAYLOAD_TYPE), SERIALIZED_BODY). @@ -119,44 +126,46 @@ either, and verifiers **MUST** accept either. ### Backwards compatible signatures To convert existing signatures from the current format to the new format, -`"backwards-compatible-json"` is added to the payload type URI to indicate that +`"raw-json-no-payload-type"` 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": "", - "payloadType": "/backwards-compatible-json", + "payload": "", "signatures" : [{ "keyid": "", - "sig": "" + "sigType": "raw-json-no-payload-type", + "sig" : "" }] } ``` -Support for this backwards compatibility mode is optional. +Support for this backwards compatibility mode is optional and should be disabled +by default. To sign: -- BODY **MUST** be an object type (`{...}`). -- Serialize BODY as [Canonical JSON]; call this SERIALIZED_BODY. +- The message **MUST** be an object type (`{...}`). +- Serialize the message as [Canonical JSON]; call this SERIALIZED_BODY. - Sign SERIALIZED_BODY, base64-encode the result, and store it in `sig`. +- Store `"raw-json-no-payload-type"` in `sigType`. - Optionally, compute a KEYID and store it in `keyid`. - Base64-encode SERIALIZED_BODY and store it in `payload`. -- Store `"/backwards-compatible-json"` in `payloadType`. To verify: -- If `payloadType` != `"/backwards-compatible-json"`, use the normal - verification process instead of this one. +- If `sigType != "raw-json-no-payload-type"`, use the + [normal verification process](#steps) instead of this one. - Base64-decode `payload`; call this SERIALIZED_BODY. Reject if the decoding fails. - Base64-decode `sig` and verify SERIALIZED_BODY. Reject if either the 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 - to be Canonical JSON. + SERIALIZED_BODY **MUST** be `{`. Verifiers **MUST NOT** require + SERIALIZED_BODY to be Canonical JSON. +- Discard `payloadType` if present. Backwards compatible signatures are not recommended because they lack the authenticated payloadType indicator. @@ -280,8 +289,8 @@ Rationales for specific decisions: payloadType were not signed. - Also, URIs don't need to be registered while Media Types do. -- Why use payloadType "backwards-compatible-json" instead of assuming - backwards compatible mode if payloadType is absent? +- Why use payloadType "raw-json-no-payload-type" instead of assuming backwards + compatible mode if payloadType is absent? - We wanted to leave open the possibility of having an application-specific "default" value if payloadType is unspecified, @@ -337,11 +346,11 @@ To detect whether a signature is in the old or new format: To convert an existing signature to the new format: - `new.payload = base64encode(CanonicalJson(orig.signed))` -- `new.payloadType = "/backwards-compatible-json"` +- `new.signatures[*].sigType = "raw-json-no-payload-type"` - `new.signatures[*].sig = base64encode(hexdecode(orig.signatures[*].sig))` - `new.signatures[*].keyid = orig.signatures[*].keyid` -To convert a backwards compatible signature to the old format: +To convert a [backwards compatible signature] to the old format: - `old.signed = jsonparse(base64decode(new.payload))` - `old.signatures[*].sig = hexencode(base64decode(new.signatures[*].sig))`