Skip to content

Commit

Permalink
denote in the specification UTF-8 serialization for hashing, signing,…
Browse files Browse the repository at this point in the history
… and verification
  • Loading branch information
zamicol committed Jul 17, 2023
1 parent 58ce959 commit 5af99fd
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 50 deletions.
104 changes: 54 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[![pkg.go.dev][GoBadge]][GoDoc]
#### ⚠️ Coze is in Alpha and appreciates feedback. Use at your own risk.
#### ⚠️ Coze is in alpha. We appreciate feedback and contributions. Use at your own risk.

![Coze][CozeLogo]

Expand Down Expand Up @@ -33,11 +33,12 @@

### Coze Fields
Coze defines standard fields and applications may include additional fields as
desired. Coze JSON fields are case sensitive and unique. All fields are
optional, but omitting standard fields may limit compatibility. Binary values
are encoded as [RFC 4648 base 64 URI canonical with padding truncated][RFC4648]
(b64ut). The Coze objects `pay`, `key`, and `coze` have respective standard
fields. Unmarshalling JSON with duplicate fields must result in an error.
desired. The Coze objects `pay`, `key`, and `coze` have respective standard
fields. Coze JSON fields are case sensitive and unique. Unmarshalling JSON with
duplicate fields must result in an error. All fields are optional, but omitting
standard fields may limit compatibility. Binary values are encoded as [RFC 4648
base 64 URI canonical with padding truncated][RFC4648] (b64ut). For signing,
verification, and hashing JSON components are serialized into UTF-8.

#### All Coze Standard Fields
![Coze Standard Fields](docs/img/coze_standard_fields.png)
Expand All @@ -56,7 +57,7 @@ additional application fields. In the first example `msg` is additional.
to denote API information such as versioning, expected fields, and/or other
application defined programmatic functions. In the first example,
`"typ":"cyphr.me/msg"` denotes a `pay` with the fields
`["msg","alg","iat","tmb","typ"]` as defined by the application.
`["msg","alg","iat","tmb","typ"]` as defined by the application.


## Coze Key
Expand Down Expand Up @@ -96,11 +97,11 @@ application defined programmatic functions. In the first example,

Note that the private component `d` is not included in `tmb` generation. Also
note that `kid` must not be used programmatically while `typ` may be used
programmatically.
programmatically.


## Coze object
The JSON name `coze` may be used to wrap a coze.
The JSON name `coze` may be used to wrap a coze.

```JSON
{
Expand Down Expand Up @@ -130,19 +131,19 @@ signing. `czd`'s hashing algorithm must align with `alg` in `pay`. `czd` refers
to a particular signed message just as `cad` refers to a particular payload.
`cad` and `czd` are calculated from brace to brace, including the braces. `cad`
and `czd` are recalculatable and are recommended to be omitted from cozies,
although they may be useful for reference.
although they may be useful for reference.

As an added technical constraint, because `sig` and `czd` are used as
identifiers, `sig` must be non-malleable. Malleable schemes like ECDSA must
perform signature canonicalization that constrains signatures to a non-malleable
form.
form.

### Verbose `coze`
Including unnecessary labels is not recommended. For example, the JSON object
`{"pay":{...},"sig":...}` doesn't need the label `coze` if implicitly known by
applications. The following should generally be omitted: `key` may be looked up
by applications by using `tmb`, the fields `can`, `cad`, and `czd` are
recalculatable, and the label `coze` may be inferred.
recalculatable, and the label `coze` may be inferred.

A tautologic coze:

Expand Down Expand Up @@ -191,26 +192,26 @@ Simplified:
A **canon** is a list of fields used for normalization, e.g. `["alg","x"]`. Coze
objects are canonicalized for creating digests, signing, and verification. The
canon of `pay` is the currently present fields in order of appearance. The
following Coze fields have predefined canons:
following Coze fields have predefined canons:

- `cad`'s canon is `pay`'s canon.
- `tmb`'s canon is `["alg","x"]`.
- `czd`'s canon is `["cad","sig"]`.

Using a canon, the **canonical form** of an object is generated by removing
fields not appearing in the canon, ordering remaining fields by appearance in
the canon, and eliding unnecessary whitespace. Note that's since `pay`'s canon
is the present fields, no fields are removed when canonicalizing `pay`.
the canon, and eliding unnecessary whitespace. The canonical form is serialized
into UTF-8 for signing, verification, and hashing.

Generation steps for the canonical form:

- Omit fields not present in canon.
- Order fields by canon.
- Omit insignificant whitespace.

A **canonical digest** is generated by hashing the canonical form using the
hashing algorithm specified by `alg`. For example,`"ES256"`'s hashing algorithm
is `"SHA-256"`.
A **canonical digest** is generated by hashing the UTF-8 serialized canonical
form using the hashing algorithm specified by `alg`. For example,`"ES256"`'s
hashing algorithm is `"SHA-256"`.

The key thumbprint, `tmb`, is the canonical digest of `key` using the canon
`["alg","x"]` and hashing algorithm specified by `key.alg`. For example, a key
Expand Down Expand Up @@ -239,7 +240,8 @@ Using the first example, the following canonical digests are calculated:
- `czd` is `d0ygwQCGzuxqgUq1KsuAtJ8IBu0mkgAcKpUJzuX075M`.

Signing and verification functions must not mutate `pay`. Any mutation of `pay`
via `can` must occur by canon related functions.
via `can` must occur by canon related functions. Note that's since `pay`'s canon
is the present fields, no fields are removed when canonicalizing `pay`.

### Coze and Binaries
The canonical digest of a binary file may simply be the digest of the file. The
Expand Down Expand Up @@ -294,12 +296,12 @@ revocation is the suggested value for `rvk`.
}
```

