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
264 changes: 264 additions & 0 deletions CIPs/CIP-122.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
---
cip: 122
title: 3 DID Method
author: Joel Thorstensson (@oed)
discussions-to: https://forum.ceramic.network/t/cip-122-3-did-method
status: Draft
category: Standards
type: Core
created: 2021-02-12
updated: 2023-01-31
replaces: 79
---

## Simple Summary

<!--Provide a simplified and layman-accessible explanation of the CIP.-->
The 3 DID method enables users to create ephemeral or long lived identities.


## Abstract

<!--A short (~200 word) description of the technical issue being addressed.-->

The 3 DID method, or 3ID for short, is a simple purely generative DID method. It is designed to be combined with a CACAO based object capability system which enables the creation of both private and composable identities. While 3ID enables the creation of simple, short lived identities, the combination of the 3 DID method with [CIP-XXX - CapReg]() affords the subject the ability to delegate control of a 3ID to mutltiple other DIDs all while maintaining the ability to easily revoke access.


## 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. However, these accounts are inherently tied to a specific account and there is no way to maintain privacy. It's also no way to maintain a single long lived identity since specific accounts may only be used for a certain amount of time.

## Specification

<!--The technical specification should describe the syntax and semantics of any new feature.-->

### The did:3 identifier

> ```
> did:3:<cacao-mh>
> ```

The `<cacao-mh>` value is a `sha2-256` multihash over the CID of a CACAO object-capability. The object capability in question MUST be a SIWx message including a ReCap delegation as specified below. The value MUST be encoded as a multibase string, using `base58btc`.

***Simple example:***

> ```
> did:3:zQmWSW4kkZK2MTphhTLFb524ReZxaUjmdHo4uFiNKutAoQJ
> ```

### CRUD Operation Definitions

3IDs are created by creating a SIWx object-capability. Updating and deactivating is not supported natively in the DID method, but a 3ID can be combined with a [CapReg]() to delegate permissions to other DIDs or revoke any capability (including the capability that created the 3ID in the first place).

#### Create

