§ Trust DID Web - did:tdw

Specification Status: DRAFT

Latest Draft: https://github.com/bcgov/trustdidweb

Editors:
Stephen Curran
John Jordan, BC Gov
Andrew Whitehead
Brian Richter
Participate:
GitHub repo
File a bug
Commit history

§ Abstract

The did:tdw (Trust DID Web) method is an enhancement to the did:web protocol, providing a complementary web-based DID method that addresses limitations of did:web. Its features include:

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

§ Definitions

DID Log
A log of JSON arrays each of which provides the information necessary to generate and validate a version of the DIDDoc from the previous version.
JSON Lines
A file of JSON Lines, as described on the site 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.
self-certifying identifier
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 the initial DIDDoc with the placeholder {SCID} wherever the SCID is to be placed.
parameters
did:tdw parameters are a defined set of configurations that control how the issuer has generated the DID, and how the resolver should process the DID Log entries. The use of parameters allows for the controlled evolution of did:tdw log handling, such as evolving the permitted hash algorithms.
ISO8601
A date/time expressed using the ISO8601 Standard.
DID Controller
Per the [DID-CORE], a DID controller is an entity that is authorized to make changes to a DID document.
Entry Hash
A did:tdw entry hash is a hash generated using a formally defined process over the data of a log entry. The generated entry hash is subsequently put into the log entry and MUST be verified by a resolver.
Data Integrity
W3C Data Integrity 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.
JSON Patch
[RFC6902] is a web standard format for describing how to change a JSON document from one state to another. It is used in did:tdw to define how a DIDDoc is changed from one version to the next.
Key Pre-Rotation
A technique for a controller of a cryptographic key to commit to the next public key that it will use for a purpose, without exposing the public key. It protects from an attacker that gains knowledger of the current private key from being able to rotate to a new key the controller does not know.
DID Log Entry
A DID Log Entry is a JSON array of items that define the authorized transformation of a DIDDoc from one version to the next. The initial entry establishes the DID and version 1 of the DIDDoc.

DID Portability

did:tdw portability encompasses the ability to change the DID string for the DID while retaining the SCID and the history of the DID. This is useful 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.

