Skip to content

Commit

Permalink
Merge pull request #7 from MarkLodato/pae-encoding
Browse files Browse the repository at this point in the history
Fully specify all encodings.
  • Loading branch information
adityasaky authored Dec 7, 2020
2 parents 492b18d + 539868e commit a4af882
Showing 1 changed file with 41 additions and 23 deletions.
64 changes: 41 additions & 23 deletions specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,63 +15,81 @@ misinterpretation of the payload. The serialized payload is encoded as a string
and verified by the recipient _before_ deserializing. A backwards compatible
variant is available.

## Specification
## Overview

$signing_spec does not rely on Canonical JSON, nor any other canonicalization
scheme. Instead, the producer records the signed bytes exactly as signed and the
consumer verifies those exact bytes before parsing. In addition, the signature
now includes an authenticated `payloadType` field indicating how to interpret
the payload.

## Specification

The signature format is a JSON message of the following form:

```json
{
"payload": "<Base64(SERIALIZED_BODY)>",
"payloadType": "<PAYLOAD_TYPE>",
"signatures": [{
…,
"sig": "<Base64(Sign(PAE([PAYLOAD_TYPE, SERIALIZED_BODY])))>"
"sig": "<Base64(Sign(PAE([UTF8(PAYLOAD_TYPE), SERIALIZED_BODY])))>"
}, ]
}
```

where PAE is the
[PASETO Pre-Authentication Encoding](https://github.com/paragonie/paseto/blob/master/docs/01-Protocol-Versions/Common.md#authentication-padding):
where:

```none
PAE([type, body]) := le64(2) || le64(len(type)) || type || le64(len(body)) || body
le64(n) := 64-bit little-endian encoding of `n`, where 0 <= n < 2^63
```
* 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:

- https://in-toto.io/Link/v0.9
- https://in-toto.io/Layout/v0.9
- https://theupdateframework.com/Root/v1.0.5
- etc...

* 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:

```none
PAE([type, body]) := le64(2) || le64(len(type)) || type || le64(len(body)) || body
le64(n) := 64-bit little-endian encoding of `n`, where 0 <= n < 2^63
```

The 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:
* Sign() is an arbitrary digital signature format. Details must be agreed upon
out-of-band by the signer and verifier. This specification places no
restriction on the signature algorithm or format.

- https://in-toto.io/Link/v0.9
- https://in-toto.io/Layout/v0.9
- https://theupdateframework.com/Root/v1.0.5
- etc...
* UTF8() is [UTF-8 encoding](https://tools.ietf.org/html/rfc3629),
transforming a unicode string to a byte sequence.

The switch from Hex to Base64 for `sig` is to save space and to be consistent
with `payload`.
* 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.

### Steps

To sign:

- Serialize BODY according to PAYLOAD_TYPE. Call the result SERIALIZED_BODY.
- Sign PAE([PAYLOAD_TYPE, SERIALIZED_BODY]), base64-encode the result, and
store it in `sig`.
- Sign PAE([UTF8(PAYLOAD_TYPE), SERIALIZED_BODY]), base64-encode the result,
and store it in `sig`.
- Base64-encode SERIALIZED_BODY and store it in `payload`.
- Store PAYLOAD_TYPE in `payloadType`.

To verify:

- Base64-decode `payload`; call this SERIALIZED_BODY. Reject if the decoding
fails.
- Base64-decode `sig` and verify PAE([PAYLOAD_TYPE, SERIALIZED_BODY]). Reject
if either the decoding or the signature verification fails.
- Base64-decode `sig` and verify PAE([UTF8(PAYLOAD_TYPE), SERIALIZED_BODY]).
Reject if either the decoding or the signature verification fails.
- Parse SERIALIZED_BODY according to PAYLOAD_TYPE. Reject if the parsing
fails.

Expand Down

0 comments on commit a4af882

Please sign in to comment.