[![pkg.go.dev][GoBadge]][GoDoc]
![Coz][CozLogo]
[Presentation][Presentation]
Coz is a cryptographic JSON messaging specification that uses digital signatures and hashes to ensure secure, human-readable, and interoperable communication.
{
"pay": {
"msg": "Coz is a cryptographic JSON messaging specification.",
"alg": "ES256",
"now": 1623132000,
"tmb": "U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg",
"typ": "cyphr.me/msg/create"
},
"sig": "OJ4_timgp-wxpLF3hllrbe55wdjhzGOLgRYsGO1BmIMYbo4VKAdgZHnYyIU907ZTJkVr8B81A2K8U4nQA6ONEg"
}
See also the Coz philosophy
Coz defines standard fields for the objects pay, key, and coz.
Applications may include additional fields as desired. While all fields are
optional, omitting standard fields may limit compatibility. Binary values are
encoded as [RFC 4648 base 64 URI canonical with padding truncated][RFC4648]
(b64ut). JSON components are serialized into UTF-8 for signing, verification,
and hashing. All JSON fields must be unique, and unmarshalling JSON with
duplicate fields must result in an error. All timestamp values should be UTC
Unix time.

pay contains the fields alg, now, tmb, and typ and optionally any
additional application fields. In the first example msg is additional.
pay Standard Fieldsalg - Specific cryptographic algorithm. E.g. "ES256"now - Unix time of message signature. E.g. 1623132000tmb - Thumbprint of the signature's key. E.g. "U5XUZ..."typ - Type of pay. E.g. "cyphr.me/msg/create"msg - Message payload (string). E.g. "Coz is a cryptographic JSON messaging specification."dig - Digest of external content. E.g. "LSgWE4v..."typ's value may be used by applications as desired. The value is recommended
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","now","tmb","typ"] as defined by an application.
{
"alg":"ES256",
"now":1623132000,
"pub":"2nTOaFVm2QLxmUO_SjgyscVHBtvHEfo2rq65MvgNRjORojq39Haq9rXNxvXxwba_Xj0F5vZibJR3isBdOWbo5g",
"tag":"Coz Example Key",
"tmb":"U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg"
}
{
"alg":"ES256",
"now":1623132000,
"prv":"bNstg4_H3m3SlROufwRSEgibLrBuRq9114OvdapcpVA",
"pub":"2nTOaFVm2QLxmUO_SjgyscVHBtvHEfo2rq65MvgNRjORojq39Haq9rXNxvXxwba_Xj0F5vZibJR3isBdOWbo5g",
"tag":"Coz Example Key",
"tmb":"U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg"
}
key Standard Fieldskey - Key object. E.g. "key":{"alg":"ES256", ...}alg - Algorithm. E.g. "ES256"now - Key creation Unix time. E.g. 1623132000prv - Private component. E.g. "bNstg4..."pub - Public component. E.g. "2nTOaF..."tmb - Thumbprint. E.g. "U5XUZ..."typ - Application defined programmatic type. E.g. "cyphr.me/key"rvk - Key revocation Unix time. E.g. 1623132000The private component prv is not included in tmb generation. Also note that
tag must not be used programmatically while typ may be used
programmatically.
The JSON name coz may be used to wrap a coz.
{
"coz":{
"pay": {
"msg": "Coz is a cryptographic JSON messaging specification.",
"alg": "ES256",
"now": 1623132000,
"tmb": "U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg",
"typ": "cyphr.me/msg/create"
},
"sig": "OJ4_timgp-wxpLF3hllrbe55wdjhzGOLgRYsGO1BmIMYbo4VKAdgZHnYyIU907ZTJkVr8B81A2K8U4nQA6ONEg"
}
}
coz Standard Fieldscoz "Coz" Coz object. E.g. {"coz":{"pay":..., sig:...}}can "Canon" Canon of pay. E.g. ["msg","alg","now","tmb","typ"]cad "Canon digest" Digest of pay. E.g. "XzrXMG..."czd "Coz digest" Digest of ["cad","sig"]. E.g. xrYMu8...pay "Payload" Signed payload. E.g. "pay":{"msg":...,"alg":...}sig "Signature" Signature over cad. E.g. "sig":"OJ4_ti..."sig is the signature over the raw bytes of cad (the b64ut-decoded digest).
cad is not rehashed before 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.
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.
cozIncluding unnecessary labels is not recommended. For example, the JSON object
{"pay":{...},"sig":...} doesn't need the label coz if implicitly known by
applications. The following may generally be omitted: key may be looked up
by applications by using tmb, the fields can, cad, and czd are
recalculatable, and the label coz may be inferred.
A tautologic coz:
{
"coz": {
"pay": {
"msg": "Coz is a cryptographic JSON messaging specification.",
"alg": "ES256",
"now": 1623132000,
"tmb": "U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg",
"typ": "cyphr.me/msg/create"
},
"key": {
"alg":"ES256",
"now":1623132000,
"pub":"2nTOaFVm2QLxmUO_SjgyscVHBtvHEfo2rq65MvgNRjORojq39Haq9rXNxvXxwba_Xj0F5vZibJR3isBdOWbo5g",
"tag":"Coz Example Key",
"tmb":"U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg"
},
"can": ["msg","alg","now","tmb","typ"],
"cad": "XzrXMGnY0QFwAKkr43Hh-Ku3yUS8NVE0BdzSlMLSuTU",
"czd": "xrYMu87EXes58PnEACcDW1t0jF2ez4FCN-njTF0MHNo",
"sig": "OJ4_timgp-wxpLF3hllrbe55wdjhzGOLgRYsGO1BmIMYbo4VKAdgZHnYyIU907ZTJkVr8B81A2K8U4nQA6ONEg"
}
}
Simplified:
{
"pay": {
"msg": "Coz is a cryptographic JSON messaging specification.",
"alg": "ES256",
"now": 1623132000,
"tmb": "U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg",
"typ": "cyphr.me/msg/create"
},
"sig": "OJ4_timgp-wxpLF3hllrbe55wdjhzGOLgRYsGO1BmIMYbo4VKAdgZHnYyIU907ZTJkVr8B81A2K8U4nQA6ONEg"
}
A canon is a list of fields used for normalization, e.g. ["alg","pub"].
Coz objects are canonicalized for creating digests, signing, and verification.
The canon of pay is the currently present fields in order of appearance. The
following Coz fields have predefined canons:
cad's canon is pay's canon.tmb's canon is ["alg","pub"].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. The canonical form is serialized into UTF-8 for signing, verification, and hashing.
Canonical form generation steps:
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","pub"] and hashing algorithm specified by key.alg. For example, a key
alg of ES256 corresponds to the hashing algorithm SHA-256. The canonical
form of the example key is:
{"alg":"ES256","pub":"2nTOaFVm2QLxmUO_SjgyscVHBtvHEfo2rq65MvgNRjORojq39Haq9rXNxvXxwba_Xj0F5vZibJR3isBdOWbo5g"}
Hashing this canonical form results in the following digest, which is tmb:
U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg.
czd is the canonical digest of coz with the canon ["cad","sig"], which
results in the JSON {"cad":"...","sig":"..."}. czd's hash must align with
alg in pay.
The canonical digest of
pay is cad,["alg","pub"] is tmb,["cad","sig"] is czd.Using the first example, the following canonical digests are calculated:
tmb is U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqgcad is XzrXMGnY0QFwAKkr43Hh-Ku3yUS8NVE0BdzSlMLSuTU.czd is xrYMu87EXes58PnEACcDW1t0jF2ez4FCN-njTF0MHNo.Signing and verification functions must not mutate pay. Since pay's canon is
the present fields, no fields are removed when canonicalizing pay. Any
mutation of pay via can must occur by canon related functions.
The canonical digest of a binary file may simply be the digest of the file. The hashing algorithm and any other metadata may be denoted by an accompanying coz. For example, an image ("coz_logo_icon_256.png") may be referred to by its digest.
{
"alg":"SHA-256",
"file_name":"coz_logo_icon_256.png",
"id":"oDBDAg4xplHQby6iQ2lZMS1Jz4Op0bNoD5LK3KxEUZo"
}
For example, a file's digest, denoted by id, may represent the authorization
to upload a file to a user's account. Note that Coz associates the signature
alg ES256 to hashing alg SHA-256.
{
"pay": {
"alg": "ES256",
"file_name": "coz_logo_icon_256.png",
"id": "oDBDAg4xplHQby6iQ2lZMS1Jz4Op0bNoD5LK3KxEUZo",
"now": 1623132000,
"tmb": "U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg",
"typ": "cyphr.me/file/create"
},
"sig": "AV_gPaDCEd9OEyA1oZPo7LwpypzXkk2htmA-bEobpmcA4Vc7xNcaFPVaEBgU8DDCAZcQZcBHgRlOIjNk9g-Mkw"
}
When Coz digest values (such as tmb, dig, cad, or czd) are stored
outside of a coz and alg is not otherwise available, implementations should
use the following self-describing, non-JSON format in order to preserve the
cryptographic binding: the name of the algorithm, followed by the delimiter :,
followed by the b64ut value.
Examples:
ES256:U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg
SHA-256:oDBDAg4xplHQby6iQ2lZMS1Jz4Op0bNoD5LK3KxEUZo
Optionally, for additional disambiguation, the prefix coz: may be prepended to
the serialized form:
coz:ES256:U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg
A revoke is a self-signed declaration that a key is compromised. A Coz key may
revoke itself by signing a coz containing the field rvk with an integer value
greater than 0. The integer value 1 is suitable to denote revocation and the
current Unix timestamp is the suggested value.
rvk - Unix timestamp of key expiry.rvk and now must be positive integers less than 2^53 – 1
(9,007,199,254,740,991), which is the integer precision limit specified by
IEEE 754 minus one. Implementations must error if either value is not an
integer or is larger than 2^53 - 1.
Coz explicitly defines a self-revoke method so that third parties may revoke leaked keys. Systems storing Coz keys must accept valid revoke cozies where pay is under 2048 bytes and must immediately mark the associated key as revoked, even if a future revocation time is specified.
Key expiration policies, key rotation, backdating, and alternative revocation methods are outside the scope of Coz.
{
"pay": {
"alg": "ES256",
"msg": "Posted my private key online",
"now": 1623132000,
"rvk": 1623132000,
"tmb": "U5XUZots-WmQYcQWmsO751Xk0yeVi9XUKWQ2mGz6Aqg",
"typ": "cyphr.me/key/revoke"
},
"sig": "EhAsIL_w51NbCtzxFUcJiRMb1KmlxFSD-g7M-9wgqH9nnVHaEHiNyecfvfkrNf--KnfZyrsDIyWuT86MLNozQg"
}
alg specifies a parameter set and is a single source of truth for Coz
cryptographic operations.
Instead of a registry, supported algorithms and their exact parameters are defined in the reference implementation (Go). Implementations must match these parameters for interoperability and correctness.
For key algorithms, Coz assumes a Deterministic Public-from-Private
Derivability property: pub can be deterministically derived from prv and
not from any separate seed or intermediate value. Future algorithms must be
constructed to support this property.
Since the delimiter : is used for serialization, future Coz alg labels must
never use the character :.
The above sections starting at # Coz constitute the Coz specification. The following sections contain additional guidance, examples, philosophy, and implementation notes that are informative but not normative.
The Coz verifier is an in-browser tool for signing and verifying.
[Coz Verifier][Verifier]

There is also the [Simple Coz Verifier][Verifier_simple] that has the minimal amount of code needed for a basic Coz application. Its [codebase is in the CozJS repo][CozeJSVerifier] and may be locally hosted.
See docs/development.md for the development guide.
The sections above are defined as the main Coz specification, Coz core. There are no plans to increase Coz's scope or features in core other th