base32_lower
Applies [RFC4648] to convert data to a base32 encoding, and then lower cases the result. Data encoded as base32 consists of a string of characters containing only the letters A-Z and digits 2-7.
Linked-VP
A [DID-CORE] service entry that specifies where a verifiable presentation about the DID subject can be found. The Decentralized Identity Foundation hosts the Linked VP Specification.
Verifiable Credential
A verifiable credential can represent all of the same information that a physical credential represents, adding technologies such as digital signatures, to make the credentials more tamper-evident and so more trustworthy than their physical counterparts. The Verifiable Credential Data Model is a W3C Standard.
Verifiable Presentation
A verifiable presentation data model is part W3C’s Verifiable Credential Data Model that contains a set of verifiable credentials about a credentialSubject, and a signature across the set of VCs generated by that subject. In this specification, the use case of primary interest is where the DID is the credentialSubject and the DID signs the verifiable presentation.
JSON Canonicalization Scheme
The [RFC8785] canonicalizes a JSON structure such that is suitable for verifiable hashing or signing.
Decentralized Identifier
Decentralized Identifiers (DIDs) [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.
DID Method
DID methods are the mechanism by which a particular type of DID and its 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.
Verifiable Conditions
The (proposed) verifiableConditions Specification defines a way to express complex conditions and additional metadata about verification methods. It can be used to combine verification methods to form conjugated conditions such as logical operations (like &&), thresholds, weighted thresholds, relationships, or delegation to external verification methods.
multi-sig
A cryptographic signature that to be valid MUST contain a defined 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 multi-signature is considered valid.

§ Overview

The evolution of Decentralized Identifiers (DID) continues to be a dynamic area of development in the quest for secure and private digital identity management. The did:web method, praised for its simplicity and ease of deployment, allows for DIDs to be associated with a domain’s reputation or published on platforms such as GitHub. However, it is not without its challenges– from trust layers inherited from the web and the absence of a verifiable history for the DID. Addressing these concerns, the proposed did:tdw (Trust DID Web) method aims to enhance did:web by introducing a verifiable history feature, akin to what is available with ledger-based DIDs, 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 processes. By publishing the resulting DID as both did:web and did:tdw, it caters to a broader range of trust requirements, from those who are comfortable with the existing did:web infrastructure to those seeking greater security assurances provided by did:tdw. This innovative step represents a significant stride towards a more trusted and secure web, where the integrity of cryptographic key publishing is paramount.

The key differences between did:web and did:tdw revolve around the core issues of decentralization and security. did:web is recognized for its simplicity and cost-effectiveness, allowing for easy establishment of a credential ecosystem. However, it is not inherently decentralized as it relies on DNS domain names, which require centralized registries, and it lacks a cryptographically verifiable, tamper-resistant, and persistently stored DID document. In contrast, did:tdw (Trust DID Web) is proposed as an enhancement to did:web, aiming to address these limitations by adding a verifiable history to the DID without the need for a ledger. This method seeks to provide a more decentralized approach by ensuring that the security of the embedded self-certifying identifier does not depend on DNS. Additionally, did:tdw is capable of resolving a cryptographically verifiable trust registry and status lists, using DID-Linked Resources, which did:web lacks. These features are designed to build a trusted web, offering a higher level of assurance for cryptographic key publishing and management.

For backwards compatibility, and for verifiers that “trust” did:web, a did:tdw can be trivially modified and published in parallel to a did:web DID. For resolvers that want more assurance, did:tdw provides a way to “trust did:web” (or to enable a “trusted web” if you say it fast) enabled by the features listed in the Abstract.

The following is a tl;dr summary of how did:tdw works:

  1. did:tdw uses the same DID-to-HTTPS tranformation as did:web, so did:tdw’s did.jsonl (JSON Lines) file is found in the same location as did:web’s did.json file.
  2. The did.jsonl is a list of JSON DID log entries, one per line, whitespace removed (per JSON Lines), each of which contains the information needed to derive a version of the DIDDoc from its preceding version.
  3. Each entry includes six JSON entries:
    1. A hash of the entry.
    2. The versionId of the DIDDoc, starting from 1 and incrementing.
    3. The versionTime (as stated by the DID Controller) of the entry.
    4. A set of parameters that impact the processing of the current and future log entries.
      • Example parameters are the version of the did:tdw specification and hash algorithm being used.
    5. The new version of the DIDDoc as either a value (the full document) or a patch derived using JSON Patch to update the new version from the previous entry.
    6. A Data Integrity (DI) proof across the entry, signed by a DID Controller authorized to update the DIDDoc.
  4. In generating the first version of the DIDDoc, the DID Controller calculates the SCID for the DID, includes it as a parameter in the first log entry, and inserts it where needed in the initial (and all subsequent) DIDDocs.
  5. A DID Controller generates and publishes the updated log file by making it available at the appropriate location on the web, based on the identifier of the DID.
  6. Given a did:tdw DID, a resolver converts the DID to an HTTPS URL, retrieves, and processes the log file did.jsonl, generating and verifying each log entry as per the requirements outlined in this specification.
    • In the process, the resolvers may collect all the DIDDoc versions and public keys (by reference) used by the DID currently, or in the past. This enables resolving both current and past DID URLs.
  7. did:tdw DID URLs with paths and /whois are resolved to documents published by the DID Controller that are by default in the web location relative to the did.jsonl file. See the note below about the powerful capability enabled by the /whois DID URL path.
  8. Optionally, a DID Controller can generate and publish a did:web DIDDoc from the latest did:tdw DIDDoc by changing the id to the did:web DID, and adding an alsoKnownAs for the did:tdw (indicating to a resolver that they can verify the DIDDoc, if wanted).
WARNING
A resolver settling for just the `did:web` version of the DID does not get the
verifiability of the `did:tdw` log.

An example of a did:tdw evolving through a series of versions can be seen in the did:tdw Examples 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. The current Typescript implementation is less than 1000 lines of Typescript code.

§ The /whois Use Case

This DID Method introduces what we hope will be a widely embraced convention for all DID Methods – the /whois path. This feature harkens back to the WHOIS protocol that was created in the 1970s to provide a directory about people and entities in the early days of ARPANET. In the 80’s, whois evolved into [RFC920] that has expanded into the global whois feature we know today as [RFC3912]. Submit a whois request about a domain name, and get back the information published about that domain.

We propose that the /whois path for a DID enable a comparable, decentralized, version of the WHOIS protocol for DIDs. Notably, when <did>/whois is resolved (using a standard DID service that follows the Linked-VP specification), a Verifiable Presentation (VP) may be returned (if published by the DID Controller) containing Verifiable Credentials with the DID as the credentialSubject, and the VP signed by the DID. Given a DID, one can gather verifiable data about the DID Controller by resolving <did>/whois and processing the returned VP. That’s powerful – an efficient, highly decentralized, trust registry. For did:tdw, the approach is very simple – transform the DID to its HTTPS equivalent, and execute a GET <https>/whois. Need to know who issued the VCs in the VP? Get the issuer DIDs from those VCs, and resolve <issuer did>/whois for each. This is comparable to walking a CA (Certificate Authority) hierarchy, but self-managed by the DID Controllers – and the issuers that attest to them.

The following is a use case for the /whois capability. Consider an example of the did:tdw controller being a mining company that has exported a shipment and created a “Product Passport” Verifiable Credential with information about the shipment. A country importing the shipment (the Importer) might want to know more about the issuer of the VC, and hence, the details of the shipment. They resolve the <did>/whois of the entity and get back a Verifiable Presentation about that DID. It might contain:

Such checks can all be done with a handful of HTTPS requests and the processing of the DIDs and verifiable presentations. If the system cannot automatically make a trust decision, lots of information has been quickly collected that can be passed to a person to make such a decision.

The result is an efficient, verifiable, credential-based, decentralized, multi-domain trust registry, empowering individuals and organizations to verify the authenticity and legitimacy of DIDs. The convention promotes a decentralized trust model where trust is established through cryptographic verification rather than reliance on centralized authorities. By enabling anyone to access and validate the information associated with a DID, the “/whois” path contributes to the overall security and integrity of decentralized networks.

§ did:tdw DID Method Specification

§ Target System

The target system of the Trust DID Web (TDW) DID method is the host (or domain) name when the domain specified by the DID is resolved through the Domain Name System (DNS).

§ Method Name

The namestring that identifies this DID method is: tdw. A DID that uses this method MUST begin with the following prefix: did:tdw. Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix, is the method-specific identifier, specified below.

§ Method-specific Identifier

The method specific identifier is a fully qualified domain name that is secured by a TLS/SSL certificate with an optional path to the DID Log. The identifier MUST contain a self-certifying identifier (SCID) as either part of the subdomain component of the domain name, or as a component of the optional path. The content of the SCID is generated in creating the DID. The formal rules describing valid domain name syntax are described in [RFC1035], [RFC1123], and [RFC2181].

The domain name component of the method specific identifier MUST match the common name used in the SSL/TLS certificate, and it MUST NOT include IP addresses. A port MAY be included and the colon MUST be percent encoded to prevent a conflict with paths. Directories and subdirectories MAY optionally be included, delimited by colons rather than slashes.

The SCID, a globally unique identifier, is generated as part of the creation of the DID and placed into the DID identifier.

As specified in the following Augmented Backus-Naur Form (ABNF) notation [RFC2234] the SCID MUST be present in the DID string, but may be placed in the (optional) subdomain component of the domain, or as a segment in the (optional) URL path. See examples below. The domain-segment and path-segment elements refer to [RFC3986]’s ABNF for a Generic URL (page 49). Attempting to replicate here the full ABNF of those elements from that RFC would inevitably be wrong.

tdw-did = "did:tdw:" *( domain-segment “.” ) scid 2*( “.” domain-segment ) *( ":" path-segment )
tdw-did = "did:tdw:" 2*( domain-segment “.” ) *( ":" path-segment ) (":" scid ) *( ":" path-segment )
domain-segment = ; A part of a domain name as defined in RFC3986, such as "example" and "com" in "example.com"
path-segment= ; A part of a URL path as defined in RFC3986, such as "path", "to", "folder" in "path/to/folder"
scid = 28+( lower-base32 )
lower-base32 = [2-7a-z]
EXAMPLE

did:tdw DIDs and the corresponding web locations for their did:tdw log file. {SCID} is a placeholder for where the generated SCID will be placed in the examples.


subdomain

did:tdw:{SCID}.example.com -->

https://{SCID}.example.com/.well-known/did.jsonl

path

did:tdw:example.com:dids:{SCID} -->

https://example.com/dids/{SCID}/did.jsonl

path w/ port

did:tdw:example.com%3A3000:dids:{SCID} -->

https://example.com:3000/dids/{SCID}/did.jsonl

The location of the did:tdw did.jsonl DID Log file is the same as where the comparable did:web did.json file is published. A DID MAY choose to publish both DIDs and so both files.

§ DID Method Operations

§ Create (Register)

Creating a did:tdw DID is done by carrying out the following steps.

  1. Define the DID string, and hence, the web location at which the DID Log (did.jsonl) will be published. Identify (using the placeholder {SCID}) where the required SCID will be placed in the DID string (ie. did:tdw:example.com:{SCID}).
  2. Create the initial DIDDoc (did.json) file for the DID, with whatever content is required. Wherever there is self-reference to the DID in the DIDDoc, use the absolute form defined in step 1, with the identified placeholder for the SCID (ie. did:tdw:example.com:{SCID}#key-1).
    1. As per Authorized Keys, the DIDDoc MUST contain at least one authentication or verificationMethod key type.
  3. Define a JSON array of valid parameters that affect the generation of the DID. The DID Generation and Validation Parameters section of this specification defines the permitted parameters.
  4. Pass the DID string, initial DIDDoc, and parameters to a did:tdw “Create” implementation that MUST:
    1. Calculate the SCID for the DID as defined in the SCID Generation and Validation section of this specification.
    2. Replace in the DIDDoc the placeholder for the SCID {SCID} with the calculated SCID.
    3. Generate a DID Entry as a JSON array with the following five JSON items:
      1. The SCID as the entryHash value: "4c99uuenu8gk6n3bgf09fuf350gx"
      2. An integer, 1, that is the versionId for this first version of the DIDDoc: 1
      3. A string that is the current time in ISO8601 format: "2024-04-04T07:32:58Z"
      4. The parameters passed in as a JSON dict: {"method":"did:tdw:1","scid":"4c99uuenu8gk6n3bgf09fuf350gx"}
      5. The contents of the initial DIDDoc, in the form: {"value": <DIDDoc>}
    4. Calculate the Entry Hash (entryHash) of the DID Entry as defined in the Entry Hash Generation and Validation section of this specification.
    5. Update the entryHash with the value produced in the previous step.
    6. Generate a Data Integrity proof on the initial DIDDoc using an authorized key from the DID, and the entryHash as the proof challenge. The definition of “authorized” in this case is specified in the Authorized Keys section of this specification. The proof becomes the sixth and last JSON item in the DID log entry.
    7. Put the resulting entry, with extraneous white space removed as the contents of a file did.jsonl and publish the file at the appropriate location defined by the did:tdw value.
      • This is a logical operation – how a deployment serves the did.jsonl content is not constrained.

A controller MAY generate an equivalent did:web DIDDoc and publish it as defined in the Publishing a Parallel did:web DID section of this specification. The did:web DIDDoc could be used for backwards compatibility as a transition is made from did:web to did:tdw. Verifiers using the did:web lose the verifiable properties and history of the did:tdw for the convenience of the simple retrieval of the did:web DIDDoc.

§ Read (Resolve)

The following steps MUST be executed to resolve the DIDDoc for a did:tdw DID:

  1. Replace : with / in the method specific identifier to obtain the fully qualified domain name and optional path.
  2. If the domain contains a port percent decode the colon.
  3. Generate an HTTPS URL to the expected location of the DIDDoc by prepending https://.
  4. If no path has been specified in the URL, append /.well-known.
  5. Append /did.jsonl to complete the URL.
  6. Perform an HTTP GET request to the URL using an agent that can successfully negotiate a secure HTTPS connection, which enforces the security requirements as described in Security and privacy considerations.
  7. When performing the DNS resolution during the HTTP GET request, the client SHOULD utilize [RFC8484] in order to prevent tracking of the identity being resolved.
  8. Process the DID Log file as described below.

To process the retrieved DID Log file, the resolver MUST carry out the following steps:

  1. Process the Log entries in the order they appear in the file, applying the parameters set on current and previous entries. As noted in the Create (Register), each log entry consists of a JSON array of 6 items:
    1. entryHash
    2. versionId
    3. versionTime
    4. parameters
    5. DIDDoc content – either the full value or a JSON Patch patch to be applied to the prior version of the DIDDoc.
    6. A Data Integrity proof for the current version of the DIDDoc of the entry.
  2. For each entry:
    1. Update the currently active parameters with the parameters from the entry (if any). Continue processing using the now active set of parameters.
    2. Verify the Data Integrity proof in the entry, and ensure it is signed by an authorized key as defined in the Authorized Keys section of this specification.
    3. Verify the entryHash for the entry using the process defined in the Entry Hash Generation and Verification section of this specification.
    4. Verify that the first log entry’s versionId is 1, and that the versionId is incremented by one for each subsequent log entry.
    5. Verify that the versionTime for each log entry is greater than the previous entry, and that the versionTime values are all earlier than the current time.
    6. For the initial version of the DIDDoc (1) verify that the SCID (defined in the parameters) is being used in the DID, and verifies according to the SCID Generation and Verification section of this specification.
    7. Generate the version of the DIDDoc for the entry by using the JSON value of the value item, or by using JSON Patch to apply the JSON value of the patch entry item to the previous version of the DIDDoc.
    8. If Key Pre-Rotation is being used, verify that any added keys in the DIDDoc have a valid pre-rotation entry as defined in the Key Pre-Rotation Hash Generation and Verification section of this specification.
    9. Once each log entry has been processed, collect the following information about each version:
      1. DIDDocument
      2. versionId
      3. versionTime

On completing the processing of all entries in the DID Log, respond to the DID resolution request, including the application of query parameters such as ?versionId= and ?versionTime= with the appropriate DIDDoc version.

The following error codes and descriptions may be returned when resolving a DID.

TODO

Document the full list of error codes that can be generated in resolving a DID.

§ Reading did:tdw DID URLs

A did:tdw resolver MAY implement the resolution of the /whois and a DID URL Path using the whois LinkedVP Service and DID URL Path Resolution Service as defined in this specification by processing the DID Log and then dereferencing the DID URL based on the contents of the DIDDoc. The client of a resolver that does not implement those capabilities must use the resolver to resolve the appropriate DIDDoc, and then process the resulting DID URLs themselves. Since the default DID-to-HTTPS URL transformation is trivial, did:tdw DID are strongly encouraged to use the default behavior for DID URL Path resolution.

§ Update (Rotate)

To update a DID a new, verifiable DID Log Entry must be generated, appended to the existing DID Log (did.jsonl) and published to the web location defined by the DID. The process to generate a verifiable DID follows a similar process to the Create process, as follows:

  1. Make the desired changes to the DIDDoc. While the contents of a new DIDDoc version are (mostly) up to the DID controller, there are some limitations:
    1. The id of the DIDDoc MAY be changed when the DID Controller wants to (or must) publish the DID at a different location and wants to retain the SCID and history of the DID. For details, see the section Moving a DID’s Web Location.
    2. If Key Pre-Rotation is being used in the DID, only keys with a valid nextKeys entry in a previous DIDDoc can be added, as defined in the Using Pre-Rotation Keys section of this specification.
  2. Define a JSON array of valid parameters that affect the evolution of the DID. The did:tdw DID Method Parameters section of this specification defines the permitted parameters.
  3. Pass the current DID Log, the updated DIDDoc, and the parameters to a did:tdw update implementation which MUST:
    1. Generate a DID Entry as a JSON array with the following JSON items:
      1. The entryHash from the previous DID Log Entry as the entryHash value.
      2. An integer that is one more than the versionId of the previous DID Log Entry.
      3. A string that is the current time in ISO8601 format: "2024-04-05T07:32:58Z"
      4. The parameters passed in as a JSON dict: {}
        1. parameters from previous versions continue to apply and do not need to be repeated in each version. As a result, the parameters item will often be an empty dict.
      5. Generate a JSON Patch to evolve the previous DIDDoc version to the new DIDDoc version, and put the resulting patch in the item {"patch": <DIDDoc Patch>}. For details see the Generating and Applying a JSON Patch section of this specification.
        1. An implementation MAY skip the JSON Patch process and simply put the full new version of the DIDDoc in the item {"value": <DIDDoc>} as is done in the initial entry in the log.
    2. Calculate the Entry Hash (entryHash) of the DID Entry as defined in the Entry Hash Generation and Validation section of this specification.
    3. Update the entryHash with the value produced in the previous step.
    4. Generate a Data Integrity proof on the new DIDDoc of the entry using an authorized key from the DID, and the entryHash as the proof challenge. The definition of “authorized” is formalized in the Authorized Keys section of this specification. The proof becomes the last JSON item in the entry.
    5. Append the resulting entry to the existing contents of the DID file did.jsonl on a new line.
  4. Update the DID Log file at the appropriate location defined by the did:tdw identifier.
    • This is a logical operation – how a deployment serves the did.jsonl content is not constrained.

A controller MAY generate an equivalent, updated did:web DIDDoc and publish it as defined in the Publishing a Parallel did:web DID section of this specification.

A controller may use the move DID log entry parameter to change the DID string. That effectively creates a new DID, but a DID that retains the SCID and verifiable history of the original DID. A DID Controller may do that when forced (for example, loss of domain name) or by choice (moving from a DID hosting provider to another) without losing the history and reputation of the DID. See the Moving a DID section of the Implementers Guide for a discussion of moving a did:tdw DID.

§ Deactivate (Revoke)

To deactivate the DID, the DID Controller SHOULD add to the DID log entry parameters the item "deactivated": true. A DID MAY update the DIDDoc further to indicate the deactivation of the DID, such as removing the authentication key type entries, preventing further updates to the DID/DIDDoc.

A resolver encountering in the DID log entry parameters the item "deactivated": true should return in the DIDDoc Metadata the JSON item "deactivated": true, as per the [DID-CORE] specification.

§ DID Method Processes

The DID Method Operations reference several processes that are executed during DIDDoc generation and DID resolution verification. Each of those processes is specified in the following sections.

§ did:tdw DID Method Parameters

Entries in the did:tdw DID Log file contain, as the 4th item, a JSON object that define the DID processing parameters being used by the DID when publishing that and subsequent DID Entries. A DID Resolver will use the same parameters when processing the DID Log to resolve the DID. The parameters object MUST only include items defined in this specification.

EXAMPLE

An example of the parameters item in the first DID Log entry for a DID:

{"method":"did:tdw:1","scid":"4c99uuenu8gk6n3bgf09fuf350gx"}

The permitted parameter items and (where applicable) enumerated values for those items are defined below.

§ SCID Generation and Validation

The Self-certifying identifier or scid is a required parameter in the first DID log entry and is a portion of the hash of the initial DID Document.

§ Generate SCID

To generate the required SCID for a did:tdw DID, the DID Controller MUST execute the following function:

left(base32_lower(hash(JCS(initial DIDDoc with placeholders))), <length>)

Where:

  1. The initial DIDDoc with placeholders is the initial DID Doc defined by the DID Controller with the placeholder {SCID} put everywhere the SCID will be used in the resolved version 1 DIDDoc. At minimum, the {SCID} MUST appear in the top level id item of the DIDDoc. It MAY occur elsewhere in the DIDDoc.
  2. JCS is an implementation of the JSON Canonicalization Scheme [RFC8785]. It outputs a canonicalized representation of its input.
  3. hash is either sha256 or an alternative hash algorithm defined in the hash item in the parameters. Its output is the hash of its input.
  4. base32_lower as defined by the base32_lower function. Its output is the lower case of the Base32 encoded string of its input.
  5. left extracts the <length> number of characters from the string input.
    1. <length> MUST be at least 28 characters.
§ Verify SCID

To verify the SCID of a did:tdw DID being resolved, the resolver MUST execute the following process:

  1. Extract from the parameters in the first DID log entry for the DID the scid item’s value.
  2. Verify that the length of the scid is at least 28 characters.
    1. If less than 28 characters, terminate the resolution process with an error.
  3. Extract from the first DID log entry the value item’s value, which is the initial DIDDoc.
  4. Treat the values value as a string and do a text replacement of the scid from the first step with {SCID}. This should result in the initial DIDDoc with placeholders data needed for the next step.
  5. Execute the hashing process defined in the generation defined above to generate the value calculatedSCID.
    1. For the <length> value, use the length of the scid extracted in step 1.
  6. Verify that the scid matches the calculatedSCID.

§ Entry Hash Generation and Validation

The entryHash is the first item in each DID log entry and is a hash calculate across the entry, excluding the Data Integrity proof.

§ Generate Entry Hash

To generate the required hash for a did:tdw DID entry, the DID Controller MUST execute the following process:

  1. Make the value of the entryHash for this entry to the entryHash of the previous entry. For the first entry in the log, set the value of entryHash to the SCID for the DID.
  2. Create the full entry JSON array with elements entryHash, versionId, versionTime, and didDocVersion (which is either a value or patch). See an example below.
  3. Calculate the hash string as base32_lower(hash(JCS(entry))), where:
    1. JCS is an implementation of the JSON Canonicalization Scheme ([RFC8785]). Its output is a canonicalized representation of its input.
    2. hash is either sha256 or an alternative hash algorithm defined in the hash item in the parameters. Its output is the hash of its input JCS content.
    3. base32_lower as defined by the base32_lower function. Its output is the lower case of the Base32 encoded string of the input hash.
  4. Replace the entryHash value in the entry with the calculated value from step 3.

Example of a DID log entry that is processed in step 3 to produce a hash. As this is a first entry in a DID Log, the entryHash is the SCID of the DID.

["4c99uuenu8gk6n3bgf09fuf350gx",1,"2024-04-15T19:56:18Z",{"method": "did:tdw:1","scid": "4c99uuenu8gk6n3bgf09fuf350gx"},{"value": {"@context": ["https://www.w3.org/ns/did/v1","https://w3id.org/security/multikey/v1"],"id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","authentication": ["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT"],"assertionMethod": ["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B"],"verificationMethod": [{"id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","type": "Multikey","publicKeyMultibase": "z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"},{"id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B","controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","type": "Multikey","publicKeyMultibase": "z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"}]}}]

Resulting entry hash: 4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g

§ Verify Entry Hash

To verify the entryHash for a did:tdw DID entry, a DID Resolver MUST execute the following process:

  1. Extract the first item in the DID log entry as the entryHash
  2. Remove the Data Integrity proof (5th item) from the entry array.
  3. Set the first value of the entry to the entryHash of the previous entry. If this is the first entry in the log, set the value to the SCID for the DID.
  4. Calculate the hash string as base32_lower(hash(JCS(entry))), where:
    1. JCS is an implementation of the JSON Canonicalization Scheme ([RFC8785]). Its output is a canonicalized representation of its input.
    2. hash is either [sha256] or an alternative hash algorithm defined in the hash item in the parameters. Its output is the hash of its input JCS content.
    3. base32_lower as defined by the base32_lower function. Its output is the lower case of the Base32 encoded string of the input hash.
  5. Verify that the calculated value from Step 4 matches the extracted value from Step 1.

§ Authorized Keys

Each entry in the DID Log MUST include a Data Integrity proof signed by a key authorized to control (create, update, deactivate) the DID. For did:tdw, the following defines the process for collecting the authorized keys.

  1. Retrieve the DIDDoc in which the set of authorized controller DIDs is found. For the first version (1) of the DID, that is the first (and only) DIDDoc. For all subsequent versions of the DID, the previous DIDDoc version is used.
  2. From the DIDDoc, the top-level controller item is retrieved to create a (possibly empty) array of controller DIDs from the DIDDoc.
    1. If the list of controller DIDs is empty, the DID being signed is added to the array.
  3. For each DID in the list, the set of authentication key type references are collected from within the DIDDoc.
    1. If there are no authentication key type references, the verificationMethod key references are collected.
    2. If the controller DID is for an external DID, the key referenced MUST be present in the DIDDoc being processed.

The controller of the DID MUST use a key from the resulting key references to sign the DID Log entry.

A resolver of the DID MUST verify that the key used for signing the DID Log entry is in the list of authorized DID key references, and MUST verify the proof.

NOTE
  • [DID-CORE] is not clear (at least to the authors of this specification) on what key types define those authorized to update a DID.
  • The requirement to have the key reference for external DIDs (not the controlled DID) copied into the DIDDoc is to prevent an implementation from having to resolve external DIDs (that could use any DID Method) during the resolution of a DID. This might be too restrictive and could be changed in an update to this specification. For example, it might be reasonable to require that external DIDs of certain DID Methods (such as did:tdw or did:web) be resolved as part of resolving the controlled DID.
  • In a future version of the specification, the authors would like to require support for verifiableConditions key types, to enable multi-sig DID control support, such as requiring “N of M” signatures must be in a proof for it to be valid.

§ Generating and Applying a JSON Patch

Each time a new did:tdw version is created, the DID Controller MAY generate a JSON Patch to concisely define the changes in the DIDDoc from the previous version. A DID log entry that uses JSON Patch has a JSON object with a patch property, with the value the JSON Patch as its 5th item. A DID Controller MAY set the fourth item of a DID log entry to be the JSON item value, with its value the complete DIDDoc. Typically (but not required), a DID Controller will use value for the first DID log entry and patch for all subsequent entries.

To create the value for a patch item for a DID log entry, the DID Controller MUST:

  1. Have the fully resolved previous version of the DIDDoc.
  2. Have the updated new version of the DIDDoc to be added.
  3. Execute an implementation of JSON Patch that takes the two DIDDocs as inputs (previous before, new after) and outputs the resulting JSON Patch from before to after.
  4. Set the fourth item of the DID log entry to {"patch": "<patch>"}, removing all extraneous whitespace from the <patch>.

When processing a DID log entry with a patch , a resolver MUST:

  1. Have the fully resolved previous version of the DIDDoc.
  2. Execute an implementation of JSON Patch that takes the previous DIDDoc and the patch as inputs, and outputs the resulting new version of the DIDDoc.

§ Publishing a Parallel did:web DID

Each time a did:tdw version is created, the DID Controller MAY generate a corresponding did:web to publish along with the did:tdw. To do so, the DID Controller MUST:

  1. Start with the resolved DIDDoc from did:tdw.
  2. Execute a text replacement across the DIDDoc of did:tdw to did:web.
  3. Add to the DIDDoc alsoKnownAs array, the full did:tdw DID. If the alsoKnownAs array does not exist in the DIDDoc, it MUST be added.
  4. Publish the resulting DIDDoc as the file did.json at the web location determined by the specified did:web DID to HTTP transformation.

Note that the SCID remains in the did:web DID string.

The benefit of doing this is that resolvers that have not been updated to support did:tdw can continue to resolve the DID Controller's DIDs. did:web resolvers that are aware of did:tdw features can use that knowledge, and the existence of the alsoKnownAs did:tdw data in the DIDDoc to get the verifiable history of the DID.

The risk of publishing the did:web in parallel with the did:tdw is that the added security and convenience of using did:tdw are lost.

§ Pre-Rotation Key Hash Generation and Validation

Pre-rotation is a term defining how a DID Controller can commit to the keys that will be added (“rotated to”) in future versions of the DIDDoc. The purpose of committing to future keys is that if the currently active keys are compromised by an attacker, the attacker should not be able to rotate the compromised keys to new ones only the attacker controls to take over the control of the DID. The effectiveness of pre-rotation is based on the idea that an attacker cannot compromised the future keys. See the non-normative section about Using Pre-Rotation Keys in the implementors guide section of this specification.

As described in the parameters section of this specification, a DID Controller MAY define that prerotation is active for the DID. When that is the case, all additions of new keys in future versions of the DIDDoc MUST have their hash in one or more of the nextKeys arrays of previous DID log entry parameters.

To create a hash to be included in the nextKeys array, the DID Controller MUST execute the following process:

  1. Generate a new key pair.
  2. Create the JSON dict Verification Material, defined in [DID-CORE], for the new key. An example of such an entry is defined below.
  3. Calculate the hash string as base32_lower(hash(JCS(<verificationMaterial>))), where:
    1. JCS is an implementation of the JSON Canonicalization Scheme [RFC8785]. Its output is a canonicalized representation of its input.
    2. hash is either sha256 or an alternative hash algorithm defined in the hash item in the parameters. Its output is the hash of its input JCS content.
    3. base32_lower as defined by the base32_lower function. Its output is the lower case of the Base32 encoded string of the input hash.
  4. Add the hash calculated in Step 3 to a DID log entry nextKeys item in the parameters (4th item of the entry array).
  5. The JSON dict from Step 2 can be inserted into a future version of the DIDDoc.

When processing a DID log entry where the prerotation parameter is active, a resolver MUST:

  1. When processing each DID log entry, after verifying a DIDDoc, add an optional array of nextKeys from the parameters into an array of hash strings.
    1. The collection of the nextKeys from the current entry must occur after the processing and verification of that entries` DIDDoc version so that a new key and its pre-rotation hash cannot be added in the same entry.
  2. For all DIDDoc versions after versionId 1, detect when a new key Verification Material is added to a version of a DIDDoc. If so, for each new key:
    1. Extract the Verification Material JSON dict for the new key from the new DIDDoc.
    2. Calculate the hash string as base32_lower(hash(JCS(verificationMaterial))), where:
      1. JCS is an implementation of the JSON Canonicalization Scheme [RFC8785]. Its output is a canonicalized representation of its input.
      2. hash is either sha256 or an alternative hash algorithm defined in the hash item in the parameters. Its output is the hash of its input JCS content.
      3. base32_lower as defined by the base32_lower function. Its output is the lower case of the Base32 encoded string of the input hash.
    3. Check to see if the hash string is listed in the collected list of nextKeys.
      1. If so, the new key is verified.
      2. If not, the verification process failed.

§ DID URL Resolution

The did:tdw DID Method embraces the power and usefulness of DID URLs, along with the semantic simplicity of using them in a web-based DID method. Specifically, a did:tdw implementation MUST:

In both cases, a DID Controller MAY define services in the DIDDoc that override the default services that MUST be resolved by the did:tdw DID Method.

The sections below formalize the services that exist by default in did:tdw and how a DID Controller can override them.

§ whois LinkedVP Service

The #whois service enables those that receive a did:tdw DID to retrieve and a Verifiable Presentation (and embedded Verifiable) the DID Controller has decided to publish about itself. The intention is that anyone interested in a particular did:tdw DID can resolve the <did>/whois DID URL, to retrieve a Verifiable published by the DID Controller that contains Verifiable Credentials to decide to publish a whois verifiable presentation, along with which verifiable credentials to put into the verifiable presentation.

See the The /whois Use Case in this specification for the background about why this capability is so useful, particularly for a web-based DID Method like did:tdw.

did:tdw DIDs automatically supports a #whois service endpoint with the following definition based on the Linked VP specification, with the serviceEndpoint matching the did:tdw DID-to-HTTPS DIDDoc transformation and did.jsonl changed to whois.json.

{
   "@context": "https://identity.foundation/linked-vp/contexts/v1",
   "id": "#whois",
   "type": "LinkedVerifiablePresentation",
   "serviceEndpoint": "https://example.com/dids/<scid>/whois.json"
}

The returned whois.json MUST contain a W3C VCDM verifiable signed by the DID and containing verifiable credentials with the DID as the credentialSubject.

A DID Controller MAY explicitly add to their DIDDoc a did:tdw service with the "id": "#whois". Such an entry MUST override the implicit service above. If the DID Controller wants to publish the /whois verifiable presentation in a different format than the W3C format, they MUST explicitly add to their DIDDoc a service with the "id": "#whois" to specify the name and implied format of the verifiable.

To resolve the DID URL <did:tdw DID>/whois, the resolver MUST:

  1. Resolve the given did:tdw DID by retrieving, processing, and verifying the DID log for the did:tdw as defined in this specification.
  2. Find the DIDDoc service with the id #whois, if any, or use the implicit service (above).
  3. Resolve the serviceEndpoint URL, if possible, and return the document found.
    1. If the serviceEndpoint URL can’t be resolved by the resolver (such as if the URL protocol is not supported by the resolver), the error Error XXX: YYY MUST be returned.
    2. If the file at the defined serviceEndpoint is not found, Error 404: Not Found MUST be returned.

§ DID URL Path Resolution Service

The automatic resolution of did:tdw DID URL paths follows the [DID-CORE] relativeRef specification, as follows:

Thus, the implicit service for DID did:tdw:example.com:dids:<scid> is:

{
   "id": "#files",
   "type": "relativeRef",
   "serviceEndpoint": "https://example.com/dids/<scid>"
}

A DID Controller MAY explicitly add to their DIDDoc a service with the "id": "#files". Such an entry MUST override the implicit service defined above.

To resolve the DID URL <did:tdw DID>/path/to/file, the resolver MUST:

  1. Resolve the given did:tdw DID by retrieving, processing, and verifying the DID log for the did:tdw as defined in this specification.
  2. Find the DIDDoc service with the id #files, if any, or use the implicit service (above).
  3. Resolve the serviceEndpoint URL with the DID URL Path appended, if possible, and return the document found at that location.
    1. If the serviceEndpoint URL can’t be resolved by the resolver (such as if the URL protocol is not supported by the resolver), the error Error XXX: YYY MUST be returned.
    2. If the file at the path appended to the defined serviceEndpoint is not found, the error Error 404: Not Found MUST be returned.

§ Security and Privacy Considerations

§ DNS Considerations

§ DNS Security Considerations

Implementers must secure DNS resolution to protect against attacks like Man in the Middle, following the detailed guidance in the did:web specification. The use of DNSSEC [RFC4033], [RFC4034], [RFC4035] is essential to prevent spoofing and ensure authenticity of DNS records.

§ DNS Privacy Considerations

Resolving a did:tdw identifier can expose users to tracking by DNS providers and web servers. To mitigate this risk, it’s recommended to use privacy-enhancing technologies such as VPNs, TOR, or trusted universal resolver services, in line with strategies outlined in the did:web specification including emerging RFCs such as Oblivious DNS over HTTPS for DNS privacy.

§ In-transit Security

For in-transit security, the guidance provided in the did:web specification regarding the encryption of traffic between the server and client should be followed.

§ International Domain Names

[DID-CORE] identifier syntax does not allow Unicode in method name nor method specific identifiers.

Implementers should be cautious when implementing support for DID URLs that rely on domain names or path components that contain Unicode characters.

See also:

§ Implementors Guide

§ Implementations

Proof of concept implementations of did:tdw software for DID Controllers and resolvers can be found here:

Both currently (as of 2024.04.11) support all of the features of did:tdw except for Key Pre-Rotation and Verifiable Conditions.

The Typescript implementation is currently less than 1000 lines of Typescript code.

§ Using Pre-Rotation Keys

In an effort to prevent the loss of control over a decentralized identifier (DID) due to a compromised private key, pre-rotation keys are introduced. These commitments, made by the DID Controller, are declarations about the keys that will be published in future versions of the DID document, without revealing the keys themselves.

The primary goal of 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) pre-rotation key in order to rotate the DID keys.

The cost of having pre-rotation protection is a much more complicated process to update the keys of a DID. The following are some considerations we have come across in considering how to use the pre-rotation feature. The feature definitely adds a layer of key management complexity in return for the benefit.

§ Key Rotation with Pre-Rotation

In using pre-rotation, a DID Controller should generate an “active” key for the DIDDoc where it can be used 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 attack. For example, 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:

§ Post Quantum Attacks

One of the potential benefits of this approach to 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 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 DID log entry would presumably both be for quantum-safe keys.

§ Challenges in Using Pre-Rotation

This draft specification states that once pre-rotation is enabled (via DID log entry parameter), it MUST apply to all of the keys in the DIDDoc. However, we’re not sure if that is needed, or if the pre-rotation should only apply to keys that are authorized to update the DID.

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.

§ Moving a DID

As noted in the did:tdw DID Method Parameters section of this specification, a did:tdw DID can be “moved” by changing the DID string to one that resolves to a different HTTPS URL, as long as:

In moving the DID, the versionId of the DID continues to increment.

While the feature does “bend” the rules for DIDs, we think there is significant value in supporting the specified functionality. These are the uses cases that we considered in adding the functionality.

§ 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 [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 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 SCID as existing DID. Thus, “finding” a did:tdw with the same SCID implies the DIDs are the same. That can be verified by processing the DID Log.

By retaining the incrementing of the versionId after a move, the “new” DID does not start at versionId of 1. Further, resolving <new-did>?versionId=1 is going to return a DIDDoc with the top-level id equal to the <old-did>. This is useful from a business perspective, but unexpected from a [DID-CORE] perspective.

§ did:tdw Example

The following shows the evolution of a did:tdw from inception through several versions, showing the DID, DIDDoc, DID Log, and some of the intermediate data structures.

In the following, all of the data for the DID log entries are displayed as prettified JSON for readability. In the log itself, the JSON has all whitespace removed, and each line ends with a CR.

§ DID Creation Data

These examples show the important structures used in the Create (Register) operation for a did:tdw DID.

§ DIDDoc with SCID Placeholders

This is the version of the DIDDoc that the DID Controller constructs (however they see fit) and passes into the SCID Generation Process.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1"
  ],
  "id": "did:tdw:example.com:{SCID}",
  "controller": "did:tdw:example.com:{SCID}",
  "authentication": [
    "did:tdw:example.com:{SCID}#y4SDXopT"
  ],
  "assertionMethod": [
    "did:tdw:example.com:{SCID}#5b48Zj6B"
  ],
  "verificationMethod": [
    {
      "id": "did:tdw:example.com:{SCID}#y4SDXopT",
      "controller": "did:tdw:example.com:{SCID}",
      "type": "Multikey",
      "publicKeyMultibase": "z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"
    },
    {
      "id": "did:tdw:example.com:{SCID}#5b48Zj6B",
      "controller": "did:tdw:example.com:{SCID}",
      "type": "Multikey",
      "publicKeyMultibase": "z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"
    }
  ]
}

§ DIDDoc with SCID In Place

After the SCID is generated, the {SCID} placeholders are replaced by the generated SCID value.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1"
  ],
  "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
  "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
  "authentication": [
    "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT"
  ],
  "assertionMethod": [
    "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B"
  ],
  "verificationMethod": [
    {
      "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT",
      "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"
    },
    {
      "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B",
      "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"
    }
  ]
}

§ Entry Hash Generation Input

The first item in the entry hashing input for Version 1 of the DIDDoc is SCID of the DID. The fifth item, containing the first version DIDDoc content is the full DIDDoc (as indicated by the value item).

[
  "4c99uuenu8gk6n3bgf09fuf350gx",
  1,
  "2024-04-15T19:56:18Z",
  {
    "method": "did:tdw:1",
    "scid": "4c99uuenu8gk6n3bgf09fuf350gx"
  },
  {
    "value": {
      "@context": [
        "https://www.w3.org/ns/did/v1",
        "https://w3id.org/security/multikey/v1"
      ],
      "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "authentication": [
        "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT"
      ],
      "assertionMethod": [
        "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B"
      ],
      "verificationMethod": [
        {
          "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT",
          "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
          "type": "Multikey",
          "publicKeyMultibase": "z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"
        },
        {
          "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B",
          "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
          "type": "Multikey",
          "publicKeyMultibase": "z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"
        }
      ]
    }
  }
]

§ First Log Entry

The following is the JSON prettified version of the entry log file that is published as the did.jsonl file. When published, all extraneous whitespace is removed, as shown in the block below the pretty-printed version.

[
  "4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g",
  1,
  "2024-04-15T19:56:18Z",
  {
    "method": "did:tdw:1",
    "scid": "4c99uuenu8gk6n3bgf09fuf350gx"
  },
  {
    "value": {
      "@context": [
        "https://www.w3.org/ns/did/v1",
        "https://w3id.org/security/multikey/v1"
      ],
      "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "authentication": [
        "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT"
      ],
      "assertionMethod": [
        "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B"
      ],
      "verificationMethod": [
        {
          "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT",
          "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
          "type": "Multikey",
          "publicKeyMultibase": "z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"
        },
        {
          "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B",
          "controller": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
          "type": "Multikey",
          "publicKeyMultibase": "z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"
        }
      ]
    }
  },
  [
    {
      "type": "DataIntegrityProof",
      "cryptosuite": "eddsa-jcs-2022",
      "verificationMethod": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT",
      "created": "2024-04-15T19:56:18Z",
      "proofPurpose": "authentication",
      "challenge": "4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g",
      "proofValue": "z4vP3KptRsxFcjpatqHNpywvwV5AfmAYhkHsMbF8K1gKqRA7WZuoyLheF9tabMu2HCXPnvNEKijfMqpRqkfKZRAHi"
    }
  ]
]

The same content as it is found in the did.jsonl file:

["4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g",1,"2024-04-15T19:56:18Z",{"method":"did:tdw:1","scid":"4c99uuenu8gk6n3bgf09fuf350gx"},{"value":{"@context":["https://www.w3.org/ns/did/v1","https://w3id.org/security/multikey/v1"],"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","authentication":["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT"],"assertionMethod":["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B"],"verificationMethod":[{"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","type":"Multikey","publicKeyMultibase":"z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"},{"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","type":"Multikey","publicKeyMultibase":"z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"}]}},[{"type":"DataIntegrityProof","cryptosuite":"eddsa-jcs-2022","verificationMethod":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","created":"2024-04-15T19:56:18Z","proofPurpose":"authentication","challenge":"4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g","proofValue":"z4vP3KptRsxFcjpatqHNpywvwV5AfmAYhkHsMbF8K1gKqRA7WZuoyLheF9tabMu2HCXPnvNEKijfMqpRqkfKZRAHi"}]]

§ did:web Version of DIDDoc

As noted in the publishing a parallel did:web DID section of this specification, here is what the did:web DIDDoc looks like for the did:tdw above.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1"
  ],
  "id": "did:web:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
  "controller": "did:web:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
  "alsoKnownAs": ["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx"],
  "authentication": [
    "did:web:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT"
  ],
  "assertionMethod": [
    "did:web:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B"
  ],
  "verificationMethod": [
    {
      "id": "did:web:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT",
      "controller": "did:web:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"
    },
    {
      "id": "did:web:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B",
      "controller": "did:web:example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"
    }
  ]
}

§ Version 2 of the DIDDoc

Time passes, and the DID Controller of the did:tdw DID decides to update its DID to a new version, version 2.

§ Target Version 2 DIDDoc

The DID Controller constructs the new target DIDDoc (below) in preparation for passing it into the process to Update the did:tdw DID.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1",
    "https://identity.foundation/linked-vp/contexts/v1"
  ],
  "id": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx",
  "controller": [
    "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"
  ],
  "authentication": [
    "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3"
  ],
  "assertionMethod": [
    "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#gJqvqaYD"
  ],
  "verificationMethod": [
    {
      "id": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3",
      "controller": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6MkuocstfAaHsJgRnQgfQdtJiECuWEMDAbQV61aCpsUrTh3"
    },
    {
      "id": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#gJqvqaYD",
      "controller": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6MksNvDtgMutKMzjezRqj8JbYuCHNjHR5HBaF2ogJqvqaYD"
    }
  ],
  "service": [
    {
      "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#whois",
      "type": "LinkedVerifiablePresentation",
      "serviceEndpoint": [
        "https://example.com/docs/4c99uuenu8gk6n3bgf09fuf350gx/whois.json"
      ]
    }
  ]
}

§ Version 2 Entry Hashing Input

The first item in the entry hashing input for Version 2 of the DIDDoc is the entry hash generated for the Version 1 of the DIDDoc. The fifth item, containing the new version DIDDoc content is in the form of a [RFC6902] JSON Patch (as indicated by the patch item), and are the set of operations to transition the DIDDoc from version 1 to this new version 2 DIDDoc.

[
  "53vtcxfvmvwfzyfw4b9cjeygccwbhm8j1v90by5k66jt4ahbhu50",
  2,
  "2024-04-15T19:56:18Z",
  {},
  {
    "patch": [
      {
        "op": "replace",
        "path": "/verificationMethod/1/publicKeyMultibase",
        "value": "z6MksNvDtgMutKMzjezRqj8JbYuCHNjHR5HBaF2ogJqvqaYD"
      },
      {
        "op": "replace",
        "path": "/verificationMethod/1/controller",
        "value": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"
      },
      {
        "op": "replace",
        "path": "/verificationMethod/1/id",
        "value": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#gJqvqaYD"
      },
      {
        "op": "replace",
        "path": "/verificationMethod/0/publicKeyMultibase",
        "value": "z6MkuocstfAaHsJgRnQgfQdtJiECuWEMDAbQV61aCpsUrTh3"
      },
      {
        "op": "replace",
        "path": "/verificationMethod/0/controller",
        "value": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"
      },
      {
        "op": "replace",
        "path": "/verificationMethod/0/id",
        "value": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3"
      },
      {
        "op": "replace",
        "path": "/assertionMethod/0",
        "value": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#gJqvqaYD"
      },
      {
        "op": "replace",
        "path": "/authentication/0",
        "value": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3"
      },
      {
        "op": "replace",
        "path": "/controller",
        "value": [
          "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"
        ]
      },
      {
        "op": "replace",
        "path": "/id",
        "value": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"
      },
      {
        "op": "add",
        "path": "/@context/2",
        "value": "https://identity.foundation/linked-vp/contexts/v1"
      },
      {
        "op": "add",
        "path": "/service",
        "value": [
          {
            "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#whois",
            "type": "LinkedVerifiablePresentation",
            "serviceEndpoint": [
              "https://example.com/docs/4c99uuenu8gk6n3bgf09fuf350gx/whois.json"
            ]
          }
        ]
      }
    ]
  }
]

§ Log File For Version 2

The new version 2 did.jsonl file contains two entries, one for each version of the DIDDoc. The data integrity proof on the version 2 entry MUST be from an authentication key from the version 1 DIDDoc.

["4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g",1,"2024-04-15T19:56:18Z",{"method":"did:tdw:1","scid":"4c99uuenu8gk6n3bgf09fuf350gx"},{"value":{"@context":["https://www.w3.org/ns/did/v1","https://w3id.org/security/multikey/v1"],"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","authentication":["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT"],"assertionMethod":["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B"],"verificationMethod":[{"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","type":"Multikey","publicKeyMultibase":"z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"},{"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","type":"Multikey","publicKeyMultibase":"z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"}]}},[{"type":"DataIntegrityProof","cryptosuite":"eddsa-jcs-2022","verificationMethod":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","created":"2024-04-15T19:56:18Z","proofPurpose":"authentication","challenge":"4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g","proofValue":"z4vP3KptRsxFcjpatqHNpywvwV5AfmAYhkHsMbF8K1gKqRA7WZuoyLheF9tabMu2HCXPnvNEKijfMqpRqkfKZRAHi"}]]
["53vtcxfvmvwfzyfw4b9cjeygccwbhm8j1v90by5k66jt4ahbhu50",2,"2024-04-15T19:56:18Z",{},{"patch":[{"op":"replace","path":"/verificationMethod/1/publicKeyMultibase","value":"z6MksNvDtgMutKMzjezRqj8JbYuCHNjHR5HBaF2ogJqvqaYD"},{"op":"replace","path":"/verificationMethod/1/controller","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"},{"op":"replace","path":"/verificationMethod/1/id","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#gJqvqaYD"},{"op":"replace","path":"/verificationMethod/0/publicKeyMultibase","value":"z6MkuocstfAaHsJgRnQgfQdtJiECuWEMDAbQV61aCpsUrTh3"},{"op":"replace","path":"/verificationMethod/0/controller","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"},{"op":"replace","path":"/verificationMethod/0/id","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3"},{"op":"replace","path":"/assertionMethod/0","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#gJqvqaYD"},{"op":"replace","path":"/authentication/0","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3"},{"op":"replace","path":"/controller","value":["did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"]},{"op":"replace","path":"/id","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"},{"op":"add","path":"/@context/2","value":"https://identity.foundation/linked-vp/contexts/v1"},{"op":"add","path":"/service","value":[{"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#whois","type":"LinkedVerifiablePresentation","serviceEndpoint":["https://example.com/docs/4c99uuenu8gk6n3bgf09fuf350gx/whois.json"]}]}]},[{"type":"DataIntegrityProof","cryptosuite":"eddsa-jcs-2022","verificationMethod":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","created":"2024-04-15T19:56:18Z","proofPurpose":"authentication","challenge":"53vtcxfvmvwfzyfw4b9cjeygccwbhm8j1v90by5k66jt4ahbhu50","proofValue":"z47viJruDDnAfpL6Zo3bowUB9Eumx1w7Qa8UwH6K1Df1Db6pExBMRvzdy9YgL452t3v5FmrKAnDGF7aQYgtG7bbga"}]]

§ Version 3

§ Version 3 Target DIDDoc

Here is the target update for the version 3 DIDDoc, as constructed by the DID Controller. It is the data used as input to the did:tdw log entry generation process.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/multikey/v1",
    "https://identity.foundation/linked-vp/contexts/v1",
    "https://didcomm.org/messaging/v2"
  ],
  "id": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx",
  "controller": [
    "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"
  ],
  "authentication": [
    "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CZSeAWLE"
  ],
  "assertionMethod": [
    "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#9vYyiXiJ"
  ],
  "keyAgreement": [
    "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#qnYZ6fWH"
  ],
  "verificationMethod": [
    {
      "id": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CZSeAWLE",
      "controller": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6Mkq7Qoa2LCvLCUiq9W2J9vXH1ooDqSX2ehWGUzCZSeAWLE"
    },
    {
      "id": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#9vYyiXiJ",
      "controller": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6Mkr2D4ixckmQx8tAVvXEhMuaMhzahxe61qJt7G9vYyiXiJ"
    },
    {
      "id": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#qnYZ6fWH",
      "controller": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx",
      "type": "Multikey",
      "publicKeyMultibase": "z6LSdYjdAE7ZY1Gh5VPAxDJdgbg45Lq6im3N9o6HqnYZ6fWH"
    }
  ],
  "service": [
    {
      "id": "did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#whois",
      "type": "LinkedVerifiablePresentation",
      "serviceEndpoint": [
        "https://example.com/docs/4c99uuenu8gk6n3bgf09fuf350gx/whois.json"
      ]
    },
    {
      "id": "did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#didcomm",
      "type": "DIDCommMessaging",
      "serviceEndpoint": {
        "uri": "https://example.com/didcomm",
        "accept": [
          "didcomm/v2",
          "didcomm/aip2;env=rfc587"
        ],
        "routingKeys": [
          "did:example:somemediator#somekey"
        ]
      }
    }
  ]
}

§ Log File For Version 3

The new version 3 did.jsonl file contains three entries, one for each version of the DIDDoc. The data integrity proof on the version 3 entry MUST be from an authentication key from the version 2 DIDDoc.

["4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g",1,"2024-04-15T19:56:18Z",{"method":"did:tdw:1","scid":"4c99uuenu8gk6n3bgf09fuf350gx"},{"value":{"@context":["https://www.w3.org/ns/did/v1","https://w3id.org/security/multikey/v1"],"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","authentication":["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT"],"assertionMethod":["did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B"],"verificationMethod":[{"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","type":"Multikey","publicKeyMultibase":"z6Mksta2t7db1WSx2JBorfYFcJnaJMBKUyupD2qPy4SDXopT"},{"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#5b48Zj6B","controller":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx","type":"Multikey","publicKeyMultibase":"z6Mkw1KSvGWNAwSwWbcpwPgFARX4vKPa1xvcDMsJ5b48Zj6B"}]}},[{"type":"DataIntegrityProof","cryptosuite":"eddsa-jcs-2022","verificationMethod":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","created":"2024-04-15T19:56:18Z","proofPurpose":"authentication","challenge":"4fbja27mgf0bumtbg2b4hbzqc2ux9a9crrqx7w6cfnd97k9u7k5g","proofValue":"z4vP3KptRsxFcjpatqHNpywvwV5AfmAYhkHsMbF8K1gKqRA7WZuoyLheF9tabMu2HCXPnvNEKijfMqpRqkfKZRAHi"}]]
["53vtcxfvmvwfzyfw4b9cjeygccwbhm8j1v90by5k66jt4ahbhu50",2,"2024-04-15T19:56:18Z",{},{"patch":[{"op":"replace","path":"/verificationMethod/1/publicKeyMultibase","value":"z6MksNvDtgMutKMzjezRqj8JbYuCHNjHR5HBaF2ogJqvqaYD"},{"op":"replace","path":"/verificationMethod/1/controller","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"},{"op":"replace","path":"/verificationMethod/1/id","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#gJqvqaYD"},{"op":"replace","path":"/verificationMethod/0/publicKeyMultibase","value":"z6MkuocstfAaHsJgRnQgfQdtJiECuWEMDAbQV61aCpsUrTh3"},{"op":"replace","path":"/verificationMethod/0/controller","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"},{"op":"replace","path":"/verificationMethod/0/id","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3"},{"op":"replace","path":"/assertionMethod/0","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#gJqvqaYD"},{"op":"replace","path":"/authentication/0","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3"},{"op":"replace","path":"/controller","value":["did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"]},{"op":"replace","path":"/id","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx"},{"op":"add","path":"/@context/2","value":"https://identity.foundation/linked-vp/contexts/v1"},{"op":"add","path":"/service","value":[{"id":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#whois","type":"LinkedVerifiablePresentation","serviceEndpoint":["https://example.com/docs/4c99uuenu8gk6n3bgf09fuf350gx/whois.json"]}]}]},[{"type":"DataIntegrityProof","cryptosuite":"eddsa-jcs-2022","verificationMethod":"did:tdw:example.com:4c99uuenu8gk6n3bgf09fuf350gx#y4SDXopT","created":"2024-04-15T19:56:18Z","proofPurpose":"authentication","challenge":"53vtcxfvmvwfzyfw4b9cjeygccwbhm8j1v90by5k66jt4ahbhu50","proofValue":"z47viJruDDnAfpL6Zo3bowUB9Eumx1w7Qa8UwH6K1Df1Db6pExBMRvzdy9YgL452t3v5FmrKAnDGF7aQYgtG7bbga"}]]
["3nxcvupjdbetntt80ggnbxurkrz9bhh93nqega3ek5ex8xpfurb0",3,"2024-04-15T19:56:18Z",{},{"patch":[{"op":"add","path":"/service/1","value":{"id":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#didcomm","type":"DIDCommMessaging","serviceEndpoint":{"uri":"https://example.com/didcomm","accept":["didcomm/v2","didcomm/aip2;env=rfc587"],"routingKeys":["did:example:somemediator#somekey"]}}},{"op":"replace","path":"/verificationMethod/1/publicKeyMultibase","value":"z6Mkr2D4ixckmQx8tAVvXEhMuaMhzahxe61qJt7G9vYyiXiJ"},{"op":"replace","path":"/verificationMethod/1/id","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#9vYyiXiJ"},{"op":"replace","path":"/verificationMethod/0/publicKeyMultibase","value":"z6Mkq7Qoa2LCvLCUiq9W2J9vXH1ooDqSX2ehWGUzCZSeAWLE"},{"op":"replace","path":"/verificationMethod/0/id","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CZSeAWLE"},{"op":"add","path":"/verificationMethod/2","value":{"id":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#qnYZ6fWH","controller":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx","type":"Multikey","publicKeyMultibase":"z6LSdYjdAE7ZY1Gh5VPAxDJdgbg45Lq6im3N9o6HqnYZ6fWH"}},{"op":"replace","path":"/assertionMethod/0","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#9vYyiXiJ"},{"op":"replace","path":"/authentication/0","value":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CZSeAWLE"},{"op":"add","path":"/@context/3","value":"https://didcomm.org/messaging/v2"},{"op":"add","path":"/keyAgreement","value":["did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#qnYZ6fWH"]}]},[{"type":"DataIntegrityProof","cryptosuite":"eddsa-jcs-2022","verificationMethod":"did:tdw:migrated.example.com:4c99uuenu8gk6n3bgf09fuf350gx#CpsUrTh3","created":"2024-04-15T19:56:18Z","proofPurpose":"authentication","challenge":"3nxcvupjdbetntt80ggnbxurkrz9bhh93nqega3ek5ex8xpfurb0","proofValue":"zedM9gUK9KvMLEXLePemFB2W5jBtscHN9WRPcxmkuRanPHsvK76M1mKHUKqJtApcdSsykRZtoHPJLiagJo3KKJsU"}]]

And so on…

§ References

DID-CORE
Decentralized Identifiers (DIDs) v1.0. Manu Sporny; Amy Guy; Markus Sabadello; Drummond Reed; 2022-07-19. Status: REC.
RFC1035
Domain names - implementation and specification. P. Mockapetris; 1987-11. Status: Internet Standard.
RFC1123
Requirements for Internet Hosts - Application and Support. R. Braden, Ed.; 1989-10. Status: Internet Standard.
RFC2181
Clarifications to the DNS Specification. R. Elz; R. Bush; 1997-07. Status: Proposed Standard.
RFC2234
Augmented BNF for Syntax Specifications: ABNF. D. Crocker, Ed.; P. Overell; 1997-11. Status: Proposed Standard.
RFC3912
WHOIS Protocol Specification. L. Daigle; 2004-09. Status: Draft Standard.
RFC3986
Uniform Resource Identifier (URI): Generic Syntax. T. Berners-Lee; R. Fielding; L. Masinter; 2005-01. Status: Internet Standard.
RFC4033
DNS Security Introduction and Requirements. R. Arends; R. Austein; M. Larson; D. Massey; S. Rose; 2005-03. Status: Proposed Standard.
RFC4034
Resource Records for the DNS Security Extensions. R. Arends; R. Austein; M. Larson; D. Massey; S. Rose; 2005-03. Status: Proposed Standard.
RFC4035
Protocol Modifications for the DNS Security Extensions. R. Arends; R. Austein; M. Larson; D. Massey; S. Rose; 2005-03. Status: Proposed Standard.
RFC4634
US Secure Hash Algorithms (SHA and HMAC-SHA). D. Eastlake 3rd; T. Hansen; 2006-07. Status: Informational.
RFC4648
The Base16, Base32, and Base64 Data Encodings. S. Josefsson; 2006-10. Status: Proposed Standard.
RFC5895
Mapping Characters for Internationalized Domain Names in Applications (IDNA) 2008. P. Resnick; P. Hoffman; 2010-09. Status: Informational.
RFC6902
JavaScript Object Notation (JSON) Patch. P. Bryan, Ed.; M. Nottingham, Ed.; 2013-04. Status: Proposed Standard.
RFC8484
DNS Queries over HTTPS (DoH). P. Hoffman; P. McManus; 2018-10. Status: Proposed Standard.
RFC8785
JSON Canonicalization Scheme (JCS). A. Rundgren; B. Jordan; S. Erdtman; 2020-06. Status: Informational.

Table of Contents
undefined