Skip to content

Commit 351e75b

Browse files
authored
Merge pull request #19 from MarkLodato/backwards-compat
2 parents 6f6b031 + 44124ed commit 351e75b

File tree

1 file changed

+14
-115
lines changed

1 file changed

+14
-115
lines changed

specification.md

Lines changed: 14 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ This document proposes a new signature scheme for use by, among others, the
1313
[in-toto] and [TUF] projects. This signature scheme (a) avoids relying on
1414
canonicalization for security and (b) reduces the possibility of
1515
misinterpretation of the payload. The serialized payload is encoded as a string
16-
and verified by the recipient _before_ deserializing. A backwards compatible
17-
variant is available.
16+
and verified by the recipient _before_ deserializing.
1817

1918
## Overview
2019

@@ -40,14 +39,13 @@ The signature format is a JSON message of the following form:
4039
```
4140

4241
Empty fields may be omitted. [Multiple signatures](#multiple-signatures) are
43-
allowed. Note that an optional `signature.sigType` field may be present but
44-
empty for compatibility with [backwards compatible signature] mode.
42+
allowed.
4543

4644
Parameters:
4745

4846
* SERIALIZED_BODY is the byte sequence to be signed.
4947

50-
* PAYLOAD_TYPE is an authenticated(*) URI indicating how to interpret
48+
* PAYLOAD_TYPE is an authenticated URI indicating how to interpret
5149
SERIALIZED_BODY. It encompasses the content type (JSON, Canonical-JSON,
5250
CBOR, etc.), the purpose, and the schema version of the payload. This
5351
obviates the need for the `_type` field within [in-toto]/[TUF] payloads.
@@ -59,9 +57,6 @@ Parameters:
5957
- https://theupdateframework.com/Root/v1.0.5
6058
- etc...
6159

62-
(*) Exception: PAYLOAD_TYPE is unauthenticated if `signature.sigType ==
63-
"raw-json-no-payload-type"`.
64-
6560
* KEYID is an optional, unauthenticated hint indicating what key and algorithm
6661
was used to sign the message. As with Sign(), details are agreed upon
6762
out-of-band by the signer and verifier. It **MUST NOT** be used for security
@@ -95,7 +90,6 @@ Functions:
9590
Out of band:
9691
9792
- Agree on a PAYLOAD_TYPE and cryptographic details.
98-
- Decide if [backwards compatible signature] mode should be allowed.
9993
10094
To sign:
10195
@@ -109,9 +103,6 @@ To sign:
109103
110104
To verify:
111105
112-
- If `sigType == "raw-json-no-payload-type"`, use
113-
[backwards compatible signature] instead. Reject if `sigType` is any other
114-
non-empty value.
115106
- Base64-decode `payload`; call this SERIALIZED_BODY. Reject if the decoding
116107
fails.
117108
- Base64-decode `sig` and verify PAE(UTF8(PAYLOAD_TYPE), SERIALIZED_BODY).
@@ -123,57 +114,6 @@ To verify:
123114
Either standard or URL-safe base64 encodings are allowed. Signers may use
124115
either, and verifiers **MUST** accept either.
125116
126-
### Backwards compatible signatures
127-
128-
To convert existing signatures from the current format to the new format,
129-
`"raw-json-no-payload-type"` is added to the payload type URI to indicate that
130-
the signature is over the raw payload. This allows the signatures to remain
131-
valid while avoiding the verifier from having to use [Canonical JSON].
132-
133-
```json
134-
{
135-
"payload": "<Base64(SERIALIZED_BODY)>",
136-
"signatures" : [{
137-
"keyid": "<KEYID>",
138-
"sigType": "raw-json-no-payload-type",
139-
"sig" : "<Base64(Sign(SERIALIZED_BODY))>"
140-
}]
141-
}
142-
```
143-
144-
Support for this backwards compatibility mode is optional and should be disabled
145-
by default.
146-
147-
To sign:
148-
149-
- The message **MUST** be an object type (`{...}`).
150-
- Serialize the message as [Canonical JSON]; call this SERIALIZED_BODY.
151-
- Sign SERIALIZED_BODY, base64-encode the result, and store it in `sig`.
152-
- Store `"raw-json-no-payload-type"` in `sigType`.
153-
- Optionally, compute a KEYID and store it in `keyid`.
154-
- Base64-encode SERIALIZED_BODY and store it in `payload`.
155-
156-
To verify:
157-
158-
- If `sigType != "raw-json-no-payload-type"`, use the
159-
[normal verification process](#steps) instead of this one.
160-
- Base64-decode `payload`; call this SERIALIZED_BODY. Reject if the decoding
161-
fails.
162-
- Base64-decode `sig` and verify SERIALIZED_BODY. Reject if either the
163-
decoding or the signature verification fails.
164-
- Parse SERIALIZED_BODY as a JSON object. Reject if the parsing fails or if
165-
the result is not a JSON object. In particular, the first byte of
166-
SERIALIZED_BODY **MUST** be `{`. Verifiers **MUST NOT** require
167-
SERIALIZED_BODY to be Canonical JSON.
168-
- Discard `payloadType` if present.
169-
170-
Backwards compatible signatures are not recommended because they lack the
171-
authenticated payloadType indicator.
172-
173-
This scheme is safe from rollback attacks because the first byte of
174-
SERIALIZED_BODY is 0x7b (`{`) in backwards compatibility mode and 0x02 in
175-
regular mode.
176-
177117
### Multiple signatures
178118
179119
A file may have more than one signature, which is equivalent to separate files
@@ -208,8 +148,10 @@ do so in the future.
208148

209149
### Differentiating between old and new formats
210150

211-
Verifiers can differentiate between the old and new wrapper format by detecting
212-
the presence of the `payload` field vs `signed` field.
151+
Verifiers can differentiate between the
152+
[old](https://github.com/in-toto/docs/blob/master/in-toto-spec.md#42-file-formats-general-principles)
153+
and new wrapper format by detecting the presence of the `payload` field (new
154+
format) vs `signed` field (old format).
213155

214156
## Design considerations
215157

@@ -315,15 +257,6 @@ Rationales for specific decisions:
315257
payloadType were not signed.
316258
- Also, URIs don't need to be registered while Media Types do.
317259

318-
- Why use payloadType "raw-json-no-payload-type" instead of assuming backwards
319-
compatible mode if payloadType is absent?
320-
321-
- We wanted to leave open the possibility of having an
322-
application-specific "default" value if payloadType is unspecified,
323-
rather than forcing the default to be backwards compatibility mode.
324-
- Note that specific applications can still choose backwards compatibility
325-
to be the default.
326-
327260
- Why not stay backwards compatible by requiring the payload to always be JSON
328261
with a "_type" field? Then if you want a non-JSON payload, you could simply
329262
have a field that contains the real payload, e.g. `{"_type":"my-thing",
@@ -340,47 +273,14 @@ Rationales for specific decisions:
340273
2. It would incur double base64 encoding overhead for non-JSON payloads.
341274
3. It is more complex than PAE.
342275

343-
## Backwards compatibility with existing TUF and in-toto signatures
344-
345-
### Current format
346-
347-
The
348-
[old signature format](https://github.com/in-toto/docs/blob/master/in-toto-spec.md#42-file-formats-general-principles)
349-
used by [TUF] and [in-toto] has a BODY that is a regular JSON object and a
350-
signature over the [Canonical JSON] serialization of BODY.
351-
352-
```json
353-
{
354-
"signed": <BODY>,
355-
"signatures": [{
356-
"keyid": "<KEYID>",
357-
"sig": "<Hex(Sign(CanonicalJson(BODY)))>"
358-
}]
359-
}
360-
```
361-
362-
To verify, the consumer parses the whole JSON file, re-serializes BODY using
363-
Canonical JSON, then verifies the signature.
364-
365-
### Detect if a document is using old format
366-
367-
To detect whether a signature is in the old or new format:
368-
369-
- If it contains a `payload` field, assume it is in the new format.
370-
- If it contains a `signed` field, assume it is in the old format.
371-
372-
To convert an existing signature to the new format:
373-
374-
- `new.payload = base64encode(CanonicalJson(orig.signed))`
375-
- `new.signatures[*].sigType = "raw-json-no-payload-type"`
376-
- `new.signatures[*].sig = base64encode(hexdecode(orig.signatures[*].sig))`
377-
- `new.signatures[*].keyid = orig.signatures[*].keyid`
378-
379-
To convert a [backwards compatible signature] to the old format:
276+
## Backwards Compatibility
380277

381-
- `old.signed = jsonparse(base64decode(new.payload))`
382-
- `old.signatures[*].sig = hexencode(base64decode(new.signatures[*].sig))`
383-
- `old.signatures[*].keyid = new.signatures[*].keyid`
278+
Backwards compatibility with the old format will be handled by the application
279+
and explained in the corresponding application-specific change proposal, namely
280+
[ITE-5](https://github.com/in-toto/ITE/pull/13) for in-toto and via the
281+
principles laid out in
282+
[TAP-14](https://github.com/theupdateframework/taps/blob/master/tap14.md) for
283+
TUF.
384284

385285
## Testing
386286

@@ -432,7 +332,6 @@ Signed wrapper:
432332
- [JWS]
433333
- [PASETO]
434334

435-
[backwards compatible signature]: #backwards-compatible-signatures
436335
[Canonical JSON]: http://wiki.laptop.org/go/Canonical_JSON
437336
[in-toto]: https://in-toto.io
438337
[JWS]: https://tools.ietf.org/html/rfc7515

0 commit comments

Comments
 (0)