- `rvk` - Unix timestamp of when the key was revoked.
- `rvk` - Unix timestamp of when the key was revoked.

Coze explicitly defines a self-revoke method so that third parties may revoke
leaked keys. Systems storing Coze keys should provide an interface permitting a
given Coze key to be marked as revoked by receiving a self-revoke message.
Self-revokes with future times must immediately be considered as revoked.
Self-revokes with future times must immediately be considered as revoked.

`rvk` must and `iat` should be a positive integer less than 2^53 – 1
(9,007,199,254,740,991), which is the integer precision limit specified by
Expand Down Expand Up @@ -348,11 +350,11 @@ The Coze verifier is an in-browser tool for signing and verifying.

There is also the [Simple Coze
Verifier][Verifier_simple] that has the minimal
amount of code needed for a basic Coze application.
amount of code needed for a basic Coze application.
Its [codebase is in the Cozejs repo][CozeJSVerifier] and may be locally hosted.

## CozeCLI
See the [Coze CLI repository][CozeCLI].
See the [Coze CLI repository][CozeCLI].

## Coze Implementations
- [Go Coze (this repo)][Coze]
Expand All @@ -370,13 +372,13 @@ specification into stone.)

Coze x (Coze extended) includes additional documentation, extra features,
drafts, proposals, early new algorithms support that's not yet adopted in Coze
core, and extended algorithm support.
core, and extended algorithm support.

See [Coze_go_x/normal][Normal] for an example of a Coze x feature not included in
Coze core.
Coze core.

Repository structure:
- [Coze][Coze] Main specification (core) and the Go Coze reference implementation.
- [Coze][Coze] Main specification (core) and the Go Coze reference implementation.
- [CozeX][CozeX] Coze extended. Additional documents, discussion, and new algorithms (Not a code repository).
- [CozeGoX][CozeGoX] Go implementation of extended features.
- [CozeJS][CozeJS] Javascript implementation of Coze core.
Expand All @@ -388,22 +390,24 @@ Repository structure:
#### Pronunciation? What does "Coze" mean?
We say "Co-zee" like a comfy cozy couch. Jared suggested Coze because it's
funny. The English word Coze is pronounced "kohz" and means "a friendly talk; a
chat" which is the perfect name for a messaging standard.
chat" which is the perfect name for a messaging standard.

#### "Coze" vs "coze"?
We use upper case "Coze" to refer to the specification, and "coze" to refer to
coze messages and objects.
We use upper case "Coze" to refer to the specification, and "coze"/"cozies" to
refer to messages.

