@@ -33,13 +33,16 @@ The signature format is a JSON message of the following form:
33
33
"payload" : " <Base64(SERIALIZED_BODY)>" ,
34
34
"payloadType" : " <PAYLOAD_TYPE>" ,
35
35
"signatures" : [{
36
- … ,
36
+ "keyid" : " <KEYID> " ,
37
37
"sig" : " <Base64(Sign(PAE(UTF8(PAYLOAD_TYPE), SERIALIZED_BODY)))>"
38
- }, … ]
38
+ }]
39
39
}
40
40
```
41
41
42
- where:
42
+ Empty fields may be omitted. [ Multiple signatures] ( #multiple-signatures ) are
43
+ allowed.
44
+
45
+ Parameters:
43
46
44
47
* SERIALIZED_BODY is the byte sequence to be signed.
45
48
@@ -55,6 +58,14 @@ where:
55
58
- https://theupdateframework.com/Root/v1.0.5
56
59
- etc...
57
60
61
+ * KEYID is an optional, unauthenticated hint indicating what key and algorithm
62
+ was used to sign the message. As with Sign(), details are agreed upon
63
+ out-of-band by the signer and verifier. It ** MUST NOT** be used for security
64
+ decisions; it may only be used to narrow the selection of possible keys to
65
+ try.
66
+
67
+ Functions:
68
+
58
69
* PAE() is the
59
70
[ PASETO Pre-Authentication Encoding] ( https://github.com/paragonie/paseto/blob/master/docs/01-Protocol-Versions/Common.md#authentication-padding ) ,
60
71
where parameters ` type ` and ` body ` are byte sequences:
64
75
le64(n) := 64-bit little-endian encoding of `n`, where 0 <= n < 2^63
65
76
```
66
77
67
- * Sign() is an arbitrary digital signature format. Details must be agreed upon
78
+ * Sign() is an arbitrary digital signature format. Details are agreed upon
68
79
out-of-band by the signer and verifier. This specification places no
69
80
restriction on the signature algorithm or format.
70
81
@@ -88,6 +99,7 @@ To sign:
88
99
SERIALIZED_BODY.
89
100
- Sign PAE(UTF8(PAYLOAD_TYPE), SERIALIZED_BODY), base64-encode the result, and
90
101
store it in `sig`.
102
+ - Optionally, compute a KEYID and store it in `keyid`.
91
103
- Base64-encode SERIALIZED_BODY and store it in `payload`.
92
104
- Store PAYLOAD_TYPE in `payloadType`.
93
105
@@ -102,33 +114,34 @@ To verify:
102
114
fails.
103
115
104
116
Either standard or URL-safe base64 encodings are allowed. Signers may use
105
- either, and verifiers must accept either.
117
+ either, and verifiers **MUST** accept either.
106
118
107
119
### Backwards compatible signatures
108
120
109
121
To convert existing signatures from the current format to the new format,
110
- `"backwards-compatible-json"` must be added to the payload type URI to indicate
111
- that the signature is over the raw payload. This allows the signatures to remain
122
+ `"backwards-compatible-json"` is added to the payload type URI to indicate that
123
+ the signature is over the raw payload. This allows the signatures to remain
112
124
valid while avoiding the verifier from having to use [Canonical JSON].
113
125
114
126
```json
115
127
{
116
128
"payload": "<Base64(CanonicalJson(BODY))>",
117
129
"payloadType": "<URI>/backwards-compatible-json",
118
130
"signatures" : [{
119
- … ,
120
- "sig" : "<Base64(Sign(CanonicalJson(BODY)))>"
121
- }, … ]
131
+ "keyid": "<KEYID>" ,
132
+ "sig": "<Base64(Sign(CanonicalJson(BODY)))>"
133
+ }]
122
134
}
123
135
```
124
136
125
137
Support for this backwards compatibility mode is optional.
126
138
127
139
To sign:
128
140
129
- - BODY ** must ** be an object type (` {...} ` ).
141
+ - BODY ** MUST ** be an object type (` {...} ` ).
130
142
- Serialize BODY as [ Canonical JSON] ; call this SERIALIZED_BODY.
131
143
- Sign SERIALIZED_BODY, base64-encode the result, and store it in ` sig ` .
144
+ - Optionally, compute a KEYID and store it in ` keyid ` .
132
145
- Base64-encode SERIALIZED_BODY and store it in ` payload ` .
133
146
- Store ` "<URI>/backwards-compatible-json" ` in ` payloadType ` .
134
147
@@ -142,16 +155,35 @@ To verify:
142
155
decoding or the signature verification fails.
143
156
- Parse SERIALIZED_BODY as a JSON object. Reject if the parsing fails or if
144
157
the result is not a JSON object. In particular, the first byte of
145
- SERIALIZED_BODY must be ` { ` . Verifiers ** must not ** require SERIALIZED_BODY
158
+ SERIALIZED_BODY ** MUST ** be ` { ` . Verifiers ** MUST NOT ** require SERIALIZED_BODY
146
159
to be Canonical JSON.
147
160
148
161
Backwards compatible signatures are not recommended because they lack the
149
162
authenticated payloadType indicator.
150
163
151
164
This scheme is safe from rollback attacks because the first byte of
152
- SERIALIZED_BODY must be 0x7b (` { ` ) in backwards compatibility mode and 0x02 in
165
+ SERIALIZED_BODY is 0x7b (` { ` ) in backwards compatibility mode and 0x02 in
153
166
regular mode.
154
167
168
+ ### Multiple signatures
169
+
170
+ A file may have more than one signature, which is equivalent to separate files
171
+ with individual signatures.
172
+
173
+ ``` json
174
+ {
175
+ "payload" : " <Base64(SERIALIZED_BODY)>" ,
176
+ "payloadType" : " <PAYLOAD_TYPE>" ,
177
+ "signatures" : [{
178
+ "keyid" : " <KEYID_1>" ,
179
+ "sig" : " <SIG_1>"
180
+ }, {
181
+ "keyid" : " <KEYID_2>" ,
182
+ "sig" : " <SIG_2>"
183
+ }]
184
+ }
185
+ ```
186
+
155
187
### Optional changes to wrapper
156
188
157
189
The standard wrapper is JSON with an explicit ` payloadType ` . Optionally,
@@ -286,9 +318,9 @@ over the [Canonical JSON] serialization of BODY.
286
318
{
287
319
"signed" : <BODY>,
288
320
"signatures" : [{
289
- … ,
321
+ "keyid" : " <KEYID> " ,
290
322
"sig" : " <Hex(Sign(CanonicalJson(BODY)))>"
291
- }, … ]
323
+ }]
292
324
}
293
325
```
294
326
@@ -307,11 +339,13 @@ To convert an existing signature to the new format:
307
339
- ` new.payload = base64encode(CanonicalJson(orig.signed)) `
308
340
- ` new.payloadType = "<URI>/backwards-compatible-json" `
309
341
- ` new.signatures[*].sig = base64encode(hexdecode(orig.signatures[*].sig)) `
342
+ - ` new.signatures[*].keyid = orig.signatures[*].keyid `
310
343
311
344
To convert a backwards compatible signature to the old format:
312
345
313
346
- ` old.signed = jsonparse(base64decode(new.payload)) `
314
347
- ` old.signatures[*].sig = hexencode(base64decode(new.signatures[*].sig)) `
348
+ - ` old.signatures[*].keyid = new.signatures[*].keyid `
315
349
316
350
## Testing
317
351
0 commit comments