Skip to content

Commit aabb994

Browse files
stevenjbkioshn
andauthored
feat(rust): Upgrade the Catalyst Key Id to be a more general Catalyst ID which can be used both as a Key ID and a registration ID. (#159)
* feat(docs): Enhance the catalyst rbac URI so it can be used as a general identifier as well as a key identifier * fix(rust): rename the kid_uri to just an id_uri to better reflect its type * fix(rust): remove cruft * feat(rust): New catalyst IdUri type to replace the more limited Kid * docs(docs): cleanup the project dict * docs(docs): Replace <key> with a concrete valid example public key * docs(docs): Fix documentation inconsistencies * Update docs/src/architecture/08_concepts/rbac_id_uri/catalyst-id-uri.md Co-authored-by: bkioshn <[email protected]> * fix(docs): Spelling issue * Update rust/catalyst-types/src/id_uri/mod.rs Co-authored-by: bkioshn <[email protected]> * Update docs/src/architecture/08_concepts/rbac_id_uri/catalyst-id-uri.md Co-authored-by: bkioshn <[email protected]> * fix(rust): Remove role and rotation from new as we should use `with_role` and `with_rotation` to set them. * fix(rust): Fail correctly if converting from &[u8] and the data isn't valid UTF8. * docs(rust): fix comment * docs(docs): add nsecs to project dictionary * fix(rust): clamp a specific nonce, in case it was attempted to be set out of range. * docs(rust): improve documentation of a number of public functions in the `IdUri` type. * fix(rust): Fix doc test --------- Co-authored-by: bkioshn <[email protected]>
1 parent 7f180cb commit aabb994

File tree

12 files changed

+848
-340
lines changed

12 files changed

+848
-340
lines changed

.config/dictionaries/project.dic

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ nextest
169169
nolfs
170170
notadb
171171
nsec
172+
nsecs
172173
OCSP
173174
Oleksandr
174175
oneshot
@@ -239,8 +240,8 @@ slotno
239240
smac
240241
stevenj
241242
stringzilla
242-
subsec
243243
subnetwork
244+
subsec
244245
symlinkat
245246
syscall
246247
tacho
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
title: RBAC KID (Key Identifier) URI
22
arrange:
3-
- kiduri.md
3+
- catalyst-id-uri.md

docs/src/architecture/08_concepts/rbac_kid_uri/kiduri.md renamed to docs/src/architecture/08_concepts/rbac_id_uri/catalyst-id-uri.md

Lines changed: 86 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
Title: RBAC Key Identifier URI Specification
2+
Title: RBAC Catalyst Identifier URI Specification
33
Category: Catalyst
44
Status: Proposed
55
Authors:
@@ -11,6 +11,8 @@ Created: 2025-01-05
1111
License: CC-BY-4.0
1212
---
1313

14+
<!-- cspell: words Fftx -->
15+
1416
* [Abstract](#abstract)
1517
* [Motivation: why is this CIP necessary?](#motivation-why-is-this-cip-necessary)
1618
* [Specification](#specification)
@@ -20,8 +22,7 @@ License: CC-BY-4.0
2022
* [`authority` - `host`](#authority---host)
2123
* [List of defined hosts](#list-of-defined-hosts)
2224
* [`authority` - `userinfo`](#authority---userinfo)
23-
* [Lists of defined subnetwork `userinfo` values](#lists-of-defined-subnetwork-userinfo-values)
24-
* [Cardano](#cardano)
25+
* [Example `userinfo` with a `hostname`](#example-userinfo-with-a-hostname)
2526
* [`path`](#path)
2627
* [Reference Implementation](#reference-implementation)
2728
* [Test Vectors](#test-vectors)
@@ -33,39 +34,44 @@ License: CC-BY-4.0
3334

3435
## Abstract
3536

36-
Definition of a [URI] which allows for RBAC keys used for different purposes to be easily and
37+
Definition of a [URI], which allows for RBAC keys used for different purposes to be easily and
3738
unambiguously identified.
3839

3940
## Motivation: why is this CIP necessary?
4041

41-
There is a need to identify which Key from a RBAC registration was used to sign data.
42+
There is a need to identify which RBAC Registration is referenced,
43+
or which Key from a RBAC registration was used to sign data.
4244
RBAC defines a universal keychain of different keys that can be used for different purposes.
4345
They can be used not only for Signatures, but also Encryption.
4446

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+
Sometimes all that is required is to identify the individual keychain.
48+
Other times a specific key on the chain needs to be referenced.
49+
50+
Therefore, there needs to be an unambiguous and easy to lookup identifier to signify which keychain,
51+
or key in a particular chain was used for a particular purpose.
4752

48-
This document defines a [URI] scheme to unambiguously define a particular key with reference to a
49-
particular RBAC keychain.
53+
This document defines a [URI] scheme to unambiguously define a keychain or a specific key within the keychain.
5054

5155
## Specification
5256

5357
### URI
5458

55-
The RBAC Kid is formatted using a [Universal Resource Identifier].
59+
The Catalyst RBAC ID is formatted using a [Universal Resource Identifier].
5660
Refer to [RFC3986] for the specification of the URI format.
5761

5862
### `scheme`
5963

60-
The [scheme](https://datatracker.ietf.org/doc/html/rfc3986#section-3.1) **MUST** be `kid.catalyst-rbac`;
64+
The [scheme](https://datatracker.ietf.org/doc/html/rfc3986#section-3.1) **MUST** be `id.catalyst`.
65+
66+
When used as a Catalyst ID, where only catalyst IDs would be used, the scheme can be omitted.
6167

6268
### `authority`
6369

6470
The [authority](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) references the blockchain or network
6571
the key was registered within.
6672

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`.
73+
It is perfectly valid for an ID Uri to reference a different network than the place where the ID or Key is used.
74+
For example, a `cardano` ID can be used to post documents to `IPFS`.
6975
Its purpose is to define WHERE the key was registered, and nothing more.
7076

7177
The Authority will consist of a `host` and optional `userinfo`.
@@ -76,32 +82,45 @@ The [host](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2)
7682
refers to the network type where the RBAC registration was made.
7783
It **IS NOT** resolvable with **DNS**, and **IS NOT** a public host name.
7884
It is used as a decentralized network identifier.
79-
The consumer of the `KID` must be able to resolve these host names.
85+
The consumer of the `ID` must be able to resolve these host names to known and supported blockchain networks.
86+
87+
The hostname may have one or more subdomains which could specify side-chains of a particular network,
88+
or test networks.
8089

8190
##### List of defined hosts
8291

8392
| `host` | Description |
8493
| --- | --- |
8594
| `cardano` | Cardano Blockchain |
95+
| `preprod.cardano` | Preprod Cardano Blockchain test network |
96+
| `preview.cardano` | Preview Cardano Blockchain test network |
8697
| `midnight` | Midnight Blockchain |
8798
| `ethereum` | Ethereum Blockchain |
8899
| `cosmos` | Cosmos Blockchain |
89100

101+
This list is indicative of the host names that can be used, any hostname is valid provided it is
102+
capable of storing catalyst RBAC registration keychains.
103+
90104
#### `authority` - `userinfo`
91105

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.
106+
The [userinfo] is used to hold a user defined readable name that can be attached to the keychain.
107+
It may contain an optional `nonce` which is separated from the user's name by a `:` and replaces a
108+
traditional password used for HTTP basic authentication.
95109

96-
##### Lists of defined subnetwork `userinfo` values
110+
Because the name is not unique, and is provided by the user, it is informational only.
111+
A URI is identical, provided the hostname and path are the same, the [userinfo] does not play
112+
a part in validating or finding the catalyst keychain being referenced.
97113

98-
###### Cardano
114+
The `nonce` part contained in the `password` component of the username *MUST* be an integer,
115+
and it is the number of seconds since 1970 UTC, when the Catalyst ID URI was generated.
99116

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 |
117+
Applications which use the `nonce` will define its use, anything that does not use the `nonce` will ignore it.
118+
119+
##### Example `userinfo` with a `hostname`
120+
121+
* `anne@cardano` - username `anne` no nonce.
122+
* `blake:1737101079@midnight` - username `blake` with nonce 1737101079.
123+
* `:173710179@ethereum` - no username with nonce 173710179.
105124

106125
### `path`
107126

@@ -115,13 +134,17 @@ The overall `path` specification is: `<initial role0 key>/<role>/<rotation>#encr
115134
* This does not change, even if the Initial Role 0 key is revoked.
116135
* This allows for an unambiguous identifier for the RBAC keychain.
117136
* It is not necessarily the key being identified.
118-
* `<role>` - This is the Role number being used.
137+
* An example Role 0 Key is `FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE`
138+
* `<role>` - *Optional* This is the Role number being used.
119139
* 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.
140+
* If it is not defined, then its default value is 0.
141+
* If it is not defined, there can be no `<rotation>` part of the path following.
142+
* `<rotation>` - *Optional* This is the rotation of the defined role key being identified.
121143
* It starts at 0 for the first published key for the role, and increments by one for each subsequent published rotation.
122144
* This number refers to the published sequence of keys for the role in the RBAC registration keychain,
123145
not the index used in the key derivation.
124146
* It is positive and no greater than 65535.
147+
* If not present, it defaults to 0.
125148
* `#encrypt` - [Fragment](https://datatracker.ietf.org/doc/html/rfc3986#section-3.5)
126149
disambiguates Encryption Public Keys from signing public keys.
127150
* Roles can have 1 active public signing key, and 1 active public encryption key.
@@ -134,26 +157,52 @@ The first implementation will be Catalyst Voices.
134157

135158
## Test Vectors
136159

137-
* `kid.catalyst-rbac://cardano/<key>/0/0`
160+
* `id.catalyst://cardano/FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE`
161+
* A Signing key registered on the Cardano Main network.
162+
* Role 0 - Rotation 0.
163+
* `username` - undefined.
164+
* `nonce` - undefined.
165+
* In this example, it is identical to `FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/0/0` or
166+
`FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/0`.
167+
* `id.catalyst://cardano/FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/0`
168+
* A Signing key registered on the Cardano Main network.
169+
* Role 0 - Rotation 0.
170+
* `username` - undefined.
171+
* `nonce` - undefined.
172+
* In this example, it is identical to `FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/0/0` or
173+
`FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE`.
174+
* `id.catalyst://gary@cardano/FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/0/0`
138175
* A Signing key registered on the Cardano Main network.
139176
* 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`
177+
* `username` - `gary`.
178+
* `nonce` - undefined.
179+
* In this example, it is identical to `FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE` or
180+
`FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/0`.
181+
* `id.catalyst://[email protected]/FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/7/3`
142182
* A Signing key registered on the Cardano pre-production network.
143183
* Role 7 - Rotation 3.
144-
The Key for Role 7, and its third published rotation
184+
* `username` - `faith`
185+
* `nonce` - undefined.
186+
* The Key for Role 7, and its third published rotation
145187
(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`
188+
* `id.catalyst://faith:173710179@preprod.cardano/FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/2/0#encrypt`
147189
* A Public Encryption key registered on the Cardano pre-production network.
148190
* Role 2 - Rotation 0.
149-
The initially published Public Encryption Key for Role 2.
150-
* `kid.catalyst-rbac://midnight/<key>/0/1`
191+
* `username` - `faith`
192+
* `nonce` - 173710179.
193+
* The initially published Public Encryption Key for Role 2.
194+
* `id.catalyst://:173710179@midnight/FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/0/1`
151195
* A Signing key registered on the Midnight Blockchain Main network
152196
* 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.
197+
* `username` - undefined.
198+
* `nonce` - 173710179.
199+
* In this example, it is NOT the same as the `FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE`,
200+
as it identifies the first rotation after `FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE`.
201+
* `id.catalyst://midnight/FftxFnOrj2qmTuB2oZG2v0YEWJfKvQ9Gg8AgNAhDsKE/2/1#encrypt`
202+
* A Public Encryption key registered on the Midnight Blockchain Main network.
156203
* Role 2 - Rotation 1.
204+
* `username` - undefined.
205+
* `nonce` - undefined.
157206

158207
## Rationale: how does this CIP achieve its goals?
159208

@@ -178,3 +227,4 @@ This document is licensed under [CC-BY-4.0](https://creativecommons.org/licenses
178227
[Universal Resource Identifier]: https://datatracker.ietf.org/doc/html/rfc3986
179228
[RFC3986]: https://datatracker.ietf.org/doc/html/rfc3986
180229
[Base64 URL]: https://datatracker.ietf.org/doc/html/rfc4648#section-5
230+
[userinfo]: (https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1)

rust/cardano-blockchain-types/deps.tmp

Lines changed: 0 additions & 61 deletions
This file was deleted.

rust/catalyst-types/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ num-traits = "0.2.19"
2626
orx-concurrent-vec = { version = "3.2.0", features = ["serde"] }
2727
pallas-crypto = { version = "0.30.1", git = "https://github.com/input-output-hk/catalyst-pallas.git", rev = "9b5183c8b90b90fe2cc319d986e933e9518957b3" }
2828
serde = { version = "1.0.217", features = ["derive", "rc"] }
29-
thiserror = "2.0.9"
29+
thiserror = "2.0.11"
3030
base64-url = "3.0.0"
31-
uuid = { version = "1.11.0", features = ["v4", "v7", "serde"] }
31+
uuid = { version = "1.12.0", features = ["v4", "v7", "serde"] }
32+
chrono = "0.4.39"
3233
fmmap = { version = "0.3.3", features = ["sync", "tokio-async"] }
3334
once_cell = "1.20.2"
3435
tracing = "0.1.41"

rust/catalyst-types/src/kid_uri/errors.rs renamed to rust/catalyst-types/src/id_uri/errors.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ use super::{key_rotation::KeyRotationError, role_index::RoleIndexError};
77

88
/// Errors that can occur when parsing a `KidUri`
99
#[derive(Display, Error, Debug)]
10-
pub enum KidUriError {
10+
pub enum IdUriError {
1111
/// Invalid KID URI
12-
InvalidURI(#[from] fluent_uri::error::ParseError),
13-
/// Invalid Scheme, not a KID URI
12+
InvalidURI(#[from] fluent_uri::error::ParseError<String>),
13+
/// Invalid Scheme, not a ID URI
1414
InvalidScheme,
1515
/// Network not defined in URI
1616
NoDefinedNetwork,
17+
/// Invalid Nonce
18+
InvalidNonce,
1719
/// Path of URI is invalid
1820
InvalidPath,
1921
/// Role 0 Key in path is invalid
@@ -30,4 +32,6 @@ pub enum KidUriError {
3032
InvalidRotationValue(#[from] KeyRotationError),
3133
/// Encryption key Identifier Fragment is not valid
3234
InvalidEncryptionKeyFragment,
35+
/// Invalid Text encoding
36+
InvalidTextEncoding(#[from] std::string::FromUtf8Error),
3337
}

rust/catalyst-types/src/kid_uri/key_rotation.rs renamed to rust/catalyst-types/src/id_uri/key_rotation.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@ pub enum KeyRotationError {
2121
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2222
pub struct KeyRotation(u16);
2323

24+
impl KeyRotation {
25+
/// Default Key Rotation
26+
pub const DEFAULT: KeyRotation = KeyRotation(0);
27+
28+
/// Is the `KeyRotation` the default value
29+
#[must_use]
30+
pub fn is_default(self) -> bool {
31+
self == Self::DEFAULT
32+
}
33+
}
34+
35+
impl Default for KeyRotation {
36+
fn default() -> Self {
37+
Self::DEFAULT
38+
}
39+
}
40+
2441
impl From<u16> for KeyRotation {
2542
fn from(value: u16) -> Self {
2643
Self(value)

0 commit comments

Comments
 (0)