Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KERI event stream - events that effect did document key state #46

Merged
merged 5 commits into from
Sep 26, 2023
Merged
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
41 changes: 24 additions & 17 deletions spec/diddocuments.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

### Introduction
DID documents in this method are generated or derived from the key state of the
corresponding AID. If the AID in question is [[ref: non-transferrable]], then the
DID document is generated algorithmically from the DID value itself, and nothing
else. If the AID is [[ref: transferrable]], then the [[ref: KEL]] and the [[ref: TEL]]
are also required inputs to the generation algorithm.
corresponding AID. By processing the [[ref: KERI event stream]] of the AID, the generation algorithm will be reading the AID [[ref: KEL]] (and possibly [[ref: TEL]])
to produce the DID document.

DID documents for this method are pure JSON. They may be processed as JSON-LD by
prepending an `@context` if consumers of the documents wish.
Expand All @@ -15,16 +13,10 @@ is an approach similar to multibase, making them self-describing and terse.

### DID Document from KERI Events
The [[ref: KERI event stream]] represents a cryptographic chain
of custody from the [[ref: AID]] itself down to the current set of signing keys and next rotation key commitments,
as well as other data such as service endpoints. When generating a
DID document an implementation must "walk the [[ref: KEL]]" (follow the chain of key events) to determine the current key state. Due to the fact that the KERI protocol
allows for non-establishment event (events that don't change key state) to be intermixed in a [[ref: KERI event stream]] with establishment
events (those that change key state), the last event may not be an establishment event and thus can not be relied on to
provide key information. In addition, the current set of witnesses is calculated from the initial set declared in the
inception event and "adds" and "cuts" declared in rotation events.
of custody from the [[ref: AID]] itself down to the current set of keys and the cryptographic commitment to the next rotation key(s). The [[ref: KERI event stream]] also contains events that do not alter the [[ref: AID]] key state, but are useful for the DID document, such as the supported domains, current set of service endpoints, etc. A did:webs resolver produces the DID document by processing the [[ref: KERI event stream]] to determine the current key state. We detail the different events in (KERI event details)[#KERI-event-details] below and show how they change the DID Document. The mapping from [[ref: KERI event stream]] to the properties of the DID Document is the core of the did:webs resolver logic. There are many ways to receive the [[ref: KERI event stream]], but only one way to process a [[ref: KERI event stream]] to produce the verifiable DID document. Understanding the optimal way to retrieve the [[ref: KERI event stream]] is beyond the scope of the spec, but a reference implementation of the resolver that details these techniques is being developed alongside this spec. The important concepts are that the entire [[ref: KERI event stream]] is used to produce and verify the DID document.
Copy link
Contributor

Choose a reason for hiding this comment

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

I didn’t get a chance to review this before it was merged but still have comments.

Why the line "There are many ways to receive the [[ref: KERI event stream]]”? AFAIK, the way in did:webs to retrieve the KERI event stream is to GET the file. KERI may have other ways (and perhaps we can do a side-reference to that effect), but in did:webs, there is only one way.

Is that not right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I merged because I thought the PR was largely fixing typos, not doing something substantive.

Since the KERI event stream can be fetched by GETting the file from any of the DID locations (not necessarily the one where the DID doc was fetched), the statement about "many ways" could be referring to did:webs synonyms rather than non-did:webs KERI features. But that not have been the intent.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I created some confusion sorry about that @swcurran @dhh1128, the initial commits were a pass to cleanup prior to adding content, but then I added new content since i hadn't seen any reviews. Soon after, there was some significant activity (Markus/Stephen/Daniel all added input). I will update the PR title to reflect the more significant content.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this has been merged (sorry for that), instead of reverting I will do a follow-on PR based on our discussions here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn’t get a chance to review this before it was merged but still have comments.

Why the line "There are many ways to receive the [[ref: KERI event stream]]”? AFAIK, the way in did:webs to retrieve the KERI event stream is to GET the file. KERI may have other ways (and perhaps we can do a side-reference to that effect), but in did:webs, there is only one way.

Is that not right?

@swcurran I think the spec is migrating away from explicityly stating 'files' and toward 'KERI event stream' resources that is retrieved via a GET on the .keri for the did:webs DID..... that 'KERI event stream' could come from file(s), database(s), etc. and could be utilizing all kinds of interesting infrastructure. To address this and your related cache issue I give more details here
Happy to discuss, I appreciate the review and think we are getting close to the right level of abstraction for the spec.


In KERI the calculated values that result from walking the [[ref: KEL]] are referred to as the "current key state" and expressed
in the Key State Notice (KSN) record. An example of a KSN can be seen here:
In KERI the calculated values that result from processing the [[ref: KERI event stream]] are referred to as the "current key state" and expressed
in the Key State Notice (KSN) record. An example of a KERI KSN record can be seen here:

```json
{
Expand Down Expand Up @@ -226,12 +218,12 @@ For example, a KERI AID with only the following inception event in its KEL:
```

#### Verification Relationships
KERI AID public keys can be used to sign a variety of data. This includes but is not limited to logging into a website, challenge-response exchanges and credential issuances. It follows that for each public key in `k` two verification relationships must be generated in the DID document. One verification relationship of type `authentication` and one verification relationship of type `assertionMethod`. The `authentication` verification relationship defines that the DID controller can authenticate using each key and the `assertionMethod` verification relationship defines that the DID controller can express claims with each key (should we address multisig and thresholds here?).
KERI AID public keys can be used to sign a variety of data. This includes but is not limited to logging into a website, challenge-response exchanges and credential issuances. It follows that for each public key in `k` two verification relationships must be generated in the DID document. One verification relationship of type `authentication` and one verification relationship of type `assertionMethod`. The `authentication` verification relationship defines that the DID controller can authenticate using each key and the `assertionMethod` verification relationship defines that the DID controller can express claims with each key (TODO: address multisig and thresholds).
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this a statement about KERI keys, or about DIDs? I think this is about DIDs in general. Not sure why it is called out here in this way, as if it was a unique feature of KERI. The rest of this reads (to me, at least) about normal DIDDoc contents.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the point here is that KERI AID keys don't generally distinguish between authenticating the controller of the identifier and signing for that controller. In other words, the text is trying to make the point that the same key shows up in two verification relationships (usually), which is not a generally true assumption in all of DID-land.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@swcurran although I only meant to specify the TODO with my change, I read the meaning of this section the way that @dhh1128 explained. Since AIDs are KEL backed the key state applies to both verification relationships.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm…still doesn’t seem like something needed to be called out for did:webs. To create/evolve a the DID, I execute KERI events to accomplish my goal. If that requires I use some keys for authentication to make the changes, I don’t think it need be call out in the DIDDoc section.

Happy to leave it for now (especially since it is merged :-) ), but lets see how it reads in a final review.


References to verification methods in the DID document MUST use the relative form of the identifier, e.g., `"authentication": ["#<identifier>"]`.

#### Service Endpoints
In KERI, service endpoints are defined by 2 sets of signed data that follow the Best Available Data - Read, Update, Nullify (BADA-RUN) (ref?) rules for data processing. Detailing the rules of BADA-RUN is beyond the scope of this document but to summarize, the protocol ensures that all data is signed in transport and at rest and versioned to ensure only the latest signed data is available.
In KERI, service endpoints are defined by 2 sets of signed data that follow the Best Available Data - Read, Update, Nullify ([[ref: BADA-RUN]]) rules for data processing. The protocol ensures that all data is signed in transport and at rest and versioned to ensure only the latest signed data is available.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should this be “In did:webs service endpoints are defined by 2 sets of signed data using KERI’s Best…."

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the same for all services in the DIDDoc, or just the KERI services? If just the KERI services, I think it should be in the next section, with this intro section covering all DIDDoc services.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@swcurran great questions! I only meant to update the ref to BADA-RUN since we detailed it in security characteristics. I will tackle detailing service endpoints in a future PR. this PR is focused on a few small fixes (like this one) and key-state related content. Would it be okay to punt this to a new issue #48 ?


The two data sets used to define service endpoints are called Location Schemes and Endpoint Role Authorizations and are expressed in KERI `rpy` events. Location Schemes define URLs for any URL scheme that an AID has exposed. For example, the following `rpy` method declares that the AID `EIDJUg2eR8YGZssffpuqQyiXcRVz2_Gw_fcAVWpUMie1` exposes the URL `http://localhost:3902` for scheme `http`:

Expand Down Expand Up @@ -288,7 +280,7 @@ The current set of endpoint roles in KERI is contained in the following table:


##### KERI Service Endpoints as Services
As defined above in [KERI Service Endpoints](#KERI-Service-Endpoints) service endpoints roles beyond `witness` can be defined using Location Scheme and Endpoint Authorization records in KERI. This section will map the current roles in KERI to service `type` values in resulting DID documents and propose a new role in KERI to map to the existing `DIDCommMessaging` service type declared in DID Specification Registries (ref?).
As defined above in [KERI Service Endpoints](#KERI-Service-Endpoints) service endpoints roles beyond `witness` can be defined using Location Scheme and Endpoint Authorization records in KERI. This section will map the current roles in KERI to service `type` values in resulting DID documents and propose a new role in KERI to map to the existing [DIDCommMessaging](https://www.w3.org/TR/did-spec-registries/#didcommmessaging) service type declared in DID Specification Registries.

```json
{
Expand All @@ -314,7 +306,7 @@ TODO: Detail the transformation


#### Other Key Commitments
Data structures similar to Location Scheme and Endpoint Authorizations and managed in KERI using BADA-RUN could be created that would be used for declaring other types of keys, for example encryption keys, etc
Data structures similar to Location Scheme and Endpoint Authorizations and managed in KERI using [[ref: BADA-RUN]] could be created that would be used for declaring other types of keys, for example encryption keys, etc

TODO: Propose new data structures in KERI and Detail the transformation

Expand Down Expand Up @@ -500,3 +492,18 @@ Resulting DID document:
]
}
```

### Basic KERI event details
[DID Document from KERI Events](#did-document-from-keri-events) introduced the core [[ref: KERI event stream]] and related DID Document concepts. This section provides additional details regarding the basic types of KERI events and how they relate to the DID document.

#### Key state events
When processing the [[ref: KERI event stream]] there are two broad types of key state events (KERI parlance is 'establishment events') that can alter the key state of the DID document. Every [[ref: AID]] starts with an [[ref: inception event]]. If that inception event does not commit to a future set of rotation key hashes, then the AID is non-transferrable because the identifier can never change key state. If the inception event does commit to a future set of rotation key hashes, then the AID is transferrable and there could be future rotation events that transfer the key state from the current keys to the rotation keys that were committed to in the previous key state event.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should be “that can alter the key state of the AID.” The DIDDoc derives from the key state, but the DIDDoc doesn’t have key state.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the bit about the transferrable, non-transferrable should be in the inception event bullet point, not in the title.

I assume we can’t change this, but the term “transferrable” I find to be quite confusing. It means AFAIK that the the keys in the DID can’t be rotated. I’m sure there is a reason behind the term “transfer”...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this should be “that can alter the key state of the AID.” The DIDDoc derives from the key state, but the DIDDoc doesn’t have key state.

I've fixed this wording and it will be in the next PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the bit about the transferrable, non-transferrable should be in the inception event bullet point, not in the title.

I assume we can’t change this, but the term “transferrable” I find to be quite confusing. It means AFAIK that the the keys in the DID can’t be rotated. I’m sure there is a reason behind the term “transfer”...

The term "transferrable" means that control can be transferred from the current keys to the next keys that were committed to (via the rules of pre-rotation). Both inception and rotation events can provide transferability by specifying a set of next key hashes that commit to the transferability. It is also possible to end the ability to transfer control to next keys by not committing to a set of next keys. This could happen in the inception or rotation event. So perhaps I should keep it in this section above but be more explicit that it applies to both inception and rotation?

Copy link
Contributor

Choose a reason for hiding this comment

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

I’ve long heard in the broader community and used the term "rotate keys" for the operation we’re talking about. And we enable it in KERI by specifying evidence of “pre-rotation” keys. AFAIK, only the KERI community uses the “Transferrable” — which for me has no connection to key rotation. When I hear it, I jump to transferring control of the DID from one entity to another, or perhaps transfering a DID from one ledger (e.g. DID identifier) to another.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree that the pre-rotation mechanism must be included for the inception event and rotation events to enable additional rotations.

* [[def: Inception event]]: The inception event is the first event in the [[ref: KEL]] that establishes the AID. This defines the initial key set and if the controller(s) desire future key rotation (transfer) then the inception event must commit to a set of future rotation key hashes. When processing the [[ref: KERI event stream]], if there are no rotation events after the inception event, then this is the current key state of the AID and will be reflected in the DID Document as specified in [Verification Methods](#verification-methods) and [Verification Relationships](#verification-relationships). You can learn more about the inception event in the [KERI specification](https://trustoverip.github.io/tswg-keri-specification/draft-ssmith-keri.html#name-basic-terminology) and you can see an [example inception event](https://trustoverip.github.io/tswg-keri-specification/draft-ssmith-keri.html#name-inception-event). To learn about future rotation key commitment, see the sections about [pre-rotation](#pre-rotation) and the [KERI specification section on pre-rotation](https://trustoverip.github.io/tswg-keri-specification/draft-ssmith-keri.html#name-key-pre-rotation-concept)
* [[def: Rotation event]]: Rotation events come after inception events and can only change the key state to the previously committed to rotation keys and if the controller(s) desires future key rotation (transfer) then the rotation event must commit to a set of future rotation key hashes. When processing the [[ref: KERI event stream]], if there are rotation events after the inception event, then the last rotation event is the current key state of the AID and will be reflected in the DID Document as specified in [Verification Methods](#verification-methods) and [Verification Relationships](#verification-relationships). You can learn more about rotation events in the [KERI specification](https://trustoverip.github.io/tswg-keri-specification/draft-ssmith-keri.html#name-basic-terminology) and you can see an [example rotation event](https://trustoverip.github.io/tswg-keri-specification/draft-ssmith-keri.html#name-rotation-event-message-body). To learn about future rotation key commitment, see the sections about [pre-rotation](#pre-rotation) and the [KERI specification section on pre-rotation](https://trustoverip.github.io/tswg-keri-specification/draft-ssmith-keri.html#name-key-pre-rotation-concept)
Copy link
Contributor

Choose a reason for hiding this comment

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

Will there be more events added to this? I’m assuming there will be — adding keys, adding services, setting the DID URL, changing the DID URL, signing documents at least.

Copy link
Contributor Author

@2byrds 2byrds Sep 26, 2023

Choose a reason for hiding this comment

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

Yes, I tackled the basic key-state events first. Based on feedback from the group I will repeat the 'format' of this PR for these issues service enpoints, verifying DID urls, etc.

We have some upcoming multisig work by Markus, that should help detail how to add/remove keys.


### Delegation KERI event details
This section focuses on delegation relationships between KERI AIDs. [DID Document from KERI Events](#did-document-from-keri-events) introduced the core [[ref: KERI event stream]] and related DID Document concepts. This section provides additional details regarding the basic types of KERI events and how they relate to the DID document. [Basic KERI event details](#basic-keri-event-details) provides additional details on the basic types of KERI events and how they relate to the DID document.

#### Delegation key state events
* [[def: Delegated inception event]]: Establishes a delegated identifier for which either the delegator or the delegate can end the delegation commitment. All delegation relationships start with a delegated inception event. The KERI specification provides [an example of a delegated inception event](https://trustoverip.github.io/tswg-keri-specification/draft-ssmith-keri.html#name-delegated-inception-event-m).
* [[def: Delegated rotation event]]: Updates the delegated identifier commitment. Either the delegator or the delegate can end the delegation commitment. Any change to the [[ref: Delegated inception event]] key state or delegated rotation event key state requires a delegated rotation event. The KERI specification provides [an example of a delegated rotation event](https://trustoverip.github.io/tswg-keri-specification/draft-ssmith-keri.html#section-8.2)
6 changes: 4 additions & 2 deletions spec/keri.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The simplest AIDs (called [[ref: direct mode]] AIDs in KERI) have no additional

[[def: Pre-rotation]]

Optionally, the inception event of an AID can also reference the hash of the _next_ key that will be used to control the AID. This changes how the AID is derived: `derive( initial_public_key, next_key_hash )`. KERI calls this feature [[ref: pre-rotation]]; AIDs that use it are called [[ref: transferrable]] AIDs because their control can be transferred to new keys. AIDs that do not use pre-rotation cannot change their keys, and are thus thus [[ref: non-transferrable]].
Optionally, the inception event of an AID can also reference the hash of the _next_ key that will be used to control the AID. This changes how the AID is derived: `derive( initial_public_key, next_key_hash )`. KERI calls this feature [[ref: pre-rotation]]; AIDs that use it are called [[ref: transferrable]] AIDs because their control can be transferred to new keys. AIDs that do not use pre-rotation cannot change their keys, and are thus [[ref: non-transferrable]].

Pre-rotation has profound security benefits. If a malicious party steals the private key for an AID with this feature, they only accomplish _temporary_ mischief, because the already-existing KEL contains a commitment to future state. This prevents them from rotating the stolen AID's key to an arbitrary value of their choosing. As soon as the AID owner suspects a compromise, they can do a valid rotation that locks the attacker out again.

Expand Down Expand Up @@ -56,4 +56,6 @@ KERI uses [[[ref: CESR]] ](https://weboftrust.github.io/ietf-cesr/draft-ssmith-c
* JSON, CBOR, and MsgPack are all valid and equivalent ways to represent a KERI data structure. Further, JSON, CBOR, and MsgPack can be freely mixed/combined, because CESR makes each chunk of content self-describing, _and a digital signature on a CESR data structure is stable no matter which format is used_. The practical effect is that developers get the best of both worlds: they can produce and consume data structures mostly using whatever toolset they like, they can displayed and debug data structures in a human-friendly form, and they can store or transmit data in its tersest form, _all without changing the signature_.
* Cryptographic primitives such as keys, hashes, and signatures are structured strings with a recognizable data type prefix and a standard representation. This means they are very terse, and there is no need for the variety of representation methods that create interoperability challenges in other DID methods (`publicKeyJwk` versus `publicKeyMultibase` versus other; see [section 5.2 of the DID spec](https://www.w3.org/TR/did-core/#verification-material)).

Despite this rich set of features, KERI imposes only light dependencies on developers. The cryptography it uses is familiar and battle-hardened — exactly what you'd find in standard toolkits for big numbers and elliptic curves. For example, the python implementation uses just the `pysodium`, `blake3`, and `cryptography` packages. Libraries for KERI exist in javascript, rust, and python.
Despite this rich set of features, KERI imposes only light dependencies on developers. The cryptography it uses is familiar and battle-hardened — exactly what you'd find in standard toolkits for big numbers and elliptic curves. For example, the python implementation uses just the `pysodium`, `blake3`, and `cryptography` packages. Libraries for KERI exist in javascript, rust, and python.

In this spec we generically refer to the CESR event stream of KEL and TEL events as the [[ref: KERI event stream]] which is used to verify the did:webs DID document.
2 changes: 1 addition & 1 deletion spec/terminology.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
~ As defined by KERI.

[[def: KERI event stream, KERI event streams]]
~ A stream of verifiable KERI data, consisting of the [[ref: key event log]] ([[ref: KEL]]) and other data such as [[ref: transaction event log]] ([[ref: TEL]]). This data may be serialized in a file using [[ref: CESR]] encoding.
~ A stream of verifiable KERI data, consisting of the [[ref: key event log]] ([[ref: KEL]]) and other data such as [[ref: transaction event log]] ([[ref: TEL]]). This data is a [[ref: CESR]] event stream (TODO: link to IANA application/cesr media type) and may be serialized in a file using [[ref: CESR]] encoding. We refer to these CESR stream resources as KERI event streams to simplify the vocabulary.