Skip to content

Commit c8810d6

Browse files
saibatizokustevenjMr-Leshiy
authored
feat(rust/signed-doc): Add deserializer for Catalyst Signed Documents (#101)
* fix(rust/signed_doc): replace ULID with UUIDv7 * fix(rust/signed_doc): update meta.schema.json with definitions for uuid v4 and v7 * wip(rust/signed_doc): add basic structure for catalyst signed document API * refactor code from mk_signed_doc example into src/lib.rs * wip(rust/signed_doc): add API methods to get document metadata uuids * fix(rust/signed_doc): fix README * wip(rust/signed_doc): Impl Display for CatalystSignedDocument, add inspect example * wip(rust/signed_doc): print cose sign example * feat(rust/signed-doc): add hex crate * feat(rust/signed-doc): implement TryFrom<Vec<u8>> for CatalystSignedDocument * updates cat-signed-doc example to display deserialized cose sign documents. * fix(rust/signed_doc): cleanup and fix to DocumentRef serde * feat(rust/signed-doc): decode CoseSign from tagged or untagged bytes * feat(rust/signed-doc): add subcommand to inspect cose sign from hex-encoded strings * fix(rust/signed_doc): remove alg from top-level protected header * feat(rust/signed-doc): refactor metadata into a module * feat(rust/signed-doc): add types for UUIDv4 and UUIDv7 * fix(rust/signed_doc): update code and examples with Uuid types * fix(rust/signed_doc): refactor Metadata impl TryFrom<coset::cbor::Value> * fix(rust/signed_doc): refactor impl TryFrom<&coset::cbor::Value> for DocumentRef * fix UuidV4 and UuidV7 is_valid methods * fix(rust/signed-doc): remove unused dependency * fix(rust): Fix cargo.toml broken after merge * fix(rust/signed-doc): Update rust/signed_doc/src/lib.rs Correct name for Content-Encoding. Co-authored-by: Steven Johnson <[email protected]> * feat(rust/signed-doc): add type for Key ID * update example + tidy up metadata module * feat(rust/signed-doc): add types for Metadata fields. * add content_encoding and content_type fields to Metadata * update the example for making signed docs * docs(docs): Add formal specification for the RBAC KID URL format. * fix(docs): Fix the example Kid URI * feat(rust): Update the KidURI struct to match the formal spec (#139) * feat(rust/signed-doc): add mod payload * chore(rust/signed-doc): tidy up metadata mod * wip(rust/signed_doc): use Content type for document payload * fix(rust/signed_doc): ser/de for ContentType and ContentEncoding. * update example to build docs from metadata file * fix(rust/signed_doc): update metadata to require content type * ContentType::Json is default * fix(rust/signed_doc): update payload type * fix(rust/signed_doc): add brotli decompression * fix(rust/signed_doc): add metadata fields * wip(rust/signed_doc): use catalyst-types crate for kid uri * wip(rust/signed_doc): use catalyst-types crate for uuids * wip(rust/signed_doc): use catalyst-types crate for kid uri * remove redundant signatures field * update cose_protected_header_find function * fix DocumentId, DocumentRef structs * rename has_error to is_valid * rename crate * remove cose_raw Co-authored-by: Joaquín Rosales <[email protected]> * move additional_fields into another mod * change Try to TryFrom * fix(rust/signed_doc): decode and validate signatures * WIP: implement temporary Error type that will be replaced with a ProblemReport * update document content * remove parsing check * wip * refactor Metadata decoding * fix(rust/signed_doc): add serde::Serialize to AdditionalFields and DocumentRef * fix(rust/signed_doc): wip fixes to examples * feat(rust/signed-doc): serialize DocumentRef to cbor value * fix(rust/signed-doc): add missing metadata aditional fields * fix(rust/signed-doc): encode metadata aditional fields as REST items * fix(rust/signed-doc): handle validation errors with crate::error::Error * remove author field * add doc_meta getter * fix(rust/signed_doc): use minicbor encode/decode * wip: fix examples * fix(rust/signed-doc): remove unused dependencies * chore(docs): update spelling dictionary * fix(rust/signed-doc): update catalyst-types * update CatalystSignedDocument decoding * fix * make minicbor imports public * fix(rust/signed_doc): cleanup examples, fix signatures decoding * fix(rust/signed_doc): more cleanup * fix(rust/signed-doc): fix spelling * update Readme.md * fix README.md * fix earthfile --------- Co-authored-by: Steven Johnson <[email protected]> Co-authored-by: Steven Johnson <[email protected]> Co-authored-by: Mr-Leshiy <[email protected]> Co-authored-by: Joaquín Rosales <[email protected]>
1 parent 3381c5b commit c8810d6

20 files changed

+1400
-450
lines changed

.config/dictionaries/project.dic

+8
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ coverallsapp
4949
cpus
5050
crontabs
5151
crontagged
52+
csprng
5253
cstring
5354
dalek
5455
dashmap
@@ -122,6 +123,7 @@ jorm
122123
jormungandr
123124
Jörmungandr
124125
jsonschema
126+
kiduri
125127
lcov
126128
Leay
127129
Leshiy
@@ -209,6 +211,8 @@ reqwest
209211
retriggering
210212
ristretto
211213
rlib
214+
rngs
215+
rsplit
212216
rulelist
213217
RULENAME
214218
runable
@@ -235,6 +239,7 @@ smac
235239
stevenj
236240
stringzilla
237241
subsec
242+
subnetwork
238243
symlinkat
239244
syscall
240245
tacho
@@ -262,8 +267,11 @@ unlinkat
262267
upnp
263268
ureq
264269
userid
270+
userinfo
265271
utimensat
266272
UTXO
273+
uuidv4
274+
uuidv7
267275
vitss
268276
Vkey
269277
vkeywitness
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
title: RBAC KID (Key Identifier) URI
2+
arrange:
3+
- kiduri.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
---
2+
Title: RBAC Key Identifier URI Specification
3+
Category: Catalyst
4+
Status: Proposed
5+
Authors:
6+
- Steven Johnson <[email protected]>
7+
Implementors:
8+
- Catalyst Fund 14
9+
Discussions: []
10+
Created: 2025-01-05
11+
License: CC-BY-4.0
12+
---
13+
14+
* [Abstract](#abstract)
15+
* [Motivation: why is this CIP necessary?](#motivation-why-is-this-cip-necessary)
16+
* [Specification](#specification)
17+
* [URI](#uri)
18+
* [`scheme`](#scheme)
19+
* [`authority`](#authority)
20+
* [`authority` - `host`](#authority---host)
21+
* [List of defined hosts](#list-of-defined-hosts)
22+
* [`authority` - `userinfo`](#authority---userinfo)
23+
* [Lists of defined subnetwork `userinfo` values](#lists-of-defined-subnetwork-userinfo-values)
24+
* [Cardano](#cardano)
25+
* [`path`](#path)
26+
* [Reference Implementation](#reference-implementation)
27+
* [Test Vectors](#test-vectors)
28+
* [Rationale: how does this CIP achieve its goals?](#rationale-how-does-this-cip-achieve-its-goals)
29+
* [Path to Active](#path-to-active)
30+
* [Acceptance Criteria](#acceptance-criteria)
31+
* [Implementation Plan](#implementation-plan)
32+
* [Copyright](#copyright)
33+
34+
## Abstract
35+
36+
Definition of a [URI] which allows for RBAC keys used for different purposes to be easily and
37+
unambiguously identified.
38+
39+
## Motivation: why is this CIP necessary?
40+
41+
There is a need to identify which Key from a RBAC registration was used to sign data.
42+
RBAC defines a universal keychain of different keys that can be used for different purposes.
43+
They can be used not only for Signatures, but also Encryption.
44+
45+
Therefore, there needs to be an unambiguous and easy to lookup identifier to signify which key was
46+
used for a particular purpose.
47+
48+
This document defines a [URI] scheme to unambiguously define a particular key with reference to a
49+
particular RBAC keychain.
50+
51+
## Specification
52+
53+
### URI
54+
55+
The RBAC Kid is formatted using a [Universal Resource Identifier].
56+
Refer to [RFC3986] for the specification of the URI format.
57+
58+
### `scheme`
59+
60+
The [scheme](https://datatracker.ietf.org/doc/html/rfc3986#section-3.1) **MUST** be `kid.catalyst-rbac`;
61+
62+
### `authority`
63+
64+
The [authority](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) references the blockchain or network
65+
the key was registered within.
66+
67+
It is perfectly valid for a Kid to reference a different network than the place where the Key is used.
68+
For example, a `cardano` KID can be used to post documents to `IPFS`.
69+
Its purpose is to define WHERE the key was registered, and nothing more.
70+
71+
The Authority will consist of a `host` and optional `userinfo`.
72+
73+
#### `authority` - `host`
74+
75+
The [host](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2)
76+
refers to the network type where the RBAC registration was made.
77+
It **IS NOT** resolvable with **DNS**, and **IS NOT** a public host name.
78+
It is used as a decentralized network identifier.
79+
The consumer of the `KID` must be able to resolve these host names.
80+
81+
##### List of defined hosts
82+
83+
| `host` | Description |
84+
| --- | --- |
85+
| `cardano` | Cardano Blockchain |
86+
| `midnight` | Midnight Blockchain |
87+
| `ethereum` | Ethereum Blockchain |
88+
| `cosmos` | Cosmos Blockchain |
89+
90+
#### `authority` - `userinfo`
91+
92+
The [userinfo](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1)
93+
is used to distinguish a subnetwork from the primary main network.
94+
The absence of `userinfo` is used to indicate the primary main network.
95+
96+
##### Lists of defined subnetwork `userinfo` values
97+
98+
###### Cardano
99+
100+
| `userinfo` | Description |
101+
| --- | --- |
102+
| `preprod` | Cardano Pre-Production Network |
103+
| `preview` | Cardano Preview Network |
104+
| 0x<hex_number> | Cardano network identified by this magic number in hex |
105+
106+
### `path`
107+
108+
The [path](https://datatracker.ietf.org/doc/html/rfc3986#section-3.3) defines the actual key within the registration.
109+
Keys are defined relative to the very first Role0 Key registered in any RBAC registration.
110+
111+
The overall `path` specification is: `<initial role0 key>/<role>/<rotation>#encrypt`
112+
113+
* `<initial role 0 key>` - This is the very first role 0 key used to post the registration to the network.
114+
* It is the [Base64 URL] encoded binary data of the role 0 public key.
115+
* This does not change, even if the Initial Role 0 key is revoked.
116+
* This allows for an unambiguous identifier for the RBAC keychain.
117+
* It is not necessarily the key being identified.
118+
* `<role>` - This is the Role number being used.
119+
* It is a positive number, starting at 0, and no greater than 65535.
120+
* `<rotation>` - This is the rotation of the defined role key being identified.
121+
* It starts at 0 for the first published key for the role, and increments by one for each subsequent published rotation.
122+
* This number refers to the published sequence of keys for the role in the RBAC registration keychain,
123+
not the index used in the key derivation.
124+
* It is positive and no greater than 65535.
125+
* `#encrypt` - [Fragment](https://datatracker.ietf.org/doc/html/rfc3986#section-3.5)
126+
disambiguates Encryption Public Keys from signing public keys.
127+
* Roles can have 1 active public signing key, and 1 active public encryption key.
128+
* By default, the URL is referencing the signing public key.
129+
* If a public encryption key is being identified, then the fragment `#encrypt` is appended to the [Universal Resource Identifier].
130+
131+
## Reference Implementation
132+
133+
The first implementation will be Catalyst Voices.
134+
135+
## Test Vectors
136+
137+
* `kid.catalyst-rbac://cardano/<key>/0/0`
138+
* A Signing key registered on the Cardano Main network.
139+
* Role 0 - Rotation 0.
140+
In this example, it is exactly the same as the `<key>`.
141+
* `kid.catalyst-rbac://preprod@cardano/<key>/7/3`
142+
* A Signing key registered on the Cardano pre-production network.
143+
* Role 7 - Rotation 3.
144+
The Key for Role 7, and its third published rotation
145+
(i.e., the fourth key published, the first is the initial key, plus 3 rotations following it).
146+
* `kid.catalyst-rbac://preprod@cardano/<key>/2/0#encrypt`
147+
* A Public Encryption key registered on the Cardano pre-production network.
148+
* Role 2 - Rotation 0.
149+
The initially published Public Encryption Key for Role 2.
150+
* `kid.catalyst-rbac://midnight/<key>/0/1`
151+
* A Signing key registered on the Midnight Blockchain Main network
152+
* Role 0 - Rotation 1.
153+
In this example, it is NOT the same as the `<key>`, as it identifies the first rotation after `<key>`.
154+
* `kid.catalyst-rbac://midnight/<key>/2/1#encrypt`
155+
* A public encryption key registered on the Midnight Blockchain Main network.
156+
* Role 2 - Rotation 1.
157+
158+
## Rationale: how does this CIP achieve its goals?
159+
160+
By creating a [URI] to identify keys,
161+
we allow the unambiguous and flexible identification of any RBAC Key that was used for any purpose.
162+
163+
## Path to Active
164+
165+
### Acceptance Criteria
166+
167+
Working Implementation before Fund 14.
168+
169+
### Implementation Plan
170+
171+
Fund 14 project catalyst will deploy this scheme for Key Identification.
172+
173+
## Copyright
174+
175+
This document is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode).
176+
177+
[URI]: https://datatracker.ietf.org/doc/html/rfc3986
178+
[Universal Resource Identifier]: https://datatracker.ietf.org/doc/html/rfc3986
179+
[RFC3986]: https://datatracker.ietf.org/doc/html/rfc3986
180+
[Base64 URL]: https://datatracker.ietf.org/doc/html/rfc4648#section-5

rust/Earthfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ build:
5858
--args1="--libs=c509-certificate --libs=cardano-blockchain-types --libs=cardano-chain-follower --libs=hermes-ipfs" \
5959
--args2="--libs=cbork-cddl-parser --libs=cbork-abnf-parser --libs=cbork-utils --libs=catalyst-types" \
6060
--args3="--libs=catalyst-voting --libs=immutable-ledger --libs=vote-tx-v1 --libs=vote-tx-v2" \
61-
--args4="--bins=cbork/cbork --libs=rbac-registration --libs=signed_doc" \
61+
--args4="--bins=cbork/cbork --libs=rbac-registration --libs=catalyst-signed-doc" \
6262
--args5="--cov_report=$HOME/build/coverage-report.info" \
6363
--output="release/[^\./]+" \
6464
--junit="cat-libs.junit-report.xml" \

rust/signed_doc/Cargo.toml

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
2-
name = "signed_doc"
3-
version = "0.1.0"
2+
name = "catalyst-signed-doc"
3+
version = "0.0.1"
44
edition.workspace = true
55
authors.workspace = true
66
homepage.workspace = true
@@ -11,16 +11,20 @@ license.workspace = true
1111
workspace = true
1212

1313
[dependencies]
14-
15-
[dev-dependencies]
16-
clap = { version = "4.5.23", features = ["derive", "env"] }
14+
catalyst-types = { version = "0.0.1", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "r20250114-02" }
1715
anyhow = "1.0.95"
1816
serde = { version = "1.0.217", features = ["derive"] }
1917
serde_json = "1.0.134"
2018
# TODO: Bump this to the latest version and fix the code
2119
jsonschema = "0.18.3"
2220
coset = "0.3.8"
21+
minicbor = "0.25.1"
2322
brotli = "7.0.0"
24-
ed25519-dalek = { version = "2.1.1", features = ["pem"] }
25-
uuid = { version = "1.11.0", features = ["v4", "serde"] }
26-
ulid = { version = "1.1.3", features = ["serde"] }
23+
ed25519-dalek = { version = "2.1.1", features = ["pem", "rand_core"] }
24+
uuid = { version = "1.11.0", features = ["v4", "v7", "serde"] }
25+
hex = "0.4.3"
26+
thiserror = "2.0.9"
27+
28+
[dev-dependencies]
29+
clap = { version = "4.5.23", features = ["derive", "env"] }
30+
rand = "0.8.5"

0 commit comments

Comments
 (0)