diff --git a/CIPs/cip-127.md b/CIPs/cip-127.md new file mode 100644 index 0000000..8ce3661 --- /dev/null +++ b/CIPs/cip-127.md @@ -0,0 +1,207 @@ +--- +cip: 127 +title: CapReg - object-capability registry +author: Joel Thorstensson (@oed) +discussions-to: https://forum.ceramic.network/t/cip-127-capreg-object-capability-registry +status: Draft +category: RFC +created: 2023-04-28 +updated: 2023-04-28 +--- + +## Simple Summary + + +The CapReg capability registry enables users to notarize and revoke any object-apability associated with their DID. + + +## Abstract + + +Using a simple Ceramic stream, the capability registry enables users to notarize and revoke object-capabilities issued by their DID. The registry is based on hashes of object-capabilities encoded as CACAO. + + +## Motivation + + + +Currently in Ceramic the main accounts types are PKH DID. These are great because they enable existing wallets to be used directly with Ceramic. Once a PKH DID is used to delegate permissions to a session key. That delegation will remain valid until the capability expires. This could be a problem in the case of a stolen session key or a malicious application. By introducing a capability registry these capabilities can be revoked at any time by the main DID (PKH DID in the case above, but this would work for any DID method). A system that uses these object capabilities could refer to the registry to verify that the capability has not been revoked before it was used. + +## Specification + + +This specification describes the data structure of the capability registry, its validation and consensus logic, as well as how wallet UX would look like for someone using the registry. + + +### Capability Registry + +The capability registry is based on a self-certifying data structure represented as a special type of Ceramic stream. Each DID has uniquely *one* capability registry. Any object capability issued by this DID can be notarized and revoked in the registry. Every update to the registry is recorded as a *Data Event*. + +```verilog +type Prinicipal Bytes // multidid +type CACAOHash Bytes // multihash +type Varsig Bytes // varsig + +type Entry struct { + key CACAOHash + revoked Boolean // true if the capability has been revoked + ocap optional Link // optionally include the CID of the capability +} representation tuple +// The registry should eventually be a HAMT or verkle-tree data structure +type Regsitry { CACAOHash : Entry } +type Snapshot struct { + registry &Regsitry + actions [Entry] +} +``` + +#### Ceramic Stream + +```verilog +type Event InitEvent | DataEvent | TimeEvent + +type InitEvent &Prinicipal // an inline CID containing raw principal bytes + +type DataEvent struct { + id &InitEvent + prev [&Event] // optional CID pointer to previous event + prf [&CACAO] // capabilities used to emit this event + data &Snapshot + sig Varsig +} + +type EthereumTx // + +type BlockchainTimestamp struct { // https://chainagnostic.org/CAIPs/caip-168 + root Link + chainID String + txType String + txHash &EthereumTx +} + +type TimeEvent struct { + id &InitEvent + prev [&DataEvent] // should always be one CID + proof &BlockchainTimestamp + path String +} +``` + +#### Streamid + +Generating the streamid can be done in three steps, + +1. Generate the multidid representation of the DID (see [Multidid specification]()). + +2. Encode the multidid as an inline CID, + + ```solidity + := + ``` + +3. Encode the Streamid (see Appending A for `stream-type`) + + ```solidity + := + ``` + +#### Create a `DataEvent` + +New data events + +1. Attain a key with a valid capability chain to the most recent *previous data event(s)* + +2. Create one or more `Entry` objects and update the `State` from the + + previous data event(s): + + 1. Write the objects to a new array and store them on the `actions` field + 2. Also append them to the `registry` map + +3. Create the `DataEvent` struct, + + 1. Set `id` to the principal (an inline CID containing a multidid encoded 3ID), + 2. Add the capability chain used to the `prf` field + 3. Add the previous event(s) to the `prev` field + 4. Add the updated state to the `data` field + 5. Create a `Varsig` over the `DataEvent` with the key from (1) and add the `sig` field + +#### Validating a `DataEvent` + +The certification of a `DataEvent` can be validated using the following algorithm, + +1. The varsig validates agains the *aud* `Principal` of the referenced CACAOs + +2. The multihash of the CACAO CID (caphash) is one of: + + 1. CapHash is in the `Registry` and `revoked` is false + 2. CapHash is in the `Principal` and **not** in the `Registry` + +3. The CACAO *ability* is crud on the CapReg streamid + + +#### Consensus + +In case of two conflicting events (two events share the same `prev` value) the event with the earliest `TimestampEvent` should be processed first. Note that this might lead to the latter event being invalid due to its delegation chain being revoked. Also, a new event emitted after the conflict must reference both branches in its `prev` and resolve any conflict of the `Registry`. + +If there is no anchor for either event yet, the `DataEvent` with the lowest binary value of its CID will win. Note that if a `TimeEvent` appears this order might change. + +#### Verified timestamps + +For convenience, once a `TimeEvent` has been verified the data used to verify it can be stored as a receipt. This is helpful when resolving the registry at a particular point in time using the `?versionTime=` DID URL parameter. + +```verilog +type EthereumHeader // + +type TimestampRecipt struct { + unixtime Integer // same as block.Time + event &TimestampEvent + block &EthereumHeader + path String // ipld path in the block to find event.txHash +} +``` + +### Object Capabilities + +CapReg relies heavily on object-capabilities as they way to add and remove CACAO hashes in the registry. Write access to CapReg can be delegated in the same way as delegting access to any other stream in Ceramic. Example using ReCap: + +```json +{ + "tar":{ + "ceramic://": { + "crud/create": [{}], + "crud/delete": [{}] + } + } +} +``` + +As an extension, it would also be worth exploring the possibility of creating a zero-knowlege proof that proves that a specific CACAO hash is allowed to be added to the registry without revealing what the content of the CACAO itself. Simply the fact that the CACAO is valid should be enough to add it to the registry. + +## Rationale + + + +CapReg enables any DID to delegate full or partial permission to any other DID without having to worry about the capability getting lost since capabilities can now be revoked. The design requires some special logic for the state transition of the event stream to ensure that the capability is valid when the stream was updated. While Ceramic generally strives towards not including state transtion logic in event streams, for this particular case it seems difficult to avoid. + +While using capabilities in public is fine for some use cases, the ability to do so privately is quite important for many. Using *capability hashes* enables more privacy since the DIDs that are delegated to don't strictly need to be revealed. It is worth noting that revealing the CACAO object when used is the simplest way to prove a capability chain. However, it is possible to create zero-knowledge proofs that only reveal the hash of the capability used and the session key which was delegated to. + + +## Backwards Compatibility + + +n/a + +## Reference Implementations + +Currently no reference implementation for CapReg currently exists. + +## Appendix A: Registrations + +### Stream type code + +**Code:** `5` + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/CIPs/cip-79.md b/CIPs/cip-79.md index de3e7b5..4fcda28 100644 --- a/CIPs/cip-79.md +++ b/CIPs/cip-79.md @@ -3,10 +3,12 @@ cip: 79 title: 3ID DID Method Specification author: Joel Thorstensson (@oed) discussions-to: https://github.com/ceramicnetwork/CIP/issues/80 -status: Draft +status: Superseded category: Standards type: RFC created: 2021-02-12 +updated: 2023-01-31 +Superseded By: 122 --- # 3ID DID Method Specification diff --git a/README.md b/README.md index 6862587..536ee27 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ An editor will ask if anyone objects to it being finalized. If the editor decide - `Accepted (Core)`: an CIP of type Core that has been accepted by the core devs to be included in a future network upgrade. - `Final (Core)`: an CIP of type Core that has already been released in a network upgrade. - `Final (non-Core)`: a non-core CIP that has met all criteria and is finished. +- `Superseded`: has been superseded by a new CIP, should also include a `Superseded By` field pointing to the new CIP. # Editors - Michael Sena ([@michaelsena](http://github.com/michaelsena))