Skip to content

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.

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 uint is used, only CoAP Content Formats that match the string format are allowed.
media_type = (
    (uint .eq (50 / 60)) /
    (tstr .eq (
        "application/json" /
        "application/schema+json" /
        "application/cbor" /
        "application/cddl"
    ))
)

; 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_ref
  ?"template" => document_ref
  ?"reply" => document_ref
  ?"section" => section_ref
  ?"collaborators" => collaborators
  ?"revocations" => revocations
  ?"parameters" => document_ref
)

; 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 another Signed Document
document_ref = [ 1* [
  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

; 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 uint is used, only CoAP Content Formats that match the string format are allowed.
media_type = (
    (uint .eq (50 / 60)) /
    (tstr .eq (
        "application/json" /
        "application/schema+json" /
        "application/cbor" /
        "application/cddl"
    ))
)

; 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_ref
  ?"template" => document_ref
  ?"reply" => document_ref
  ?"section" => section_ref
  ?"collaborators" => collaborators
  ?"revocations" => revocations
  ?"parameters" => document_ref
)

; 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 another Signed Document
document_ref = [ 1* [
  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

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

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. These fields are defined here.

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 © 2024-2025 IOG Singapore, All Rights Reserved
License This document is licensed under CC-BY-4.0
Created 2024-12-27
Modified 2025-05-05
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.