Create and sign a [SIWx](https://chainagnostic.org/CAIPs/caip-122) message where:

- `address` - a blockchain address (e.g. `0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2`)
- `uri` - either a Key DID or the identifier for a new 3 DID (e.g. `did:3:new`)

If the `uri` contains a Key DID, this key can be used directly to take any actions on behalf of the newly created 3ID. Otherwise if the `uri` contains the new 3 DID identifier it indicates that no delegation is done at this point in time. Note that the issuer, as defined by the `address`, always have full control permissions over the newly created 3ID.

And resources contains the following ReCap object:

```java
{
"att": {
"did:3:new": { "*": [{}] }
}
}
```

When signing this would look something like this for the user:

```
example.com wants you to sign in with your Ethereum account:
0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2

I further authorize https://example.com to perform the following
actions on my behalf: (1) "*" for "did:3:new".

URI: did:3:new
Version: 1
Chain ID: 1
Nonce: n-0S6_WzA2Mj
Issued At: 2022-06-21T12:00:00.000Z
Resources:
- urn:recap:example:eyJkZWYiOlsicmVhZCJdLCJ0YXIiOnsibXkucmVzb3VyY2UuMSI6WyJhcHBlbmQiLCJkZWxldGUiXSwibXkucmVzb3VyY2UuMiI6WyJhcHBlbmQiXSwibXkucmVzb3VyY2UuMyI6WyJhcHBlbmQiXX19
```

##### Create the DID

Pseudo-code for how to compute the 3ID identifier.

```jsx
cacaoCID = ipld.put(CACAO(SIWx-message, signature))
did = 'did:3:' + multihash(cacaoCID)
```

#### Read

When reading a 3 DID, the DID document is simply created deterministically from the identifier.

##### Example DID Document

For `did:3:zQmWSW4kkZK2MTphhTLFb524ReZxaUjmdHo4uFiNKutAoQJ` the DID document looks as follows,

```json
{
"@context": [
"<https://www.w3.org/ns/did/v1>",
]
"id": "did:3:zQmWSW4kkZK2MTphhTLFb524ReZxaUjmdHo4uFiNKutAoQJ",
"verificationMethod": [{
"id": "#0",
"type": "capabilityHash",
"controller": "did:3:zQmWSW4kkZK2MTphhTLFb524ReZxaUjmdHo4uFiNKutAoQJ",
"multihash": "zQmWSW4kkZK2MTphhTLFb524ReZxaUjmdHo4uFiNKutAoQJ"
}],
"authentication": [ "#0" ],
"assertionMethod": [ "#0" ],
"capabilityDelegation": [ "#0" ],
"capabilityInvocation": [ "#0" ],
}
```

See Appendix A for the registrations of `capabilityHash` and `multihash`.

#### Update

Updating a 3 DID is not possible. Note however that a 3 DID may be used together with object capabilities and a revocation registry, for example [CapReg](). In this case it would be possible to delegate permissions to any new DID or revoke any capability.

#### Deactivate

In order to deactivate a 3ID all capabilities will need to be revoked including the capability with referenced by `<cacao-mh>`.

### Object Capabilities

The 3 DID method relies heavily on the fact that object-capabilities can be used to delegate permissions. It further relies on the `*` permission when delegating authority to give full control over the DID itself and all resources it control. When combined with a way to revoke and notralize capabilities, such as [CapReg](), 3ID can now add and remove any DID as a controller. Including revoking the `<cacao-mh>` capability itself, without revoking DIDs that have been delegated to before `<cacao-mh>` was revoked!

This way of using an object-capability registry is very similar to how adding and removing verification methods from the DID document works in traditional DID methods.

#### Delegating full DID control

In order to delegate full control over the 3ID to another DID the following ReCap should be used:

```json
{
"att":{
"did:3:zQmWSW4kkZK2MTphhTLFb524ReZxaUjmdHo4uFiNKutAoQJ": {
"*": [{}]
}
}
}
```

#### Delegate with exceptions

Say you want to give a DID the ability to act as your 3ID, but you don't want this DID to be able to delegate full DID control further, nor revoke any capabilities. Then you can add an exclusion to the delegation.

```json
{
"att":{
"did:3:zQmWSW4kkZK2MTphhTLFb524ReZxaUjmdHo4uFiNKutAoQJ": {
"*": [{ "exlude": "ceramic:/<streamid>" }]
}
}
}
```

#### Using a 3ID in Ceramic

In order to act on behalf of a 3ID that controls a Ceramic stream, a delegation can be created by the `address` that created the 3ID. Or if a delegation to another DID has been created as described above, the delegatee can create a re-delegation. As long as there's a valid delegation chain back to the capability identified by `<cacao-mh>`, the ReCap delegation described below will be valid for the 3ID.

```json
{
"tar":{
"ceramic://*?model=zkfif...": {
"crud/mutate": [],
"crud/read": []
}
}
}
```

## 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.-->

While most DID methods include full public keys, or other DIDs as verification methods 3ID chooses to use hash of an object-capability as its verification method. One of the main use cases for 3ID is to connect multiple PKH DIDs into a single identifier on Ceramic using object-capability chains. While doing so publically is fine for some use cases, the ability to do so privately is quite important for many. Using a *capability hash* enables more privacy since the DIDs that are delegated to doesn'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 which session key was delegated to.

### Cryptographic Agility

The 3 DID method itself doesn't really limit what cryptography can be used. It boils down to what the system that interprets the actual object capabilities is capable of. In Ceramic this includes the following, but is not limited to, and can be extended in the future:

* `ed25519`
* `secp256k1`
* `secp256r1`

Once good post quantum cryptography becomes more widely available extending Ceramic to support that will also be fairly straight forward.


## Backwards Compatibility
Copy link
Contributor

Choose a reason for hiding this comment

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

This talks about backwards compat for users of the old 3id, but what about backwards compat for existing users of did:pkh? Will they have a migration path to 3id that doesn't cause them to lose all their data/streams? I'm thinking about what Orbis brought up in our call with them today about being forced to start from scratch multiple times.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is out of scope for this specification. This would be added on top, e.g. using a mechanism similar to caip10-links. See Grafting DIDs paragraph of this article: https://blog.ceramic.network/accounts-evolution-of-3id/

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't really follow how that helps with backwards compatibility? Can you now use your 3id to update your streams that are controlled by your old did:pkh?

Copy link
Contributor Author

@oed oed Feb 10, 2023

Choose a reason for hiding this comment

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

Can you now use your 3id to update your streams that are controlled by your old did:pkh?

Haven't thought about this use case. Interesting, would need to think about how this could be done securely. Perhaps the did:pkh could delegate */* (or did/control) as a capability to the did:3.


<!--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.-->
Previous iterations of 3ID relied on the TileDocument stream type and an interpretation layer above that translated the tile contents to a DID document. That approach had numerious flaws the main one being the impossibility of privacy. This version of the spec deviates from the previous version in that it fully relies on object-capabilities and the existance of [CapReg](), while the DID itself remains purely generative. This is a great improvement but unfortunately it is not possible to make an upgrade in a backwards compatible manner. Instead all implementers are recommended to follow this specification only.

## Privacy Requirements

The 3 DID method provides a unique privacy enhancement over most other DID methods in that subject only need to reveal hashes of object-capabilities in order to use it. While the simplest way of implementing usage of the system would imply pulicly revealing these object-capabilities, it is indeed possible to create zero-knowledge proofs of the valididty of an object-capability without revealing its content.
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
The 3 DID method provides a unique privacy enhancement over most other DID methods in that subject only need to reveal hashes of object-capabilities in order to use it. While the simplest way of implementing usage of the system would imply pulicly revealing these object-capabilities, it is indeed possible to create zero-knowledge proofs of the valididty of an object-capability without revealing its content.
The 3 DID method provides a unique privacy enhancement over most other DID methods in that subject only need to reveal hashes of object-capabilities in order to use it. While the simplest way of implementing usage of the system would imply publicly revealing these object-capabilities, it is indeed possible to create zero-knowledge proofs of the validity of an object-capability without revealing its content.


## Security Considerations

3ID derives most of its security properties from the Ceramic protocol. Most notably *censorship resistance*, *decentralization*, and requiring a minimal amount of data to be synced to completely verify the integrity of a 3ID. For more details see the Ceramic [specification](https://github.com/ceramicnetwork/ceramic/blob/master/SPECIFICATION.md).

## Reference Implementations

Currently no reference implementation for 3ID exists.

## Appendix A: Registrations

This appendix contains all regsitrations necessary for the 3 DID method.

### Verification method property

**Property name:** `multihash`

The multihash property is used to specify a multibase-encoded multihash. Usually this is a hash over an object-capability.

* [Multihash specification](https://github.com/multiformats/multihash)
* [Multibase specification](https://github.com/multiformats/multibase)

### Verification Method Type

**Type name:** `capabilityHash`

The capabilityHash verification method type indicates that the verification method is the hash of a CACAO. For a signature to be valid under a specific capabilityHash verification method, the proof must show that there is a valid delegation chain from the CACAO that corresponds with the given hash. In the most trivial case this can be achived by revealing the CACAO itself as part of the proof, a verifier can then check the hashed value of the CACAO. However, zero-knowledge proofs may be used to remove the need to reveal the CACAO, improving privacy for the DID subject.

* [CAIP-74: CACAO - Chain Agnostic CApability Object](https://chainagnostic.org/CAIPs/caip-74)

### Multidid code

**Code:** `0x12` - sha2-256

## Appendix B: Multidid encoding

```
<multidid-code><method code><id-length><hash-bytes><url-length><url-bytes>
```

Where:

- `multidid-code` - a varint encoding of `0x0d1d`
- `method-code` - a varint encoding of `0x12`
- `id-lenght` - varint representing the length of the id hash
- `hash-bytes` - MUST contain exactly the number of bytes specified byte the method code
- `url-length` - a varint describing the length of the `url-bytes` parameter
- `url-bytes` - a UTF-8 encoded string representing the [DID URL parameters](https://www.w3.org/TR/did-core/#did-url-syntax)

Given a 3 DID `<cacao-mh>` byte string it's trivial to encode a multidid by simply prepending it with `varint(0x0d1d)`, and appending the url component.

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
4 changes: 3 additions & 1 deletion CIPs/CIP-79/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