diff --git a/spec/abstract.md b/spec/abstract.md index 45d05fb..6327789 100644 --- a/spec/abstract.md +++ b/spec/abstract.md @@ -27,18 +27,17 @@ limitations. `did:tdw` features include: resolving `/path/to/file` by using a comparable DID-to-HTTPS translation as for the [[ref: DIDDoc]]. - A DID URL path `/whois` that defaults to automatically returning (if - published by the [[ref: DID controller]]) a [[ref: Verifiable Presentation]] containing - [[ref: Verifiable Credentials]] with the DID as the `credentialSubject`, - signed by the DID. + published by the [[ref: DID controller]]) a [[ref: Verifiable Presentation]] + containing [[ref: Verifiable Credentials]] with the DID as the + `credentialSubject`, signed by the DID. It draws inspiration from the + traditional WHOIS protocol [[spec:rfc3912]], offering an easy-to-use, + decentralized, trust registry. [High Assurance DIDs with DNS]: https://datatracker.ietf.org/doc/draft-carter-high-assurance-dids-with-dns/ Combined, the additional features enable greater trust and security without compromising the simplicity of `did:web`. -The incorporation of the DID Core compatible "/whois" path, drawing inspiration -from the traditional WHOIS protocol [[spec:rfc3912]], offers an easy-to-use, -decentralized, trust registry. The `did:tdw` method aims to establish a more -trusted and secure web environment by providing robust verification processes -and enabling transparency and authenticity in the management of decentralized -digital identities. +For more information about the Trust DID Web (`did:tdw`) DID method and how (and +where) it is used in practice, please visit +[https://didtdw.org/](https://didtdw.org/) diff --git a/spec/definitions.md b/spec/definitions.md index 5b78c6e..3c81c87 100644 --- a/spec/definitions.md +++ b/spec/definitions.md @@ -13,18 +13,23 @@ is a specification of mechanisms for ensuring the authenticity and integrity of structured digital documents using cryptography, such as digital signatures and other digital mathematical proofs. -[[def: Decentralized Identifier, Decentralized Identifiers]] +[[def: Decentralized Identifier, Decentralized Identifiers, DID, DIDs]] ~ Decentralized Identifiers (DIDs) [[spec:did-core]] are a type of identifier that enable verifiable, decentralized digital identities. A DID refers to any subject (e.g., a person, organization, thing, data model, abstract entity, etc.) as determined by the controller of the DID. +[[def: DID Controller, DID Controllers]] + +~ The entity that controls (create, updates, deletes) a given DID, as defined +in the [[spec:DID-CORE]]. + [[def: DIDDoc]] ~ 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`... @@ -33,7 +38,7 @@ by the controller of the DID. ~ A DID Log is a list of [[ref: Entries]], with an entry added for each update of the DID, including new versions of the [[ref: DIDDoc]] or changed information necessary to generate or validate the DID. -[[def: DID Log Entry, DID Log Entries, Entries, Log Entries]] +[[def: DID Log Entry, DID Log Entries, Entries, Log Entries, Log Entry]] ~ A DID Log Entry is a JSON object that defines the authorized transformation of a [[ref: DIDDoc]] from one version to the next. The initial entry @@ -47,7 +52,7 @@ associated DID document are created, resolved, updated, and deactivated. DID methods are defined using separate DID method specifications. This document is the DID Method Specification for `DID:tdw`. -[[def: DID Portability, DID:tdw portability, `DID:tdw` portability]] +[[def: DID Portability, DID:tdw portability, `DID:tdw` portability, portability]] ~ `did:tdw` portability is the capability to change the DID string for the DID while retaining the [[ref: SCID]] and the history of the DID. This is useful @@ -73,7 +78,7 @@ the secured document. More information on further operations and applications of the cryptosuite can be found in the specification, here: [eddsa-jcs-2022](https://www.w3.org/TR/vc-di-eddsa/#eddsa-jcs-2022) -[[def: Entry Hash, entryHash]] +[[def: Entry Hash, entryHash, entry hashes]] ~ A `DID:tdw` entry hash is a hash generated using a formally defined process over the input data to a [[ref: log entry]], excluding the [[ref: Data Integrity]] @@ -93,14 +98,14 @@ Standard](https://en.wikipedia.org/wiki/ISO_8601). ~ [[spec:rfc8785]] defines a method for canonicalizing a JSON structure such that is suitable for verifiable hashing or signing. -[[def: JSON Lines]] +[[def: JSON Lines, JSON Line]] ~ A file of JSON Lines, as described on the site [https://jsonlines.org/](https://jsonlines.org/). In short, `JSONL` is lines of JSON with whitespace removed and separated by a newline that is convenient for handling streaming JSON data or log files. -[[def: Pre-Rotation]] +[[def: Pre-Rotation, Key Pre-Rotation]] ~ A technique for a controller of a cryptographic key to commit to the public key it will rotate to next, without exposing that actual public key. It protects @@ -132,7 +137,7 @@ multi-signature key reference points to a verification method that defines what keys may contribute to the signature, and under what conditions the multi-signature is considered valid. -[[def: parameters]] +[[def: parameters, parameter]] ~ `did:tdw` parameters are a defined set of configurations that control how the issuer has generated the DID, and how the resolver must process the DID [[ref: @@ -140,7 +145,7 @@ Log entries]]. The use of parameters allows for the controlled evolution of `did:tdw` log handling, such as evolving the set of permitted hash algorithms or cryptosuites. This enables support for very long lasting identifiers -- decades. -[[def: self-certifying identifier, SCID, SCIDs]] +[[def: self-certifying identifier, self-certifying identifiers, SCID, SCIDs]] ~ An object identifier derived from initial data such that an attacker could not create a new object with the same identifier. The input for a `DID:tdw` SCID is diff --git a/spec/example.md b/spec/example.md deleted file mode 100644 index 4bf9b56..0000000 --- a/spec/example.md +++ /dev/null @@ -1,314 +0,0 @@ -## `did:tdw` Example - -The following shows the evolution of a `did:tdw` from inception through several -versions, showing the DID, [[ref: DIDDoc]], [[ref: DID Log]], and some of the -intermediate data structures. - -**The examples are aligned with version 0.4 of the `did:tdw` specification.** - -In some of the following examples the data for the [[ref: DID log entries]] is -displayed as prettified JSON for readability. In the log itself, the JSON has -all whitespace removed, and each line ends with a `CR`, per the [[ref: JSON -Lines]] convention. - -### DID Creation Data - -These examples show the important structures used in the [Create (Register)](#create-register) operation for a `did:tdw` DID. - -#### Input to the SCID Generation Process with Placeholders - -The following JSON is an example of the input that the [[ref: DID Controller]] -constructs and passes into the -[SCID Generation Process](#scid-generation-and-verification). In this example, the [[ref: DIDDoc]] is -particularly boring, containing the absolute minimum for a valid [[ref: DIDDoc]]. - -This example includes both the initial "authorized keys" to sign the [[ref: Data Integrity]] proof -(`updateKeys`) and the [[ref: pre-rotation]] commitment to the next authorization keys (`nextKeyHashes`). Both -are in the `parameters` property in the [[ref: log entry]]. - -```json -{ - "versionId": "{SCID}", - "versionTime": "2024-09-26T23:22:26Z", - "parameters": { - "prerotation": true, - "updateKeys": [ - "z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R" - ], - "nextKeyHashes": [ - "QmXC3vvStVVzCBHRHGUsksGxn6BNmkdETXJGDBXwNSTL33" - ], - "method": "did:tdw:0.4", - "scid": "{SCID}" - }, - "state": { - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - "id": "did:tdw:{SCID}:domain.example" - } -} -``` - -#### Output of the SCID Generation Process - -After the [[ref: SCID]] is generated, the literal `{SCID}` placeholders are -replaced by the generated [[ref: SCID]] value (see below). This JSON is the -input to the [`entryHash` generation -process](#entry-hash-generation-and-verification) -- with the [[ref: SCID]] -`versionId``. Once the process has run, the version number of this first version -of the DID (`1`), a dash `-` and the resulting output hash replace the [[ref: -SCID]] as the `versionId` value. - -```json -{ - "versionId": "QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ", - "versionTime": "2024-09-26T23:22:26Z", - "parameters": { - "prerotation": true, - "updateKeys": [ - "z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R" - ], - "nextKeyHashes": [ - "QmXC3vvStVVzCBHRHGUsksGxn6BNmkdETXJGDBXwNSTL33" - ], - "method": "did:tdw:0.4", - "scid": "QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ" - }, - "state": { - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example" - } -} -``` - -#### Data Integrity Proof Generation and First Log Entry - -The last step in the creation of the first [[ref: log entry]] is the generation -of the [[ref: data integrity]] proof. One of the keys in the `updateKeys` [[ref: -parameter]] **MUST** be the `verificationMethod` in the proof (in `did:key` -form) to generate the signature across the post-[[ref: entryHash]] processed -[[ref: DID log entry]]. The generated proof is added to the [[ref: JSON Line]] -and the [[ref: log entry]] JSON object becomes the first entry in the [[ref: -DID Log]]. - -The following is the JSON prettified version of the entry log file that is -published as the initial `did.jsonl` file. When published, all extraneous -whitespace is removed, as shown in the block below the pretty-printed version. - -```json -{ - "versionId": "1-QmQq6Kg4ZZ1p49znzxnWmes4LkkWgMWLrnrfPre8UD56bz", - "versionTime": "2024-09-26T23:22:26Z", - "parameters": { - "prerotation": true, - "updateKeys": [ - "z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R" - ], - "nextKeyHashes": [ - "QmXC3vvStVVzCBHRHGUsksGxn6BNmkdETXJGDBXwNSTL33" - ], - "method": "did:tdw:0.4", - "scid": "QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ" - }, - "state": { - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example" - }, - "proof": [ - { - "type": "DataIntegrityProof", - "cryptosuite": "eddsa-jcs-2022", - "verificationMethod": "did:key:z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R#z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R", - "created": "2024-09-26T23:22:26Z", - "proofPurpose": "authentication", - "proofValue": "z2fPF6fMewtV15kji2N432R7RjmmFs8p7MiSHSTM9FoVmJPtc3JUuZ472pZKoWgZDuT75EDwkGmZbK8ZKVF55pXvx" - } - ] -} -``` - -The same content "un-prettified", as it is found in the `did.jsonl` file: - -```json -{"versionId": "1-QmQq6Kg4ZZ1p49znzxnWmes4LkkWgMWLrnrfPre8UD56bz", "versionTime": "2024-09-26T23:22:26Z", "parameters": {"prerotation": true, "updateKeys": ["z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R"], "nextKeyHashes": ["QmXC3vvStVVzCBHRHGUsksGxn6BNmkdETXJGDBXwNSTL33"], "method": "did:tdw:0.4", "scid": "QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ"}, "state": {"@context": ["https://www.w3.org/ns/did/v1"], "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example"}, "proof": [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R#z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R", "created": "2024-09-26T23:22:26Z", "proofPurpose": "authentication", "proofValue": "z2fPF6fMewtV15kji2N432R7RjmmFs8p7MiSHSTM9FoVmJPtc3JUuZ472pZKoWgZDuT75EDwkGmZbK8ZKVF55pXvx"}]} -``` - -#### `did:web` Version of DIDDoc - -As noted in the [publishing a parallel `did:web` -DID](#publishing-a-parallel-didweb-did) section of this specification a `did:tdw` can be published -by replacing `did:tdw` with `did:web` in the [[ref: DIDDoc]], adding an `alsoKnownAs` entry for the `did:tdw` -and publishing the resulting [[ref: DIDDoc]] at `did.json`, logically beside the `did.jsonl` file. - -Here is what the `did:web` [[ref: DIDDoc]] looks like for the `did:tdw` above. - -```json -{ - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - "id": "did:web:domain.example", - "alsoKnownAs": ["did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example"] -} -``` - -### Version 2 of the DIDDoc - -Time passes, and the [[ref: DID Controller]] of the `did:tdw` DID decides to -update its DID to a new version, version 2. In this case, the only change -the [[ref: DID Controller]] makes is transition the authorization key to -the [[ref: pre-rotation]] key. - -#### Version 2 Entry Hashing Input - -To generate a new version of the DID, the [[ref: DID Controller]] needs to -provide the updated `parameters`, and the new [[ref: DIDDoc]]. The following -processing is done to create the new [[ref: DID log entry]]: - -- The `versionId` from the previous (first) [[ref: log entry]] is made the value - of the `versionId` in the new [[ref: log entry]]. -- The `versionTime` in the new [[ref: log entry]] is set to the current time. -- The `parameters` entry passed in is processed. In this case, since the -`updateKeys` array is updated, and [[ref: pre-rotation]] is active, the a -verification is done to ensure that the hash of the `updateKeys` entries are -found in the `nextKeyHashes` property from version 1 of the DID. As required by the -`did:tdw` specification, a new `nextKeyHashes` is included in the new `parameters`. -- The new (but unchanged) [[ref: DIDDoc]] is included in its entirety, as the value of the `state` property. -- The resultant JSON object is passed into the [`entryHash` generation - process](#entry-hash-generation-and-verification) which outputs the - `entryHash` for this [[ref: log entry]]. Once again, the `versionId` value is - replaced by the version number (the previous version number plus `1`, so `2` - in this case), a dash (`-`), and the new `entryHash`. -- The [[ref: data integrity]] proof is generated added to the [[ref: log - entry]], spaces are removed, a `CR` character added (per [[ref: JSON Lines]]) - and the entire entry is appended to the existing [[ref: DID log]] file. - -The [[ref: DID log]] file can now be published, optionally with an updated version of the corresponding `did:web` DID. - -The following is the JSON pretty-print [[ref: log entry]] for the second version of an example `did:tdw`. Things to note in this example: - -- The [[ref: data integrity]] proof `verificationMethod` is the `did:key` from - the first [[ref: log entry]], since the `updateKeys` change in the second - [[ref: log entry]] does not take affect until _after_ the version update is - complete. -- A new `updateKeys` property in the `parameters` has been added, along with - commitment to a future key (`nextKeyHashes`) that will control future updates - to the DID. - -```json -{ - "versionId": "2-QmXL6CLK1BMHAd3zQMqkY49VSc9T3zhUcPxu6zEW176PfN", - "versionTime": "2024-09-26T23:22:26Z", - "parameters": { - "updateKeys": [ - "z6MkvQnUuQn3s52dw4FF3T87sfaTvXRW7owE1QMvFwpag2Bf" - ], - "nextKeyHashes": [ - "QmdA9fxQSLLwCQo6TkovcoaLgGYWq6Ttqx6A5D1RY13iFG" - ] - }, - "state": { - "@context": [ - "https://www.w3.org/ns/did/v1" - ], - "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example" - }, - "proof": [ - { - "type": "DataIntegrityProof", - "cryptosuite": "eddsa-jcs-2022", - "verificationMethod": "did:key:z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R#z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R", - "created": "2024-09-26T23:22:26Z", - "proofPurpose": "authentication", - "proofValue": "z2nkLj9rYAMG7TStpvihuo4HTovpC7uvWcDoYiGhoN8cqQuiwW2EnPZdWtid2FZAQDQPoaNkTooKVftGKDTh9p3Fy" - } - ] -} -``` - -#### Log File For Version 2 - -The new version 2 `did.jsonl` file contains two [[ref: entries]], one for each version -of the [[ref: DIDDoc]] -- as per the use of [[ref: JSON Lines]]. - -```json -{"versionId": "1-QmQq6Kg4ZZ1p49znzxnWmes4LkkWgMWLrnrfPre8UD56bz", "versionTime": "2024-09-26T23:22:26Z", "parameters": {"prerotation": true, "updateKeys": ["z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R"], "nextKeyHashes": ["QmXC3vvStVVzCBHRHGUsksGxn6BNmkdETXJGDBXwNSTL33"], "method": "did:tdw:0.4", "scid": "QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ"}, "state": {"@context": ["https://www.w3.org/ns/did/v1"], "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example"}, "proof": [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R#z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R", "created": "2024-09-26T23:22:26Z", "proofPurpose": "authentication", "proofValue": "z2fPF6fMewtV15kji2N432R7RjmmFs8p7MiSHSTM9FoVmJPtc3JUuZ472pZKoWgZDuT75EDwkGmZbK8ZKVF55pXvx"}]} -{"versionId": "2-QmXL6CLK1BMHAd3zQMqkY49VSc9T3zhUcPxu6zEW176PfN", "versionTime": "2024-09-26T23:22:26Z", "parameters": {"updateKeys": ["z6MkvQnUuQn3s52dw4FF3T87sfaTvXRW7owE1QMvFwpag2Bf"], "nextKeyHashes": ["QmdA9fxQSLLwCQo6TkovcoaLgGYWq6Ttqx6A5D1RY13iFG"]}, "state": {"@context": ["https://www.w3.org/ns/did/v1"], "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example"}, "proof": [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R#z6MkhbNRN2Q9BaY9TvTc2K3izkhfVwgHiXL7VWZnTqxEvc3R", "created": "2024-09-26T23:22:26Z", "proofPurpose": "authentication", "proofValue": "z2nkLj9rYAMG7TStpvihuo4HTovpC7uvWcDoYiGhoN8cqQuiwW2EnPZdWtid2FZAQDQPoaNkTooKVftGKDTh9p3Fy"}]} -``` - -#### Log File For Version 3 - -The same process is repeated for version 3 of the DID. In this case: - -- The [[ref: DIDDoc]] is changed. - - an `authentication` method is added. - - two services are added. -- No changes are made to the authorized keys to update the DID. As a result, the `parameters` entry is empty (`{}`), and the [[ref: parameters]] in effect from previous versions of the DID remain in effect. - -Here is the pretty-printed [[ref: log entry]]: - -```json -{ - "versionId": "3-QmaSKJRACGefmi19LkS6TFj5FeMEfr98GpBWk7vEmbhT92", - "versionTime": "2024-09-26T23:22:26Z", - "parameters": {}, - "state": { - "@context": [ - "https://www.w3.org/ns/did/v1", - "https://w3id.org/security/multikey/v1", - "https://identity.foundation/.well-known/did-configuration/v1", - "https://identity.foundation/linked-vp/contexts/v1" - ], - "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example", - "authentication": [ - "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#z6MkrgET7ZLV32qNrr6vUd2kVXGw63vbPvqxDqqhRQpvngBX" - ], - "assertionMethod": [ - "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#z6MkrgET7ZLV32qNrr6vUd2kVXGw63vbPvqxDqqhRQpvngBX" - ], - "verificationMethod": [ - { - "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#z6MkrgET7ZLV32qNrr6vUd2kVXGw63vbPvqxDqqhRQpvngBX", - "controller": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example", - "type": "Multikey", - "publicKeyMultibase": "z6MkrgET7ZLV32qNrr6vUd2kVXGw63vbPvqxDqqhRQpvngBX" - } - ], - "service": [ - { - "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#domain", - "type": "LinkedDomains", - "serviceEndpoint": "https://domain.example" - }, - { - "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#whois", - "type": "LinkedVerifiablePresentation", - "serviceEndpoint": "https://domain.example/.well-known/whois.vc" - } - ] - }, - "proof": [ - { - "type": "DataIntegrityProof", - "cryptosuite": "eddsa-jcs-2022", - "verificationMethod": "did:key:z6MkvQnUuQn3s52dw4FF3T87sfaTvXRW7owE1QMvFwpag2Bf#z6MkvQnUuQn3s52dw4FF3T87sfaTvXRW7owE1QMvFwpag2Bf", - "created": "2024-09-26T23:22:26Z", - "proofPurpose": "authentication", - "proofValue": "z2V72e7bRFpjvphDcWfYeSDTLsbkoVU5SfWAKMwpxYAL74D8GugTuoB2vH93cJqb8XXz8tN4es9AM787CogcbmXKa" - } - ] -} -``` - -Here is the [[ref: log entry]] for just version 3 of the DID. - -```json -{"versionId": "3-QmaSKJRACGefmi19LkS6TFj5FeMEfr98GpBWk7vEmbhT92", "versionTime": "2024-09-26T23:22:26Z", "parameters": {}, "state": {"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1", "https://identity.foundation/.well-known/did-configuration/v1", "https://identity.foundation/linked-vp/contexts/v1"], "id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example", "authentication": ["did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#z6MkrgET7ZLV32qNrr6vUd2kVXGw63vbPvqxDqqhRQpvngBX"], "assertionMethod": ["did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#z6MkrgET7ZLV32qNrr6vUd2kVXGw63vbPvqxDqqhRQpvngBX"], "verificationMethod": [{"id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#z6MkrgET7ZLV32qNrr6vUd2kVXGw63vbPvqxDqqhRQpvngBX", "controller": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example", "type": "Multikey", "publicKeyMultibase": "z6MkrgET7ZLV32qNrr6vUd2kVXGw63vbPvqxDqqhRQpvngBX"}], "service": [{"id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#domain", "type": "LinkedDomains", "serviceEndpoint": "https://domain.example"}, {"id": "did:tdw:QmfGEUAcMpzo25kF2Rhn8L5FAXysfGnkzjwdKoNPi615XQ:domain.example#whois", "type": "LinkedVerifiablePresentation", "serviceEndpoint": "https://domain.example/.well-known/whois.vc"}]}, "proof": [{"type": "DataIntegrityProof", "cryptosuite": "eddsa-jcs-2022", "verificationMethod": "did:key:z6MkvQnUuQn3s52dw4FF3T87sfaTvXRW7owE1QMvFwpag2Bf#z6MkvQnUuQn3s52dw4FF3T87sfaTvXRW7owE1QMvFwpag2Bf", "created": "2024-09-26T23:22:26Z", "proofPurpose": "authentication", "proofValue": "z2V72e7bRFpjvphDcWfYeSDTLsbkoVU5SfWAKMwpxYAL74D8GugTuoB2vH93cJqb8XXz8tN4es9AM787CogcbmXKa"}]} -``` - -And so on... diff --git a/spec/header.md b/spec/header.md index 2386abb..f144fed 100644 --- a/spec/header.md +++ b/spec/header.md @@ -8,6 +8,9 @@ Trust DID Web - `did:tdw` **Latest Draft:** [https://github.com/decentralized-identity/trustdidweb](https://github.com/decentralized-identity/trustdidweb) +**Information Site:** + [https://didtdw.org/](https://didtdw.org/) (Contains non-normative information previously in the specification) + **Editors:** ~ [Stephen Curran](https://github.com/swcurran) ~ [John Jordan, BC Gov](https://github.com/jljordan42) @@ -26,9 +29,11 @@ Trust DID Web - `did:tdw` ~ [TypeScript] ~ [Python] ~ [Go] +~ [DIDTDW Server in Python] [TypeScript]: https://github.com/bcgov/trustdidweb-ts [Python]: https://github.com/bcgov/trustdidweb-py [Go]: https://github.com/nuts-foundation/trustdidweb-go +[DIDTDW Server in Python]: https://github.com/decentralized-identity/trustdidweb-server-py ------------------------------------ diff --git a/spec/implementors_guide.md b/spec/implementors_guide.md deleted file mode 100644 index 68bee42..0000000 --- a/spec/implementors_guide.md +++ /dev/null @@ -1,243 +0,0 @@ -## Implementors Guide - -### Implementations - -Proof of concept implementations of `did:tdw` software for [[ref: DID Controllers]] and resolvers can be found here: - -- [Typescript] -- [Python] -- [Go] - -The implementations support all of the features of the core `did:tdw` including [[ref: Key Pre-Rotation]], except support for [[ref: witnesses]]. - -### Using Pre-Rotation Keys - -In an effort to prevent the loss of control over a decentralized identifier -(DID) due to a compromised private key, [[ref: pre-rotation]] keys are -introduced. These commitments, made by the [[ref: DID Controller]], are -declarations about the authorization keys that will be published in future -versions of the DID log, without revealing the keys themselves. - -The primary goal of [[ref: pre-rotation]] keys is to ensure that even if an attacker -gains access to the current active key, they will not be able to take control of -the DID. This safeguard is achieved because the attacker could not simply rotate to -a key they generate and control. Rather, they would need to have also -compromised the unpublished (and presumably securely stored) [[ref: pre-rotation]] key in -order to rotate the DID keys. - -The cost of having [[ref: pre-rotation]] protection is a more complicated process to update -the keys of a DID. The following are some considerations we have come across in -thinking about how to use the [[ref: pre-rotation]] feature. The feature adds a -layer of key management complexity in return for the benefit. - -#### Key Rotation with Pre-Rotation - -In using [[ref: pre-rotation]], a [[ref: DID Controller]] should generate an "active" key -for the [[ref: DIDDoc]] that is accessible for "production" purposes (signing, -decrypting), and generates the "next key" in an isolated location from -production. This prevents both the "active" and "next key" from being compromised in the -same intrusion attack. For example, if an intruder gets into your infrastructure and is able to extract all of your -private keys both DID control keys would be lost. Thus, we expect the feature to be used as follows: - -- The [[ref: DID Controller]] creating the DID would request from an isolated - service the hash of the "next key" as defined in this specification. For - example, an entity might have the "active" DID/key hosted by one Cloud - Provider, and the "next key" by another, on the theory that an attacker might - get into one environment or another but not both. -- When a key rotation is to be done, two [[ref: entries]] are put in the log, using the following steps by the [[ref: DID Controller]]: - 1. Get the full key reference entry from the isolated service for the [[ref: pre-rotation]] "nextKey". - 2. Locally generate a [[ref: pre-rotation]] key hash for a new key that will soon become the "active" key. - 3. Add a [[ref: DID log]] entry that includes the properties from the previous two steps, and signs the proof using an authorized key (that presumably it controls, though not required). - 1. Although the [[ref: DID log]] could be published now, it is probably best to hold off and publish it after adding a second, as described by the rest of the steps. - 4. Get a new [[ref: pre-rotation]] hash from the isolated service. - 5. Get the full key-rotation key reference for the [[ref: pre-rotation]] hash created for the last [[ref: DID log entry]]. - 6. Add a [[ref: DID Log]] entry that includes the properties from the previous two step - 7. If the key rotated in the previous [[ref: DID log entry]] was a/the - authorized key to make updates to the DID, call the isolated service to produce - the [[ref: Data Integrity]] proof over the entry using the key the isolated - service controls. - 1. This step is not needed if the active service has a key authorized to sign the [[ref: DIDDoc]] update. - 8. Publish the new [[ref: DID log]] containing the two new [[ref: entries]]. - -#### Post Quantum Attacks - -One of the potential benefits of this approach to [[ref: pre-rotation]] is that it is -"post-quantum safe". The idea is that in a post-quantum world, the availability -of the published key and signatures may enable the calculation of the -corresponding private key. Since the [[ref: pre-rotation]] value is a hash of the -`nextKey` and not the public key itself, a post-quantum attack would not -compromise that key, and so a further rotation by the attacker would not be -possible. If there was a (suspected) need to transition to using a quantum-safe -key, the same process listed above would be used, but key reference and the -pre-rotation hash added into the second [[ref: DID log]] entry would presumably -both be for quantum-safe keys. - -#### Challenges in Using Pre-Rotation - -Key management is hard enough without having to maintain isolated key generation -environments for creating keys for different purposes. Enabling connectivity between -the key generation environments to enable automated key rotation while maintaining the -key recovery environment as "isolated" is technically challenging. - -### Using DID Portability - -As noted in the [DID Portability](#did-portability) section of the -specification, a `did:tdw` DID can be renamed (ported) by changing the `id` DID string in -the [[ref: DIDDoc]] to one that resolves to a different HTTPS URL, as long as the -specified conditions are met. - -While the impact of the feature is in fact the creation of a new DID, we think -there is significant value in some use cases for supporting the specified -capability. Ideally, the HTTPS URL for the "old" DID is changed to a redirect to -the new DID, allowing for a seamless, verifiable evolution of the DID. - -An interesting example use case is a DID that replaces an email address hosted -by a particular service. The extra capabilities of having the identifier being a -DID vs. an email address is compelling enough, allowing it to be used for a -range of services beyond email. The [[ref: portability]] benefit comes when the owner of -the DID decides to move to a new service, taking their DID with them. The -verifiable history carried over to the renamed DID hosted by the new service -provides assurance to those who interacted with the old DID (through chats, -emails, postings, etc.) that they are still engaging with the same entity, -despite the DID renaming. Compare that with what happens today when you switch -from one email provider to another, and you have to reach out to all your -contacts to assure them that you changed providers. - -While [[ref: portability]] is powerful, it must be used with care and only in use -cases where the capability is specifically required. When used, both the -pre-rotation and [[ref: witnesses]] features of `did:tdw` **SHOULD** also be enabled. - -#### Mergers, Acquisitions and Name Changes - -Organizations change over time and such changes often involve names changes. -Name changes in turn trigger domain name changes, as organizations match their -Web location with their names. Mergers, acquisitions, and simple name changes, -all can cause an organization's "known" domain name to change, including the -relinquishment of control over their previous domain name. When such changes -occur, it is very unlikely that just because the organization's DIDs use the old -domain name will prevent the changes. Thus the DIDs need to "adapt" to the new -domain -- the domain name portion of the DID has to change. Ideally, the old -location and domain can be retained and a web redirect used to resolve the old -DID to the new, but even if that cannot be done, the ability to use the same -SCID and retain the full history can be preserved. - -#### DID Hosting Service Providers - -Consider being able to replace the current identifiers we are given (email -addresses, phone numbers) with `did:tdw` DIDs. Comparable hosting platforms -might publish our DIDs for us (ideally, with us in custody of our own private -keys...). Those DIDs, with the inherent public keys can be used for many -purposes -- encrypted email (hello PGP!), messaging, secure file sharing, and -more. - -From time to time in that imagined future, we may want to move our DIDs -from one hosting service to another, just as we move from one email or mobile -provider to another. With DIDs that can move and retain the history, we can make -such moves smoothly. Contacts will see the change, but also see that the history -of the DID remains. - -#### Challenges in Moving a DID - -While we see great value (and even a hard requirement) for being able to move a -DID's web location, it does create challenges in aligning with the -[[spec:DID-CORE]] specification. These challenges are listed below. - -Moving a `did:tdw` is actually the (partial or complete) deactivation of the old -DID and the creation of a new DID. The use of the [[ref: SCID]] and the way it -is generated is designed to prevent an attacker from being able to create a DID -they control but with the same [[ref: SCID]] as existing DID. Thus, "finding" a `did:tdw` -with the same [[ref: SCID]] implies the DIDs are the same. That can be verified by -processing the [[ref: DID Log]]. - -By retaining the incrementing of the `versionId` after a move, the "new" DID -does not start at `versionId` of `1`. Further, resolving `?versionId=1` -is going to return a [[ref: DIDDoc]] with the top-level `id` equal to the ``. -This is useful from a business perspective, but unexpected from a -[[spec:DID-CORE]] perspective. - -### Using High Assurance DIDs with DNS - -The [High Assurance DIDs with DNS] mechanism that can be used with `did:web` -applies equally well with `did:tdw`. A [[ref: DID Controller]] publishing a -`did:tdw` could use the mechanisms defined in the [High Assurance DIDs with DNS] -specification despite `did:tdw` DIDs not (yet) being explicitly called out in -the [High Assurance DIDs with DNS] specification. In particular, as `did:tdw` -uses the same DID-to-HTTP transformation, publishing the expected DNS Domain -records, and adding the required verification method and [[ref: Data Integrity]] -proof to their [[ref: DIDDoc]] is done as defined in the [High Assurance DIDs -with DNS] specification. Likewise, a resolver can include code to check to see if -the [[ref: DID Controller]] published the [High Assurance DIDs with DNS] -specification DNS records and use those to further verify the DID. - -Alternatively, since `did:tdw` is not mentioned in the [High Assurance DIDs with -DNS] specification, a `did:tdw` [[ref: DID Controller]] could use the "not `did:web`" -technique described in that specification and include a `dnsValidationDomain` -entry in the [[ref: DIDDoc]] to explicitly denote where to find the DNS records to use in -binding the DID to the DNS domain. This technique could also be used with -`did:tdw` (and `did:web` for that matter) if the DID is published on a platform -(such as GitHub) and the controller wants to bind it to its DNS domain. - -#### Future Possibilities - -In the future, as `did:tdw` becomes more accepted, we would like to see -`did:tdw` explicitly added to the [High Assurance DIDs with DNS] specification -beside `did:web`. - -Since `did:tdw` and the [High Assurance DIDs with DNS] specification both have -the goal of adding methods for additional verifications of the DID, the support -for `did:tdw` in the [High Assurance DIDs with DNS] could be more specific to -the DID Method. For example, the key in the DNS record could be a required -`did:tdw` witness, with its [[ref: Data Integrity]] proof being a part of the -[[ref: DID log entry]] rather than in the [[ref: DIDDoc]] itself. - -### Witnesses - -The term "witness" is often used in the decentralized trust space to refer to -participants in an ecosystem that oversee the evolution of an identifier -according to some ecosystem-specific governance framework. The goal is for a -[[ref: witness]] to collect, verify and approve data about the identifier and -share it with others that trust the [[ref: witness]] so they don't need to do -that work themselves. The extra participants are intended to identify both -malicious attackers of the identifier, and malicious use of the identifier by -the [[ref: DID Controller]]. - -Witnesses play an explicit function in `did:tdw`. When used by a [[ref: DID -Controller]], [[ref: witnesses]] (themselves identified by DIDs) are sent -pending [[ref: DID log entries]] prepared by the [[ref: DID Controller]]. The -[[ref: witnesses]] verify the [[ref: log entry]] using their copy of the -"current state" of the DID, and then "approve" the update, according to the -governance they use to define what "approval" means. For example, a [[ref: -witness]] might interact with another party (perhaps even a person) to confirm -that the [[ref: DID Controller]] created the [[ref: log entry]]. Once the [[ref: -witness]] has both verified and approved the change, they express that approval -by creating a [[ref: Data Integrity]] proof that is chained to the [[ref: data -integrity]] proof created by the [[ref: DID Controller]], and send the proof -back to the [[ref: DID Controller]]. Once the number of [[ref: data integrity]] -proofs received by the [[ref: DID Controller]] from the [[ref: witnesses]] has -exceeded a threshold, the [[ref: DID Controller]] adds those proofs to their own -[[ref: data integrity]] proof in the [[ref: log entry]]. Next, the [[ref: DID -Controller]] adds the [[ref: log entry]] to the [[ref: DID log]] and publishes -the updated DIDDoc. A [[ref: DID Controller]] relying on [[ref: witnesses]] -cannot independently publish an update to their DID -- they must get and publish -the [[ref: witness]] approval proofs. - -The application of [[ref: witnesses]] is very much dependent on the governance -of the ecosystem. Such governance is outside the scope of the `did:tdw` -specification, and up to those deploying `did:tdw` DIDs. Hence, a [[ref: DID -Controller]] that controls a series of DIDs and uses those DIDs as [[ref: -witnesses]] adds no additional trust or security to a DID if no properly defined -governance is in place. In particular, in order for [[ref: witnesses]] to add -security and trust to a DID requires the members of an ecosystem to agree to the -defined governance. A [[ref: witness]] could be an "endorser" of a set of DIDs -that are part of an ecosystem, with the act of witnessing the updates conveying -through their approval that the DIDs are a legitimate participant in the -ecosystem. [[ref: Witnesses]] can also be used as a form of "two-factor -authentication" of a change, such as having a public key published as a DNS -record used as a [[ref: witness]] for the DID. Such an addition means that an -attacker would need to compromise both the web-publishing infrastructure of the -DID Controller (where they publish the DID's `did.jsonl` file) as well as its -DNS entry. - -`did:tdw` witnesses have been specified to be simple to implement and use. Their -power and effectiveness will come in how they are deployed within specific, -governed ecosystems. diff --git a/spec/overview.md b/spec/overview.md index 478df90..8196f52 100644 --- a/spec/overview.md +++ b/spec/overview.md @@ -14,11 +14,11 @@ without its challenges-- from trust layers inherited from the web and the absence of a verifiable history for the DID. -Tackling these concerns, the proposed `did:tdw` (Trust DID Web) +Tackling these concerns, the `did:tdw` (Trust DID Web) DID method aims to enhance `did:web` by introducing features such as a [[ref: self-certifying identifiers]] (SCIDs), update key(s) and a verifiable history, akin to what is available with ledger-based DIDs, -without relying on a ledger. +but without relying on a ledger. This approach not only maintains backward compatibility but also offers an additional layer of assurance for those requiring more robust verification @@ -106,14 +106,8 @@ The following is a `tl;dr` summary of how `did:tdw` works: ::: An example of a `did:tdw` evolving through a series of versions can be seen in -the [did:tdw Examples](#didtdw-example) of this specification. - -This draft specification was developed in parallel with the development of two -proof of concept implementations. The specification/implementation interplay -helped immensely in defining a practical, intuitive, straightforward, DID -method. The existing proof of concept implementations of the `did:tdw` DID -Method are listed in the [Implementors Guide](#Implementations). The current -implementations range from around 1500 to 2000 lines of code. +the [did:tdw Examples](https://didtdw.org/latest/example/) on the `did:tdw` +information site. ### The `/whois` Use Case diff --git a/spec/specification.md b/spec/specification.md index e8eef79..c60185d 100644 --- a/spec/specification.md +++ b/spec/specification.md @@ -924,13 +924,6 @@ An overview of the [[ref: witness]] mechanism is as follows: - The specification leaves to implementers how the proofs are conveyed to the [[ref: DID Controller]]. -::: to do - -To Do: Update to use a [[ref: Data Integrity]] Proof Set, where the authorized key identifies -the proof, and the [[ref: witnesses]] proofs reference the identifier. - -::: - 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 @@ -976,8 +969,11 @@ the [[ref: DID Controller]] with a `selfWeight` of 2, and a `threshold` of 4, th threshold will be met by two [[ref: witnesses]] approving the change, plus the [[ref: DID Controller]]. -See the Implementer's Guide section on [Witnesses](#witnesses) for more -discussion on the witness capability and using it in production scenarios. +If you want to learn 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 +using it in production scenarios. #### Publishing a Parallel `did:web` DID diff --git a/spec/version.md b/spec/version.md index c801f6c..b143964 100644 --- a/spec/version.md +++ b/spec/version.md @@ -3,6 +3,7 @@ The following lists the substantive changes in each version of the specification. - 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]]. - Changes the data format of the [[ref: DID log entries]] from an array to an object. The [[ref: DID Log]] remains in the [[ref: JSON Lines]] format. - Changes the [[ref: DID log entry]] array to be named JSON objects or properties. diff --git a/specs.json b/specs.json index 52ca64f..25a13b2 100644 --- a/specs.json +++ b/specs.json @@ -6,12 +6,10 @@ "markdown_paths": [ "header.md", "abstract.md", - "definitions.md", "overview.md", "specification.md", "security_and_privacy.md", - "implementors_guide.md", - "example.md", + "definitions.md", "references.md", "version.md" ],