Catalyst Signed Document Specification¶
Abstract¶
Project Catalyst requires a verifiable data format for the publication and validation of large volumes of off chain information.
The Catalyst Signed Documents Specification is based on COSE and provides the basis of this document specification.
Motivation¶
As Project Catalyst decentralizes via both on-chain and off-chain mechanisms, a reliable, standardized process for authenticating documents and their relationships is required.
Specification¶
Project Catalyst generates a large volume of off chain information. This information requires similar guarantees as on-chain data. It needs to be verifiably published and also immutable. However, we also require the ability to publish new versions of documents, and for documents to be able to securely reference one another.
Catalyst Signed Documents are based on COSE. Specifically, the COSE Sign format is used. This allows one or more signatures to be attached to the same document.
While every Catalyst Signed Document is a valid COSE Sign format document, not every COSE Sign format document is a valid Catalyst Signed Document. The following restrictions apply:
Unprotected Headers are not permitted¶
It is a requirement that any document that contains exactly the same data, must produce the same catalyst signed document. This means that unprotected headers, which do not form part of the data protected by the signature are not permitted. Any document which contains any unprotected headers is not a valid Catalyst Signed Document, even though it may be a valid COSE Sign formatted document.
Only defined metadata and COSE Headers are allowed¶
Each document type, defines a set of metadata and the COSE Headers which are allowed in that document type. Even if the Catalyst Signed document metadata exists in this specification, IF it is not defined as a valid metadata or COSE Header field for that particular document it may not be present. Unexpected but otherwise valid Metadata or COSE Header fields invalidate the Catalyst Signed Document.
No undefined metadata or unused COSE Headers may be present¶
COSE Header Fields which are defined by the COSE Specification, but are NOT defined as part of a Catalyst Signed Document may not be present. Any such COSE Header Fields present in the document render it an invalid Catalyst Signed Document.
Any metadata field that is not defined in this specification may not be present in any protected header. Unrecognized metadata fields in a document render it an invalid Catalyst Signed Document.
CBOR Deterministic Encoding MUST be used¶
The Catalyst Signed Document MUST be encoded using CBOR Deterministic Encoding. The "length-first core deterministic encoding requirements" variant of deterministic encoding MUST be used.
Signed Document CDDL Definition¶
CDDL Specification
; Catalyst Signed Document.
;
; A specific implementation of a COSE-SIGN data objects
; used by the Catalyst project to encapsulate and authenticate
; documents used within the system.
;
; See: https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si
; Catalyst Signed Document data object.
signed_document = COSE_Sign
; COSE-SIGN data object
COSE_Sign = [
COSE_Document_Headers,
payload : bstr / nil,
signatures : [+ COSE_Signature]
]
; COSE Document headers (only protected headers are used)
COSE_Document_Headers = (
protected : bstr .cbor COSE_Document_Header_Map,
unprotected : { COSE_Generic_Headers } ; Unused and ignored
)
; COSE Document Header Map
COSE_Document_Header_Map = {
COSE_Document_Standard_Headers,
Signed_Document_Metadata_Headers,
COSE_Generic_Headers
}
; COSE Standard headers used by a Document
COSE_Document_Standard_Headers = (
3 => media_type
?"content-encoding" => http_content_encoding
)
; Supported Content Media Types.
; If the Media Type is supported by COAP, then the `uint` CoAP encoded
; version of the media type must be used, in preference to the string.
media_type = (
(uint .eq (0 / 50 / 60 / 20000)) /
(tstr .eq (
"application/cbor" /
"application/cddl" /
"application/json" /
"application/schema+json" /
"text/css; charset=utf-8" /
"text/css; charset=utf-8; template=handlebars" /
"text/html; charset=utf-8" /
"text/html; charset=utf-8; template=handlebars" /
"text/markdown; charset=utf-8" /
"text/markdown; charset=utf-8; template=handlebars" /
"text/plain; charset=utf-8" /
"text/plain; charset=utf-8; template=handlebars"
))
)
; Supported Content Encoding Types
http_content_encoding = tstr .eq "br"
; Generic definition (does not include metadata constraints)
Signed_Document_Metadata_Headers = (
"type" => document_type
"id" => document_id
"ver" => document_ver
?"ref" => document_refs
?"template" => document_refs
?"reply" => document_refs
?"section" => section_ref
?"collaborators" => collaborators
?"revocations" => revocations
?"parameters" => document_refs
?"chain" => chain
)
; Document Type
document_type = [ 1* uuid_v4 ]
; UUIDv4
uuid_v4 = #6.37(bytes .size 16)
; Document ID
document_id = uuid_v7
; UUIDv7
uuid_v7 = #6.37(bytes .size 16)
; Document Version
document_ver = uuid_v7
; Reference to one or more Signed Documents
document_refs = [ 1* document_ref ]
; Reference to a single Signed Document
document_ref = [
document_id,
document_ver,
document_locator
]
; Where a document can be located, must be a unique identifier.
document_locator = {
"cid" => cid
}
; IPLD content identifier
; TODO: add size limits if possible
cid = #6.42(bytes)
; Reference to a section in a referenced document.
section_ref = json_pointer
; RFC6901 Standard JSON Pointer
json_pointer = text
; Allowed Collaborators on the next subsequent version of a document.
collaborators = [ * catalyst_id_kid ]
; UTF8 Catalyst ID URI encoded as a bytes string.
catalyst_id_kid = bytes
; List of revoked versions of this document.
revocations = [ * document_ver ] / true
; Reference to the previous Signed Document in a sequence.
; * `height` is of the CURRENT block.
; * `document_ref` is *ONLY* omitted in the very first document in a sequence.
chain = [height, ? document_ref]
; The consecutive sequence number of the current document
; in the chain.
; The very first document in a sequence is numbered `0` and it
; *MUST ONLY* increment by one for each successive document in
; the sequence.
;
; The FINAL sequence number is encoded with the current height
; sequence value, negated.
;
; For example the following values for height define a chain
; that has 5 documents in the sequence 0-4, the final height
; is negated to indicate the end of the chain:
; `0, 1, 2, 3, -4`
;
; No subsequent document can be chained to a sequence that has
; a final chain height.
height = int
; Generic Header definition
COSE_Generic_Headers = ( * COSE_label => COSE_values )
; COSE Map Generic Label
COSE_label = int / tstr
; COSE Map Generic Value
COSE_values = any
; An Individual Document Signature
COSE_Signature = [
COSE_Signature_Headers,
signature : bstr
]
; COSE Signature headers (only protected headers are used)
COSE_Signature_Headers = (
protected : bstr .cbor COSE_Signature_Header_Map,
unprotected : { COSE_Generic_Headers } ; Unused and ignored
)
; COSE Signature Header Map
COSE_Signature_Header_Map = {
COSE_Signature_Standard_Headers,
COSE_Generic_Headers
}
; COSE Signature headers
COSE_Signature_Standard_Headers = (
4 => catalyst_id_kid
)
CDDL
; Catalyst Signed Document.
;
; A specific implementation of a COSE-SIGN data objects
; used by the Catalyst project to encapsulate and authenticate
; documents used within the system.
;
; See: https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si
; Catalyst Signed Document data object.
signed_document = COSE_Sign
; COSE-SIGN data object
COSE_Sign = [
COSE_Document_Headers,
payload : bstr / nil,
signatures : [+ COSE_Signature]
]
; COSE Document headers (only protected headers are used)
COSE_Document_Headers = (
protected : bstr .cbor COSE_Document_Header_Map,
unprotected : { COSE_Generic_Headers } ; Unused and ignored
)
; COSE Document Header Map
COSE_Document_Header_Map = {
COSE_Document_Standard_Headers,
Signed_Document_Metadata_Headers,
COSE_Generic_Headers
}
; COSE Standard headers used by a Document
COSE_Document_Standard_Headers = (
3 => media_type
?"content-encoding" => http_content_encoding
)
; Supported Content Media Types.
; If the Media Type is supported by COAP, then the `uint` CoAP encoded
; version of the media type must be used, in preference to the string.
media_type = (
(uint .eq (0 / 50 / 60 / 20000)) /
(tstr .eq (
"application/cbor" /
"application/cddl" /
"application/json" /
"application/schema+json" /
"text/css; charset=utf-8" /
"text/css; charset=utf-8; template=handlebars" /
"text/html; charset=utf-8" /
"text/html; charset=utf-8; template=handlebars" /
"text/markdown; charset=utf-8" /
"text/markdown; charset=utf-8; template=handlebars" /
"text/plain; charset=utf-8" /
"text/plain; charset=utf-8; template=handlebars"
))
)
; Supported Content Encoding Types
http_content_encoding = tstr .eq "br"
; Generic definition (does not include metadata constraints)
Signed_Document_Metadata_Headers = (
"type" => document_type
"id" => document_id
"ver" => document_ver
?"ref" => document_refs
?"template" => document_refs
?"reply" => document_refs
?"section" => section_ref
?"collaborators" => collaborators
?"revocations" => revocations
?"parameters" => document_refs
?"chain" => chain
)
; Document Type
document_type = [ 1* uuid_v4 ]
; UUIDv4
uuid_v4 = #6.37(bytes .size 16)
; Document ID
document_id = uuid_v7
; UUIDv7
uuid_v7 = #6.37(bytes .size 16)
; Document Version
document_ver = uuid_v7
; Reference to one or more Signed Documents
document_refs = [ 1* document_ref ]
; Reference to a single Signed Document
document_ref = [
document_id,
document_ver,
document_locator
]
; Where a document can be located, must be a unique identifier.
document_locator = {
"cid" => cid
}
; IPLD content identifier
; TODO: add size limits if possible
cid = #6.42(bytes)
; Reference to a section in a referenced document.
section_ref = json_pointer
; RFC6901 Standard JSON Pointer
json_pointer = text
; Allowed Collaborators on the next subsequent version of a document.
collaborators = [ * catalyst_id_kid ]
; UTF8 Catalyst ID URI encoded as a bytes string.
catalyst_id_kid = bytes
; List of revoked versions of this document.
revocations = [ * document_ver ] / true
; Reference to the previous Signed Document in a sequence.
; * `height` is of the CURRENT block.
; * `document_ref` is *ONLY* omitted in the very first document in a sequence.
chain = [height, ? document_ref]
; The consecutive sequence number of the current document
; in the chain.
; The very first document in a sequence is numbered `0` and it
; *MUST ONLY* increment by one for each successive document in
; the sequence.
;
; The FINAL sequence number is encoded with the current height
; sequence value, negated.
;
; For example the following values for height define a chain
; that has 5 documents in the sequence 0-4, the final height
; is negated to indicate the end of the chain:
; `0, 1, 2, 3, -4`
;
; No subsequent document can be chained to a sequence that has
; a final chain height.
height = int
; Generic Header definition
COSE_Generic_Headers = ( * COSE_label => COSE_values )
; COSE Map Generic Label
COSE_label = int / tstr
; COSE Map Generic Value
COSE_values = any
; An Individual Document Signature
COSE_Signature = [
COSE_Signature_Headers,
signature : bstr
]
; COSE Signature headers (only protected headers are used)
COSE_Signature_Headers = (
protected : bstr .cbor COSE_Signature_Header_Map,
unprotected : { COSE_Generic_Headers } ; Unused and ignored
)
; COSE Signature Header Map
COSE_Signature_Header_Map = {
COSE_Signature_Standard_Headers,
COSE_Generic_Headers
}
; COSE Signature headers
COSE_Signature_Standard_Headers = (
4 => catalyst_id_kid
)
COSE Header Parameters¶
COSE documents define a set of standard COSE header parameters. All COSE Header Parameters are protected and MUST appear in the protected headers section of the document. The COSE header parameters defined and used by Catalyst Signed Documents are as follows:
content type
¶
Media Type/s allowed in the Payload
- Required : yes
- Cose Label : 3
- Format : Media Type
-
Supported Values:
- application/cbor : An RFC8949 Binary CBOR Encoded Document.
- application/cddl : A CDDL Document.
Note:
- This is an unofficial media type
- RFC9165 Additional Control Operators for CDDL are supported.
- Must not have Modules, schema must be self-contained.
- application/json : JSON Document
- application/schema+json : A JSON Schema Draft 2020-12 Document.
Note:
- This is currently an unofficial media type.
- text/css; charset=utf-8 : CSS Content used for styling HTML. CSS should use the least set of features possible to achieve the desired presentation to ensure the broadest compatibility.
- text/css; charset=utf-8; template=handlebars : CSS Content used for styling HTML. CSS should use the least set of features possible to achieve the desired presentation to ensure the broadest compatibility.
The text includes Handlebars type template fields that need processing and replacement prior to display. * text/html; charset=utf-8 : Formatted text using HTML5 markup for rich text. Only HTML5 syntax is supported. * text/html; charset=utf-8; template=handlebars : Formatted text using HTML5 markup for rich text. Only HTML5 syntax is supported.
The text includes Handlebars type template fields that need processing and replacement prior to display. * text/markdown; charset=utf-8 : Formatted text using Markdown for rich text. Markdown formatting is as defined by CommonMark.
IF the document includes HTML, then HTML5 syntax only is supported.
The following Markdown Extensions are also supported:
- None
- text/markdown; charset=utf-8; template=handlebars : Formatted text using Markdown for rich text. Markdown formatting is as defined by CommonMark.
IF the document includes HTML, then HTML5 syntax only is supported.
The following Markdown Extensions are also supported:
- None
The text includes Handlebars type template fields that need processing and replacement prior to display. * text/plain; charset=utf-8 : Plain Text with no markup or special formatting. Multiline Plain Text MUST always interpret
as a hard line break. * text/plain; charset=utf-8; template=handlebars : Plain Text with no markup or special formatting. Multiline Plain Text MUST always interpret
as a hard line break.
The text includes Handlebars type template fields that need processing and replacement prior to display.
content-encoding
¶
Supported HTTP Encodings of the Payload. If no compression or encoding is used, then this field must not be present.
- Required : optional
- Cose Label : content-encoding Custom Header
- Format : HTTP Content Encoding
- Supported Values:
Metadata¶
Catalyst Signed Documents extend the Header Parameters with a series of Metadata fields.
Signing Catalyst Signed Documents¶
Catalyst Signed Documents are based on the COSE Sign format. This allows one or more signatures to be attached to the same document. A catalyst signed document MUST have at least one valid signature attached. Multiple signatures may also be attached to the same document, where that is required.
Each signature is contained in an array of signatures attached to the document. The signatures contain protected headers, and the signature itself. The headers currently defined for the signatures are:
kid
¶
Catalyst ID URI identifying the Public Key.
The kid
is a UTF-8 encoded Catalyst ID URI.
Any kid
URI which conforms to the Catalyst ID specification may be used.
The Catalyst ID unambiguously defines both the signing keys and signing algorithm
used to sign the protected portion of the document.
- Required : yes
- Cose Label : 4
- Format : Catalyst ID
Copyright¶
Copyright | |
---|---|
License | This document is licensed under CC-BY-4.0 |
Created | 2024-12-27 |
Modified | 2025-05-30 |
Authors | Alex Pozhylenkov alex.pozhylenkov@iohk.io |
Steven Johnson steven.johnson@iohk.io |
Changelog¶
0.01 (2025-04-04)¶
- First Published Version
0.02 (2025-04-09)¶
- Add version control changelogs to the specification.
0.03 (2025-05-05)¶
- Use generalized parameters.
0.04 (2025-05-30)¶
- Improve and make document serialization more repeatable, and stricter.
- TODO: Define Systems parameters
- TODO: Define DReps documents.
- TODO: Define Proposer Profiles.
- TODO: Define Role 0 Profile.