#### Why release pre-alpha on 2021/06/08?
Coze was released on 2021/06/08 (1623132000) since it's 30 years and one day
after the initial release of PGP 1.0. We wrote a blog with more [details of
Coze's
genesis](https://cyphr.me/md/xlA-MSFwPxmWED4ZcNdxUy8OA22UPiLWlGQUQik8DwY).
genesis](https://cyphr.me/md/xlA-MSFwPxmWED4ZcNdxUy8OA22UPiLWlGQUQik8DwY).

# What is Coze useful for?
Coze can be used for anything needing cryptographic signing, such as IoT,
authentication, sessions, and cookies. We think most things on the Internet
should be cryptographically signed.
Coze's applications are endless as Coze is useful for anything needing
cryptographic signing. Coze is deployed in various business applications such as
user authentication (user login), authorization, product tracking, user
comments, user votes, chain of custody, Internet of things (IoT), sessions, and
cookies.

As a timely example, reddit.com/u/spez, the CEO of Reddit, [edited people's
comments on
Expand Down Expand Up @@ -454,10 +458,10 @@ Alternative schemes require a larger canon, `{"head":{...},"pay":{...}}`, or
concatenation like `digest(head) || digest(pay)`. By hashing only `pay`, the
"head" label and encapsulating braces are dropped, `pay:{...}`, and the label
`"pay"` may then be inferred, `{...}`. `{...}` is better than
`{"head":{...},"pay":{...}}`.
`{"head":{...},"pay":{...}}`.

Verifying a coze already requires hashing `pay`. Parsing `alg` from `pay` is a
small additional cost.
small additional cost.

#### JSON APIs? Can my API do versioning?
Coze is well suited for JSON APIs. API versioning may be handled by applications
Expand All @@ -475,7 +479,7 @@ capabilities see [Normal][Normal].
For applications, `pay.typ` may denote a canon. For example, a `typ` with value
`cyphr.me/msg/create` has a canon, as defined by the service, of ["alg", "iat",
"msg", "tmb", "typ"]. The service may reject a coze that's not canonicalized as
expected. For example, the service might reject cozies missing `iat`.
expected. For example, the service might reject cozies missing `iat`.

`Key.tmb` ignores `key.typ` because a static canon, `["alg","x"]` is always used
when producing key's `tmb`. Like `typ` in `pay`, applications may use `key.typ`
Expand All @@ -484,7 +488,7 @@ to specify custom fields, e.g. "first_seen" or "account_id" and field order.
#### ECDSA `x` and `sig` Bytes.
For ECDSA , (X and Y) and (R and S) are concatenated for `x` and `sig`
respectively. For ES512, which unlike the other ECDSA algorithms uses the odd
numbered P-521, X, Y, R, and S are padded before concatenation.
numbered P-521, X, Y, R, and S are padded before concatenation.

#### Why use `tmb` and not `x` for references in messages?
Coze places no limit on public key size, which can be very large. For example,
Expand All @@ -497,12 +501,12 @@ Additionally, `x` may be cryptographically significant for key security while
The standard fields provide Coze and applications fields with known types since
JSON has limited type identifiers. Coze has no required fields, however omitting
standard fields limits interoperability among applications, so it is suggested
to include standard fields appropriately.
to include standard fields appropriately.

Cozies that are missing the fields `pay.alg` and/or `pay.tmb` are **contextual
cozies**, denoting that additional information is needed for verification.
Caution is urged when deploying contextual cozies as including the standard
fields `pay.alg` and `pay.tmb` is preferred.
fields `pay.alg` and `pay.tmb` is preferred.

An **empty coze**, which has an empty `pay` and populated `sig`, is legitimate.
It may be verified if `key` is known. The following empty coze was signed with
Expand All @@ -524,7 +528,7 @@ initial reason for why Coze uses b64ut see [base64.md][base64.md].
We respect the various projects in the space. Other projects have noble goals
and we're thankful they exist. Coze is influenced by ideas from many others.
However existing solutions were not meeting our particular needs so we created
Coze.
Coze.

See [coze_vs.md][coze_vs] and the [introduction
presentation](https://docs.google.com/presentation/d/1bVojfkDs7K9hRwjr8zMW-AoHv5yAZjKL9Z3Bicz5Too/edit#slide=id.g1367bc4eb0f_0_6)
Expand All @@ -539,14 +543,14 @@ Systems may use `sig` as an integrity check via cryptographic verification. If
For keys, `x` and/or `tmb` may be recalculated and error on mismatch.Coze keys
cannot be integrity checked when `d`, `x`, or `tmb` are presented alone. In
situations needing integrity checking, we recommend including at least two
components. See [checksums.md][checksums] for more.
components. See [checksums.md][checksums] for more.

#### Performance hacks?
Coze is not optimized for long messages, but if early knowledge of Coze standard
fields is critical for application performance, put the Coze standard fields
first, e.g. `{"alg", "tmb", ...}`

#### I need to keep my JSON separate but inside a coze.
#### I need to keep my JSON separate but inside a coze.
If appending custom fields after the standard Coze fields isn't sufficient, we
suggest encapsulating custom JSON in "~", the last ASCII character. We've
dubbed this a "tilde encapsulated payload". For example:
Expand All @@ -571,16 +575,16 @@ For example, FIPS PUB 186-3 defines P-224, P-256, P-384, and P-521.
To learn more see this [walkthrough of ECDSA](https://learnmeabitcoin.com/technical/ecdsa).

#### Unsupported Things?
The following are out of scope or redundant.
The following are out of scope or redundant.

- `ES192`, `P-192` - Not implemented anywhere and dropped from later FIPS.
- `SHA1`, `MD5` - Not considered secure for a long time.
- `kty` - "Key type". Redundant by `alg`.
- `iss` - `tmb` fulfills this role. Systems that need something like an issuer,
associating messages with people/systems, can look up "issuer" based on
thumbprint. Associating thumbprints to issuers is the design we recommend.
- `exp` - "Expiration". Outside the scope of Coze.
- `nbf` - "Not before". Outside the scope of Coze.
thumbprint. Associating thumbprints to issuers is the design we recommend.
- `exp` - "Expiration". Outside the scope of Coze.
- `nbf` - "Not before". Outside the scope of Coze.
- `aud` - "Audience". Outside the scope of Coze, but consider denoting this with
`typ`.
- `sub` - "Subject". Outside the scope of Coze, but consider denoting this with
Expand Down Expand Up @@ -614,9 +618,9 @@ key.

#### Why are duplicate field names prohibited?
Coze explicitly requires that implementations disallow duplicate field names in
`coze`, `pay`, and `key`. Existing JSON implementations have varying behavior.
`coze`, `pay`, and `key`. Existing JSON implementations have varying behavior.
Douglas Crockford, JSON's inventor, [tried to fix this but it was decided it
was too late](https://esdiscuss.org/topic/json-duplicate-keys).
was too late](https://esdiscuss.org/topic/json-duplicate-keys).

Although Douglas Crockford couldn't change the spec forcing all implementations
to error on duplicate, his Java JSON implementation errors on duplicate names.
Expand Down Expand Up @@ -657,7 +661,7 @@ See also I-JSON and JSON5
- [JSON5][JSON5]


#### HTTP? HTTP Cookies? HTTP Headers?
#### HTTP? HTTP Cookies? HTTP Headers?
When using Coze with HTTP cookies, Coze messages should be JSON minified. For
example, we've encountered no issues using the first example as a cookie:

Expand All @@ -672,7 +676,7 @@ Coze prohibits signature malleability. See
[malleability_low_s.md][low_s].

#### Who created Coze?
Coze was created by [Cyphr.me](https://cyphr.me).
Coze was created by [Cyphr.me](https://cyphr.me).

#### Discussion? Social Media?
- We have a bridged Matrix and Telegram chat room. (This is where we are the most active)
Expand Down
1 change: 1 addition & 0 deletions coze_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ func ExampleCoze_MetaWithAlg() {
}

// Test no coze.pay.alg or alg given, which must error.
// Will error with Hash: invalid HshAlg "UnknownHshAlg")
cz2 := new(Coze)
err = json.Unmarshal(GoldenCozeNoAlg, cz2)
if err != nil {
Expand Down

0 comments on commit 5af99fd

Please sign in to comment.