Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 207 additions & 0 deletions CIPs/cip-127.md
Original file line number Diff line number Diff line change
@@ -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

<!--Provide a simplified and layman-accessible explanation of the CIP.-->
The CapReg capability registry enables users to notarize and revoke any object-apability associated with their DID.


## Abstract

<!--A short (~200 word) description of the technical issue being addressed.-->
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

<!--Motivation is critical for CIPs that want to change the Ceramic protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the CIP solves. CIP submissions without sufficient motivation may be rejected outright.-->

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.
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

<!--The technical specification should describe the syntax and semantics of any new feature.-->
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be nice to make this more than a boolean, but rather a state string. For instance at some point I think it could be very valuable to have a distinction between revoking a capability and invalidating it only after the time it is revoked, vs doing a revocation that also retroactively invalidates all writes that were ever done with the capability - decreeing the capability to never have been valid in the first place. The latter could be useful if a user is tricked into signing a capability to a malicious app that then immediately starts publishing junk as the user.

Even if we only support "going forward" revocation in the first version, it would be nice to leave the door open to adding "retroactive" revocation as well in the future.

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 // <https://ipld.io/specs/codecs/dag-eth/chain/#transaction-ipld>

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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is interesting as it breaks some assumptions in the Ceramic code as it exists today. Currently we always assume the genesis CID can be loaded and used to create an initial StreamState object for the stream


```solidity
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this marked as solidity code?

<genesis-cid> := <varint cidv1><varint 0x55><varint 0x00><varint multidid-length><multidid>
```

3. Encode the Streamid (see Appending A for `stream-type`)

```solidity
<streamid> := <varint 0xce><varint stream-type><genesis-cid>
```

#### 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=<iso-time>` DID URL parameter.

```verilog
type EthereumHeader // <https://ipld.io/specs/codecs/dag-eth/chain/>

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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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:
CapReg relies heavily on object-capabilities as the 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://<capreg-streamid>": {
"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

<!--The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.-->

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While Ceramic generally strives towards not including state transtion logic in event streams

What does this mean?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't all of our streams have state transition logic?


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

<!--All CIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The CIP must explain how the author proposes to deal with these incompatibilities. CIP submissions without a sufficient backwards compatibility section may be rejected outright.-->
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/).
4 changes: 3 additions & 1 deletion CIPs/cip-79.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down