diff --git a/README.md b/README.md index 302ebb5..e368695 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,18 @@ Proof of concept implementations available: - Python: [https://github.com/bcgov/trustdidweb-py](https://github.com/bcgov/trustdidweb-py) - Go: [https://github.com/nuts-foundation/trustdidweb-go](https://github.com/nuts-foundation/trustdidweb-go) +## Current Status of the Specification -- updated: 2024-11-29 + +The current stable version of the specification is **v0.4**. It is the landing page +of the [rendered specification](https://identity.foundation/trustdidweb/) and +has been snapshotted into the `spec-v0.4` folder in this repo. Active work is happening (in +the `spec`) folder on the next version of the specification ([rendered +here](https://identity.foundation/trustdidweb/next)). The editors will announce +when that new version is stable, assigned a version number, and becomes the next +current version of the specification. Updates in that version will included at +least changes in the pre-rotation handling, witnesses, and will include a name +change to the DID Method. + ## Abstract The `did:tdw` (Trust DID Web) method is an enhancement to the diff --git a/spec/definitions.md b/spec/definitions.md index 176bde5..16e55c5 100644 --- a/spec/definitions.md +++ b/spec/definitions.md @@ -29,7 +29,7 @@ in the [[spec:DID-CORE]]. ~ A DID Document as defined by the [[spec: DID-Core]] -- the document returned when a DID is resolved. -[[def: did:key]] +[[def: did:key, `did:key`]] ~ `DID:key`... @@ -60,7 +60,7 @@ when forced to change (such as when an organization is acquired by another, resulting in a change of domain names) and when changing DID hosting service providers. -[[def: did:web]] +[[def: did:web, `did:web`]] ~ `did:web` as described in the [W3C specification](https://w3c-ccg.github.io/did-method-web/) is a DID method that leverages the Domain Name System (DNS) to perform the DID operations. @@ -131,7 +131,7 @@ in this specification as permitted. [[def: multi-sig, multisig]] -~ A cryptographic signature that to be valid **MUST** contain a defined threshold +~ A cryptographic signature that to be valid **MUST** contain a defined [[ref: threshold]] (for example, 4 of 7) individual signatures to be considered valid. The multi-signature key reference points to a verification method that defines what keys may contribute to the signature, and under what conditions the @@ -174,6 +174,14 @@ and approves it according to its ecosystem governance (whatever that might be). approval process results are positive, witnesses returns to the DID Controller a [[ref: Data Integrity]] proof attesting to that positive result. +[[def: threshold, witness threshold]] + +~ An algorithm that defines when a sufficient number of [[ref: witnesses]] have +submitted valid [[ref: Data Integrity]] proofs for a [[ref: DID Log entry]] such +that it is approved and can be published. The algorithm details are in the +[Witness Threshold Algorithm](#witness-threshold-algorithm) section of this +specification. + [[def: W3C VCDM]] ~ A Verifiable Credential that uses the Data Model defined by the W3C [[spec: W3C-VC]] specification. diff --git a/spec/specification.md b/spec/specification.md index 6319284..aa44381 100644 --- a/spec/specification.md +++ b/spec/specification.md @@ -60,7 +60,10 @@ this specification) element in `did:tdw` that is not in `did:web`. As specified in the [DID-to-HTTPS Transformation](#the-did-to-https-transformation) section of this specification, `did:tdw` and `did:web` DIDs that have the same fully qualified domain and path transform to the same HTTPS URL, with the exception of -the final file -- `did.json` for `did:web` and `did.jsonl` for `did:tdw`. +the final file -- `did.json` for `did:web` and `did.jsonl` for `did:tdw`. For +`did:tdw` DIDs using [[ref: witnesses]], another file `did-witness.json` is also +found (logically) beside the `did.jsonl` web server file. See the +[witnesses](#did-witnesses) section of this specification for details. ### The DID to HTTPS Transformation @@ -89,9 +92,15 @@ retrieve the [[ref: DID Log]]. 6. Generate an HTTPS URL to the expected location of the [[ref: DIDDoc]] by prepending `https://`. 7. Append `/did.jsonl` to complete the URL. - 1. When this algorithm is used for resolving a DID path (such as - `/whois` or `/path/to/file as defined in the section [DID URL + 1. If the DID is using [[ref: witnesses]], an extra JSON file containing the + witness proofs for the [[ref: DID entries]] must be published and + retrieved during resolution. The URL for the extra file is defined by + replacing the `/did.jsonl` at the end of the [[ref: DID Log]] URL with + `/did-witness.json`. + 2. When this algorithm is used for resolving a DID path (such as + `/whois` or `/path/to/file` as defined in the section [DID URL Handling](#did-url-resolution)), append the DID URL path instead. +8. The content type for the `did.jsonl` file **SHOULD** be `text/jsonl`. The following are some examples of various DID-to-HTTPS transformations based on the processing steps specified above. @@ -134,7 +143,7 @@ path w/ port The location of the `did:tdw` `did.jsonl` [[ref:DID Log]] file is the same as where the comparable `did:web`'s `did.json` file is published. A [[ref: DID -Controller]] **MAY** choose to publish both DIDs and so, both files. The process +Controller]] **MAY** publish both DIDs and so, both files. The process to do so is described in the [publishing a parallel `did:web` DID](#publishing-a-parallel-didweb-did) section of this specification. @@ -168,8 +177,8 @@ Each entry is a JSON object consisting of the following properties. specification. 4. The JSON object `state` contains the [[ref: DIDDoc]] for this version of the DID. -5. The JSON array `proof` contains a [[ref: Data Integrity]] proof calculated across - the entry and signed by key authorized to update the [[ref: DIDDoc]]. +5. The JSON array `proof` contains a [[ref: Data Integrity]] proof created for + the entry and signed by a key authorized to update the [[ref: DIDDoc]]. After creation, each entry has (per the [[ref JSON Lines]] specification) all extra whitespace removed, a `\n` character appended, and the result added to @@ -179,7 +188,9 @@ A more comprehensive description of how to create and update a [[ref: DID log entry]] is given in steps 4 - 6 of the [create DID](#create-register) section. Examples of [[ref: DID Logs]] and [[ref: DID log entries]] can be found in the -[did:tdw` Examples](#didtdw-example) section of this specification. +[Examples] section on the `did:tdw` information website. + +[Examples]: https://didtdw.org/latest/example/ ### DID Method Operations @@ -276,11 +287,6 @@ Creating a `did:tdw` DID is done by carrying out the following steps. be generated using an authorized key in the required `updateKeys` property in the [[ref: parameters]] object. - If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] for the - DID, the required approvals from the DID's [[ref: witnesses]] **MUST** be - collected and added to the [[ref: Data Integrity]] proof property. See the [DID - Witnesses](#did-witnesses) section of this specification. - 6. **Add the [[ref: Data Integrity]] proof** The [[ref Data Integrity]] proof is added to the preliminary JSON object. The resultant JSON object is the initial [[ref: DID log entry]] for the DID. @@ -290,9 +296,15 @@ Creating a `did:tdw` DID is done by carrying out the following steps. entry by removing extraneous white space and appending a carriage return, and the result stored as the contents of the file `did.jsonl`. + If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] for the + DID, the required proofs from the DID's [[ref: witnesses]] **MUST** be + collected and published in the `did-witness.json` file before the [[ref: DID + Log]] with the new version is published. See the [DID + Witnesses](#did-witnesses) section of this specification. + 7. **Publish the [[ref: DID Log]]** - The complete [[ref: DID Log]] file **MUST** be published at the appropriate Web location defined by - the `did:tdw` DID identifier (see step 1) + The complete [[ref: DID Log]] file **MUST** be published at the appropriate + Web location defined by the `did:tdw` DID identifier (see step 1) - This is a logical operation -- how a deployment serves the `did.jsonl` content is not constrained. - Use the [DID-to-HTTPS Transformation](#the-did-to-https-transformation) @@ -333,26 +345,27 @@ are each a JSON object with the following properties: 2. `versionTime` 3. `parameters` 4. `state` -- the version's [[ref: DIDDoc]]. - 5. `proof` -- a [[ref: Data Integrity]] proof across the [[ref: log entry]]. + 5. `proof` -- a [[ref: Data Integrity]] proof for the [[ref: log entry]]. For each entry: -1. Update the currently active [[ref: parameters]] with the [[ref: parameters]] from - the entry (if any). Continue processing using the now active set of - [[ref: parameters]]. +1. Update the currently active [[ref: parameters]] with the [[ref: parameters]] + from the entry (if any). The `parameters` **MUST** adhere to the [`did:tdw` + DID Method Parameters](#didtdw-did-method-parameters) section of this + specification. Continue processing using the now active set of [[ref: + parameters]]. - While all [[ref: parameters]] in the first [[ref: Log Entry]] take effect - immediately, some kinds of [[ref: parameters]] defined in later [[ref: entries]] only take - effect *after* that entry has been published. For example, rotating the - authorized keys to update a DID takes effect only *after* the entry in - which they are defined has been published. + immediately, some kinds of [[ref: parameters]] defined in later [[ref: + entries]] only take effect *after* that entry has been published. For + example, updating the `nextKeys` and `witnesses` arrays take effect only + *after* the entry in which they are defined has been published. 2. The [[ref: Data Integrity]] proof in the entry **MUST** be valid and signed by an authorized key as defined in the [Authorized Keys](#authorized-keys) section of this specification. - 1. If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] and the - last entry of the log is being processed, the [[ref: witness]] [[ref: Data - Integrity]] proofs **MUST** be valid and **MUST** be signed by a threshold - of [[ref: witnesses]]. For details, see the [DID - Witnesses](#did-witnesses) section of this specification. + 1. If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] + resolvers **MUST** retrieve and verify the DID's `did-witness.json` file. For + details, see the [DID Witnesses](#did-witnesses) section of this + specification. 3. Verify the `versionId` for the entry. The `versionId` is the concatenation of the version number, a dash (`-`), and the `entryHash`. 1. The version number **MUST** be `1` for the the first [[ref: log entry]] and **MUST** be @@ -366,26 +379,19 @@ For each entry: `versionTime` for each [[ref: log entry]] **MUST** be greater than the previous entry's time. The `versionTime` of the last entry **MUST** be earlier than the current time. -5. Parse and apply the `did:tdw` DID Method configuration `parameters`. Note - that in versions after the first, some `parameters` apply to immediately and - impact the process of the current DID version, while others, such as - `updateKeys` and `witnesses` apply after the current version has been - published. The `parameters` **MUST** adhere to the [`did:tdw` DID Method - Parameters](#didtdw-did-method-parameters) section of this specification. -6. When processing the first [[ref: DID log]] entry, verify the [[ref: SCID]] +5. When processing the first [[ref: DID log]] entry, verify the [[ref: SCID]] (defined in the [[ref: parameters]]) according to the [SCID Generation and Verification](#scid-generation-and-verification) section of this specification. -7. Get the value of the [[ref: log entry]] property `state`, which is the [[ref: +6. Get the value of the [[ref: log entry]] property `state`, which is the [[ref: DIDDoc]] for the version. -8. If [[ref: Key Pre-Rotation]] is being used, the hash of all `updateKeys` entries +7. If [[ref: Key Pre-Rotation]] is being used, the hash of all `updateKeys` entries in the `parameters` property **MUST** match a hash in the array of `nextKeyHashes` [[ref: parameter]] from the previous [[ref: DID log]] entry, with exception of the first entry, as defined in the [Key [[ref: Pre-Rotation]] Hash Generation and Verification](#pre-rotation-key-hash-generation-and-verification) section of this specification. -9. If any verifications fail, discard the DID as invalid with an error message. -10. As each [[ref: log entry]] is processed and verified, collect the following information +8. As each [[ref: log entry]] is processed and verified, collect the following information about each version: 1. The [[ref: DIDDoc]]. 2. The `versionId` of the [[ref: DIDDoc]]. @@ -398,6 +404,12 @@ For each entry: `nextKeyHashes` list in the [[ref: parameters]]. 6. All other `did:tdw` processing configuration settings as defined by in the `parameters` object. +9. If the `parameters` for any of the versions define that some or all of + the [[ref: DID Log entries]] must be witnessed, further verification of + the [[ref: witness]] proofs must be carried out, as defined in the [DID + Witnesses](#did-witnesses) section of this specification. +10. If any of the DID verifications outlined in this process fail, discard the + DID as invalid with an error message. On completing the processing and successful verification of all [[ref: entries]] in the [[ref: DID Log]], respond to the DID resolution request, including the @@ -476,13 +488,15 @@ verifiable [[ref: DID Log Entry]] follows a similar process to the the array of `nextKeyHashes` [[ref: parameter]] from the previous [[ref: DID log]] entry with exception of the first entry, as defined in the [Key [[ref: Pre-Rotation]] Hash Generation and Verification](#pre-rotation-key-hash-generation-and-verification) section of this specification. -8. If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] for the - DID, collect the required approvals from the DID's [[ref: witnesses]], adding - their proofs to the [[ref: data integrity]] proof. See the [DID - Witnesses](#did-witnesses) section of this specification. -9. The proof JSON object **MUST** be added as the value of the `proof` property in the [[ref: log entry]]. -10. The entry **MUST** be made a [[ref JSON Line]] by removing extra whitespace, adding a `\n` +8. The proof JSON object **MUST** be added as the value of the `proof` property in the [[ref: log entry]]. +9. The entry **MUST** be made a [[ref JSON Line]] by removing extra whitespace, adding a `\n` to the entry. +10. If the [[ref: DID Controller]] has opted to use [[ref: witnesses]] for the + DID, the [[ref: DID Controller]] **MUST** collect the [[ref: threshold]] of proofs + from the DID's [[ref: witnesses]], and update and publish the DID's + `did-witness.json` file. The updated `did-witness.json` file **MUST** be published + **BEFORE** the updated [[ref: DID Log]] file is published. See the [DID + Witnesses](#did-witnesses) section of this specification. 11. The new [[ref: log entry]] **MUST** be appended to the existing contents of the [[ref: DID Log]] file `did.jsonl`. 12. The updated [[ref: DID Log]] file **MUST** be published the appropriate @@ -505,7 +519,7 @@ further indicate the deactivation of the DID, such as including an empty further versions of the DID. A resolver encountering in the [[ref: DID log entry]] [[ref: parameters]] the -property key:value pair `"deactivated": true` **MUST** return in the [[ref: DIDDoc]] Metadata the property key:value +property key:value pair `"deactivated": true` **MUST** return in the [[ref: DIDDoc]] Metadata the property key:value `"deactivated": true`, as per the [[spec:DID-RESOLUTION]] specification. ### DID Method Processes @@ -607,10 +621,11 @@ properties are defined below. collaboration with [[ref: witnesses]] prior to publication. For details of this data and its usage in the approvals process, see the [DID Witnesses](#did-witnesses) section of this specification. - - A `witness` property in the first [[ref: DID log entry]] is used to define the - [[ref: witnesses]] and necessary threshold for that initial [[ref: log entry]]. In all other - [[ref: DID log entries]], a `witness` property becomes active **after** the publication - of its entry -- meaning its [[ref: log entry]] **MUST** be witnessed by the most recent + - A `witness` property in the first [[ref: DID log entry]] is immediately + "active" and used to define the [[ref: witnesses]] and necessary [[ref: threshold]] + for witnessing the initial [[ref: log entry]]. In all other [[ref: DID log entries]], + a `witness` property becomes active **after** the publication of its entry + -- meaning its [[ref: log entry]] **MUST** be witnessed by active `witnesses` from a **prior** [[ref: DID log]] entry. - `deactivated`: A JSON boolean that **SHOULD** be set to `true` when the DID is to be deactivated. See the [deactivate (revoke)](#deactivate-revoke) section of @@ -881,109 +896,176 @@ When processing other than the first [[ref: DID log entry]] where #### DID Witnesses -The [[ref: witness]] process for a DID provides a way for other collaborators to -work with the [[ref: DID Controller]] to "witness" the publication of a new version of -the DID. Including [[ref: witnesses]] can prevent malicious updates to the DID by both -the [[ref: DID Controller]] and external parties. This specification defines -the mechanism for using [[ref: witnesses]] but leaves the governance and policy -questions about when and how to use the mechanism to implementers. - -Witnesses can prevent a [[ref: DID Controller]] from updating/removing DID versions of a -DID without detection. [[ref: Witnesses]] are also a further mitigation against malicious -actors compromising both a [[ref: DID Controller]]'s authorization key(s) to update the -DID, and the [[ref: DID Controller]]'s web site where the [[ref: DID log]] is published. -With both compromises, a malicious actor could take control over the DID by -rewriting the [[ref: DID Log]] using the keys they have comprised. By adding -[[ref: witnesses]] that monitor and approve each version update, a malicious -actor cannot rewrite the previous history without also compromising a sufficient -number of [[ref: witnesses]]. - -An overview of the [[ref: witness]] mechanism is as follows: - -- The [[ref: DID Controller]] specifies (in the `parameters` of a [[ref: log - entry]]) a list of [[ref: witnesses]], DIDs that together with the [[ref: DID - Controller]] will contribute to "approving" all subsequent versions of the - DID. - - Ideally, the [[ref: DID Controller]] does that in the inception event for the - DID. - - Over time, the list of [[ref: witnesses]] may evolve, with each change being - approved by the declared list of [[ref: witnesses]] from **before** such a - change. -- The [[ref: DID Controller]] prepares a [[ref: DID Log Entry]] and shares it with - the [[ref: witnesses]]. - - The specification leaves to implementers *how* the [[ref: log entry]] data is provided to the [[ref: witnesses]]. -- Each [[ref: witness]] verifies the [[ref: DID Log Entry]], as defined by this - specification. If not, the [[ref: witnesses]] **MUST NOT** approve the [[ref: log entry]]. - - The [[ref: witnesses]] ***MUST** have their own copy of the current [[ref: - DID Log]]. -- Each [[ref: witness]] determines (based on the governance of the ecosystem) - if they approve of the DID version update. - - This specification has no opinion on what "approve" means for any - deployment of `did:tdw`. That is up to the ecosystem in which the [[ref: DID - Controller]] and [[ref: witnesses]] are participating. -- If the verification is successful and the approval granted, the [[ref: - witness]] sends a [[ref: Data Integrity]] proof across the [[ref: DID log entry]] to the [[ref: DID Controller]], similar - to that generated by the [[ref: DID Controller]], but signed by the [[ref: witness]]'s key. -- When a weighted threshold of proofs are received, the DID Controller - inserts the [[ref: witnesses]]'s proofs into the `proof` array in - the [[ref: DID Log Entry]] and publishes the updated version of the [[ref: DID - Log]]. - - In publishing a new version of the [[ref: DID Log]], the [[ref: DID - Controller]] **SHOULD** remove the [[ref: witness]] [[ref: Data Integrity]] proofs from - earlier [[ref: entries]] to reduce the size of the log. Only the set of approval - proofs on the last [[ref: log entry]] are needed because of the chaining of the - proofs via the use of the `entryHash` challenge. - - Removing the prior entry [[ref: witness]] proofs does not affect the verifiability of - the DID because the `entryHash` calculation does not include the `proof` property. - - The specification leaves to implementers how the proofs are conveyed to - the [[ref: DID Controller]]. - -As with the handling of the `updateKeys`, [[ref: DID Log Entry]] changes require -proofs from the the [[ref: witnesses]] active *prior* to the publication of a -new version. If a new version changes the list of [[ref: witnesses]], that -change must be approved by the *prior* [[ref: witnesses]]. For the first entry -in the [[ref: DID Log]], the [[ref: witnesses]] listed in that entry must -approve the version, since there are no "prior" [[ref: witnesses]]. - -The data model for the `witness` [[ref: parameter]] is as follows. -The threshold design borrows from the [[ref: verifiable conditions]] -specification. +The [[ref: witness]] process for a DID provides a way for collaborators to work +with the [[ref: DID Controller]] to "witness" the publication of new versions of +the DID. This specification defines the technical mechanism for using [[ref: +witnesses]]. Governance and policy questions about when and how to use the +technical mechanism are outside the scope of this specification. + +Witnesses can prevent a [[ref: DID Controller]] from updating/removing +versions of a DID without detection by the witnesses. [[ref: Witnesses]] are +also a further mitigation against malicious actors compromising both a [[ref: +DID Controller]]'s authorization key(s) to update the DID, and the [[ref: DID +Controller]]'s web site where the [[ref: DID log]] is published. With both +compromises, a malicious actor could take control over the DID by rewriting the +[[ref: DID Log]] using the keys they have compromised. By adding [[ref: +witnesses]] to monitor and approve each version update, a malicious actor cannot +rewrite the previous history without having compromised a sufficient number of +[[ref: witnesses]], the [[ref: DID Controller]]'s key(s), and the Web Server on +which the [[ref: DID Log]] is published. + +##### Witness Lists + +The list of DIDs that witness DID updates are defined in the `witness` +parameter, as described in the [Parameters](#didtdw-did-method-parameters) +section of this specification. Once the first `witness` parameter has been added +to a version, there is always an active list of witnesses, and a [[ref: threshold]] of +the active witnesses must provide verified proofs about an update before the +update can be published. If a DID version contains a new (replacement) list +of witnesses (by including a new `witness` [[ref: parameter]]) that new list +becomes active **AFTER** the new version is published. + +##### Witness DIDs and Reputation + +`did:tdw` witness DIDs **MUST** be `did:key` DIDs. + +If there is a need in an ecosystem to identify who the witnesses are, a +mechanism should be defined by the governance of the ecosystem, such as the +entry of the DID in a [[ref: Trust Registry]]. Such mechanisms are outside the +scope of this specification. + +##### The `witness` Parameter + +The `witness` element in a [[ref: parameters]] object of a [[ref: DID Log +entry]] has the following data structure: ```json + "witness" : { "threshold": n, - "selfWeight": n, "witnesses" : [ { - "id": "", + "id": "", "weight": n } ] } + ``` where: -- `threshold`: an integer that must be attained or surpassed by the sum of the [[ref: witnesses]] and - [[ref: DID Controller]]'s weights for a [[ref: DID log entry]] to be considered approved. -- `selfWeight`: an integer that is the weight given the [[ref: DID Controller]]'s - verified proof, in determining if the threshold has been surpassed. -- `witnesses`: an array of witnesses, each including the required fields: - - `id`: the DID of the witness - - `weight`: the weight of this [[ref: witness]]'s approval - -The use of the threshold and weighted approvals (versus needing approvals from -all [[ref: witnesses]]) is to prevent faulty [[ref: witnesses]] from blocking the publishing of -a new version of the DID. To determine if the threshold has been passed, sum the -`weight` integer of the received approvals, plus the `selfWeight` of the [[ref: DID -Controller]], and if it equal to or more than `threshold`, the update can be -published. The calculation **MUST** also be executed by resolvers processing a -DID Log. For example, if there are three [[ref: witnesses]], each with a `weight` of 1, -the [[ref: DID Controller]] with a `selfWeight` of 2, and a `threshold` of 4, the -threshold will be met by two [[ref: witnesses]] approving the change, plus the [[ref: DID -Controller]]. +- threshold: an integer that must be attained or surpassed by the sum of the witnesses weights for a DID log entry to be considered approved. +- witnesses: an array of witnesses, each including the required fields: + - id: the DID of the witness. The DID **MUST** be a `did:key` DID. + - weight: an integer that is the weight given to this witness's approval + +##### Witness Threshold Algorithm -If you want to learn about the practical application of witnesses, see the +The use of the [[ref: threshold]] and weighted approvals (versus needing +approvals from all [[ref: witnesses]]) is to prevent faulty [[ref: witnesses]] +from blocking the publishing of a new version of the DID. To determine if the +[[ref: threshold]] has been met, sum the `weight` integer of the received +approvals and if it equal to or more than the `threshold`, the update can be +published. The calculation **MUST** be executed by resolvers processing a +[[ref: DID Log]]. + +For example, if there are three [[ref: witnesses]] with a `weight` of `1`, a +fourth with a weight of `2`, and a `threshold` of `3`, the [[ref: threshold]] is met +by either the fourth plus any one of the other [[ref: witnesses]] (`2+1`), or +all of the first three witness (`1+1+1`) providing an approving `proof`. + +##### The Witness Proofs File + +Proofs from witnesses are retained in a separate file (`did-witness.json`) from the +[[ref: DID Log]]. The same [DID to HTTPS +Transformation](#the-did-to-https-transformation) used for the [[ref: DID Log]] +is used to locate the `did-witness.json` resource, with only the last element +changed (`did.jsonl` to `did-witness.json`). The media type of the file **SHOULD** be +`text/json`. + +The data model for the `did-witness.json` file is: + +```json +{ + [ + { + "versionId": "1-QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ", + "witness": "did:key:z82LkvR3CBNkb...", + "proof": { ... } + }, + ... + ] +} +``` + +Where: + +- `versionId` is the `versionId` of the [[ref: DID log entry]] to which the proof applies. +- `witness` is the DID of the witness. +- `proof` is the proof of the [[ref: DID Log Entry]] (excluding the `proof` item) identified by the `versionId`. + +To limit the size of the file, only the two most recent proofs from each [[ref: witness]] are retained in the +`did-witness.json` file. When a new, verified proof from a [[ref: witness]] is received, +the [[ref: DID Controller]] adds it to the file. If two other proofs from that +[[ref: witness]] are found in the file, the oldest **SHOULD** be removed. The presence of a valid +proof is an attestation from a [[ref: witness]] that the current **and all prior** versions +of the DID have been verified and approved by that witness. + +##### Witnessing a DID Version Update + +The following process is used to witness a DID version update: + +- The [[ref: DID Controller]] prepares the full [[ref: DID Log Entry]] (including the + `proof` element) for the new version of the DID, and shares it with the active [[ref: witnesses]]. + - The specification leaves to implementers *how* the [[ref: log entry]] data is provided to the [[ref: witnesses]]. +- The [[ref: witnesses]] ***MUST** hold their own copy of the published [[ref: + DID Log]] prior to the version being witnessed. +- Each [[ref: witness]] verifies the [[ref: DID Log Entry]], as defined by this + specification. If not verified, the [[ref: witnesses]] **MUST NOT** approve the [[ref: log entry]]. +- Each [[ref: witness]] determines (based on the governance of the ecosystem) + if they approve of the DID version update. + - The meaning of "approve" for any given implementation is outside the scope of this specification. +- If the verification is successful and approval granted, the [[ref: witness]] + creates and sends a [[ref: Data Integrity]] proof for the [[ref: DID log entry]] (minus + the DID Controller `proof`) to the [[ref: DID Controller]], signed by the [[ref: witness]]'s key. + - The proof generation process of the witness **MUST** match the one used by + the DID Controller in generating its proof for the [[ref: DID log entry]], + as defined in the [Authorized Keys](#authorized-keys) section of this + specification. +- The DID Controller updates the [[ref: witnesses]]'s proofs in the + `did-witness.json` file with the received proofs, and publishes the updated file. + - The specification leaves to implementers how [[ref: witness]] proofs are + conveyed to the [[ref: DID Controller]]. + - The [[ref: DID Controller]] **MAY** publish the updated `did-witness.json` file + as new witness proofs are added to the file. + - The [[ref: DID Controller]] **MUST** publish the updated `did-witness.json` file + **after** a [[ref: threshold]] of witness proofs have been received and **before** the + witnessed [[ref: DID Log]] file is published. + +##### Verifying Witness Proofs During Resolution + +A `did:tdw` resolver **MUST** verify that all [[ref: DID Log entries]] that have +active [[ref: witnesses]] have a [[ref: threshold]] of active witnesses approving the [[ref: log entry]]. +To do so, resolvers must: + +- Successfully complete the non-[[ref: witness]] verifications of the [[ref: DID Log]]. +- Verify the [[ref: witness]] proofs in the `did-witness.json` file. + - Ignore any witness proofs that do not verify. For example, a `did-witness.json` file + **MAY** contain proofs of pending (unpublished) [[ref: DID Log entries]]. + Such proofs **MUST** be ignored by resolvers. +- For each [[ref: DID log entry]] requiring witnessing, the resolver **MUST** + confirm that the `did-witness.json` file contains verified [[ref: witness]] + [[ref: Data Integrity]] proofs from a [[ref: threshold]] of active [[ref: + witnesses]] for the current or any **later** log entry. If not, terminate the + resolution process with an error. + - As noted in the section on the [Witness proofs + file](#the-witness-proofs-file), no more than two proofs from any [[ref: witness]] + are retained in the file. A valid proof from a [[ref: witness]] on a given entry + implies the [[ref: witness]]'s "approval" of **all** prior [[ref: DID log + entries]]. + +If you want to learn more about the practical application of witnesses, see the Implementer's Guide section on [Witnesses](https://didtdw.org/latest/implementers_guide/#witnesses) on the `did:tdw` information site for more discussion on the witness capability and diff --git a/spec/version.md b/spec/version.md index d4bed51..3147c6c 100644 --- a/spec/version.md +++ b/spec/version.md @@ -4,7 +4,12 @@ The following lists the substantive changes in each version of the specification - Version 0.5 - Remove the `prerotation` parameter. The feature is automatically enforced when `nextKeyHashes` is present. - - Clarify the way the [[ref: Pre-Rotation]] feature works, once a `nextKeyHashes` is commited, the next [[ref: DID log entries]] has to be signed by one of the commited keys. + - Clarify the way the [[ref: Pre-Rotation]] feature works, once a `nextKeyHashes` is committed, the next [[ref: DID log entries]] has to be signed by one of the committed keys. + - Changes the [[ref: witness]] handling by removing the witness [[ref: Data + Integrity]] proofs from the [[ref: DID Log]] file and into a separate file + `did-witness.json`. Adjustments to the witness threshold algorithm were also + made, such as removing the [[ref: DID Controllers]]' `selfweight` attribute, + and defining that all witness DIDs must be `did:key` DIDs. - Version 0.4 - Removes large non-normative sections, such as the implementer's guide, as they are now published on the [https://didtdw.org/](https://didtdw.org/) information site. - Removes the use of JSON Patch from the specification. The full DIDDoc is included in each [[ref: DID log entry]].