§ The DID DHT Method Specification 1.0

Specification Status: Working Draft

Latest Draft: https://did-dht.com

Registry: https://did-dht.com/registry

Draft Created: October 20, 2023

Latest Update: April 22, 2024

Editors:
Gabe Cohen
Daniel Buchner
Contributors:
Moe Jangda
Frank Hinek
Participate:
GitHub repo
File a bug
Commit history

§ Abstract

A DID Method [DID-CORE] based on DNS Resource Records and Mainline DHT, identified by the prefix did:dht.

DID DHT
DNS RRs
Mainline DHT

DID DHT makes use of Mainline DHT, specifically BEP44 to store signed mutable records. This DID method uses DNS Resource Records to efficiently represent DID Documents.

Mainline is in use for the following reasons:

  1. It has a proven track record of 15 years.
  2. It is the biggest DHT in existence with an estimated 10 million servers.
  3. It is fairly generous in retaining data.
  4. It has been implemented in most languages and is stable.

The syntax of the identifier and accompanying data model used by the protocol is conformant with the [DID-CORE] specification and shall be registered with the [DID-SPEC-REGISTRIES].

§ Conformance

The keywords MAY, MUST, MUST NOT, RECOMMENDED, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

§ Terminology

Decentralized Identifier
A W3C specification describing an identifier that enables verifiable, decentralized digital identity. A DID identifier is associated with a JSON document containing cryptographic keys, services, and other properties outlined in the specification.
DID Suffix
The unique identifier string within a DID URI. For DID DHT the suffix is the z-base-32 encoded Identity Key.
Identity Key
An Identity Key is a z-base-32 encoded Ed25519 public key required to authenticate all records in Mainline DHT. The encoded string comprises the Suffix of did:dht identifier. This key is guaranteed to be present in each did:dht document.
DID DHT Service
A service that provides a Mainline interface, extended to support this DID method.
DNS Resource Records
An efficient format for representing DID Documents and providing semantics pertinent to DID DHT, such as TTLs, caching, and different record types (e.g. NS, TXT). Follows [RFC1035].
Mainline DHT
Mainline DHT is the name given to the Distributed Hash Table used by the BitTorrent protocol. It is a distributed system for storing and finding data on a peer-to-peer network. It is based on Kademlia and is primarily used to store and retrieve peer data. It is estimated to consistently have tens of millions of concurrent active users.
Gateway
A server that that facilitates DID DHT operations. The gateway may offer a set of APIs to interact with the DID DHT method features such as providing guaranteed retention, historical resolution, and other features. Gateways can make themselves discoverable via a Gateway Registry.
Gateway Registry
A system used to aid in the discovery of Gateways. One such system is the registry provided by this specification.
Client
A client is a piece of software that is responsible for generating a did:dht and submitting it to a Mainline Server or Gateway. Notably, a client has the ability to sign messages with the Identity Key.
Retained DID Set
The set of DIDs that a Gateway is retaining and thus is responsible for republishing.
Retention Proof
A proof of work that is performed by the DID controller to prove that they are still in control of the DID. Gateways use this proof to determine how long they should retain a DID.
Sequence Number
A sequence number, or seq, is a property of a mutable item as defined in BEP44. It is a 64-bit integer that increases in a consistent, unidirectional manner, ensuring that items are ordered sequentially. This specification requires that sequence numbers are Unix Timestamps represented in seconds.
Unix Timestamp
A value that measures time by the number of non-leap seconds that have elapsed since 00:00:00 UTC on 1 January 1970, the Unix epoch.

§ DID DHT Method Specification

§ Format

The format for did:dht conforms to the [DID-CORE] specification. It consists of the did:dht prefix followed by the Mainline identifier. The Mainline identifier is a z-base-32-encoded Ed25519 public key, which we refer to as an Identity Key.

did-dht-format := did:dht:<z-base-32-value>
z-base-32-value := [a-km-uw-z13-9]+

Alternatively, one can interpret the encoding rules as a series of transformation functions on the raw public key bytes:

did-dht-format := did:dht:Z-BASE-32(raw-public-key-bytes)

§ Identity Key

A unique property of DID DHT is its dependence on an a single non-rotatable key which we refer to as an Identity Key. This requirement stems from BEP44, particularly within the Mutable Items section:

Mutable items can be updated, without changing their DHT keys. To authenticate that only the original publisher can update an item, it is signed by a private key generated by the original publisher. The target ID mutable items are stored under is the SHA-1 hash of the public key (as it appears in the put message).

This mechanism, as detailed in BEP44, ensures that all entries in the DHT are authenticated through a private key unique to the initial publisher. Consequently, DHT records, including DID DHT Documents, are independently verifiable. This independence implies that trust in a specific Mainline or Gateway server for providing unaltered messages is unnecessary. Instead, all clients can, and should, verify messages themselves. This approach significantly mitigates risks associated with other DID methods, where a compromised server or DID resolver might tamper with a DID Document which would be undetectable by a client.

Currently, Mainline exclusively supports the Ed25519 key type. In turn, Ed25519 is required by DID DHT and is used to uniquely identify DID DHT Documents. DID DHT identifiers are formed by concatenating the did:dht: prefix with a z-base-32 encoded Identity Key, which acts as its suffix. Identity Keys MUST have the identifier 0 as both its Verification Method id and JWK kid [RFC7517]. Identity Keys MUST have the Verification Relationships Authentication, Assertion, Capability Invocation, and Capability Delegation.

While the system requires at least one Ed25519, a DID DHT Document can include any number of additional keys. Additional key types MUST be registered in the Key Type Index.

As a unique consequence of the requirement of the Identity Key, DID DHT Documents are able to be partially-resolved without contacting Mainline or Gateway servers, though it is RECOMMENDED that deterministic resolution is only used as a fallback mechanism. Similarly, the requirement of an Identity Key enables interoperability with other DID methods.

§ DIDs as DNS Records

In this scheme, we encode the DID Document as DNS Resource Records. These resource records make up a DNS packet [RFC1034] [RFC1035], which is then stored in the DHT.

Name Type TTL Rdata
_did.<ID>. TXT 7200 v=0;vm=k0,k1,k2;auth=k0;asm=k1;inv=k2;del=k2;srv=s0,s1,s2
_k0._did. TXT 7200 id=0;t=0;k=<unpadded-b64url>
_k1._did. TXT 7200 id=1;t=1;k=<unpadded-b64url>
_k2._did. TXT 7200 id=2;t=1;k=<unpadded-b64url>
_s0._did. TXT 7200 id=domain;t=LinkedDomains;se=https://foo.com
_s1._did. TXT 7200 id=dwn;t=DecentralizedWebNode;se=https://dwn.tbddev.org/dwn5
NOTE

The recommended TTL value is 7200 seconds (2 hours), the default TTL for Mainline records.

§ Root Record

The root record is a special record which serves as instructions on how to reconstruct a DID Document, by providing a property mapping for a DID Document, along with containing pertinent metadata such as a version identifier.

Additionally:

Example Root Record

Name Type TTL Rdata
_did.o4dksfbqk85ogzdb5osziw6befigbuxmuxkuxq8434q89uj56uyy. TXT 7200 v=0;vm=k0,k1,k2;auth=k0;asm=k1;inv=k2;del=k2;srv=s0,s1,s2

§ Property Mapping

The following section describes mapping a DID Document to a DNS packet’s rdata.

The subsequent instructions serve as a reference for mapping DID Document properties to DNS Resource Records:

§ Identifiers

§ Controller

A DID controller MAY be present in a did:dht document.

To ensure that the DID controller is authorized to make changes to the DID Document, the controller for the Identity Key Verification Method MUST be contained within the controller property.

Example Controller Record

Name Type TTL Rdata
_cnt._did. TXT 7200 did:example:abcd
§ Also Known As

A did:dht document MAY have multiple identifiers using the alsoKnownAs property.

Example AKA Record

Name Type TTL Rdata
_aka._did. TXT 7200 did:example:efgh,did:example:ijkl

§ Verification Methods

NOTE

Controllers are not cryptographically verified by Gateways or this DID method. This means any DID may choose to list a controller, even if there is no relationship between the identifiers. As such, DID controllers should be interrogated to assert the veracity of their relations.

§ Verification Relationships

The following table acts as a map between Verification Relationship types and their record name:

§ Verification Relationship Index
Verification Relationship Record Name
Authentication auth
Assertion asm
Key Agreement agm
Capability Invocation inv
Capability Delegation del

The record data is uniform across Verification Relationships, represented as a comma-separated list of key references.

Example Verification Relationship Records

Verification Relationship Rdata in the Root Record
“authentication”: [“did:dht:example#0”, “did:dht:example#HTsY9aMkoDomPBhGcUxSOGP40F-W4Q9XCJV1ab8anTQ”] auth=0,HTsY9aMkoDomPBhGcUxSOGP40F-W4Q9XCJV1ab8anTQ
“assertionMethod”: [“did:dht:example#0”, “did:dht:example#HTsY9aMkoDomPBhGcUxSOGP40F-W4Q9XCJV1ab8anTQ”] asm=0,HTsY9aMkoDomPBhGcUxSOGP40F-W4Q9XCJV1ab8anTQ
“keyAgreement”: [“did:dht:example#1”] agm=1
“capabilityInvocation”: [“did:dht:example#0”] inv=0
“capabilityDelegation”: [“did:dht:example#0”] del=0

§ Services

Example Service Record

Name Type TTL Rdata
_s0._did. TXT 7200 id=dwn;t=DecentralizedWebNode;se=https://example.com/dwn

Each Service is represented as part of the root record (_did.<ID>.) as a list under the key srv=<ids> where ids is a comma-separated list of all IDs for each Service.

§ Example

A sample transformation of a fully-featured DID Document to a DNS packet is exemplified as follows:

DID Document

{
  "id": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y",
  "controller": "did:example:abcd",
  "alsoKnownAs": ["did:example:efgh", "did:example:ijkl"],
  "verificationMethod": [
    {
      "id": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#0",
      "type": "JsonWebKey",
      "controller": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y",
      "publicKeyJwk": {
        "kid": "0",
        "alg": "Ed25519",
        "crv": "Ed25519",
        "kty": "OKP",
        "x": "r96mnGNgWGOmjt6g_3_0nd4Kls5-kknrd4DdPW8qtfw"
      }
    },
    {
      "id": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#HTsY9aMkoDomPBhGcUxSOGP40F-W4Q9XCJV1ab8anTQ",
      "type": "JsonWebKey",
      "controller": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y",
      "publicKeyJwk": {
        "kid": "HTsY9aMkoDomPBhGcUxSOGP40F-W4Q9XCJV1ab8anTQ",
        "alg": "ES256K",
        "crv": "secp256k1",
        "kty": "EC",
        "x": "KI0DPvL5cGvznc8EDOAA5T9zQfLDQZvr0ev2NMLcxDw",
        "y": "0iSbXxZo0jIFLtW8vVnoWd8tEzUV2o22BVc_IjVTIt8"
      }
    }
  ],
  "authentication": [
    "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#0",
    "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#HTsY9aMkoDomPBhGcUxSOGP40F-W4Q9XCJV1ab8anTQ"
  ],
  "assertionMethod": [
    "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#0",
    "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#HTsY9aMkoDomPBhGcUxSOGP40F-W4Q9XCJV1ab8anTQ"
  ],
  "capabilityInvocation": [
    "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#0"
  ],
  "capabilityDelegation": [
    "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#0"
  ],
  "service": [
    {
      "id": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#dwn",
      "type": "DecentralizedWebNode",
      "serviceEndpoint": ["https://example.com/dwn1", "https://example/dwn2"]
    }
  ]
}

DNS Resource Records

Name Type TTL Rdata
_did.<ID>. TXT 7200 v=0;vm=k0,k1;auth=k0,k1;asm=k0,k1;inv=k0;del=k0;srv=s1
_cnt.did. TXT 7200 did:example:abcd
_aka.did. TXT 7200 did:example:efgh,did:example:ijkl
_k0._did. TXT 7200 t=0;k=afdea69c63605863a68edea0ff7ff49dde0a96ce7e9249eb7780dd3d6f2ab5fc;a=Ed25519
_k1._did. TXT 7200 t=1;k=AyiNAz7y-XBr853PBAzgAOU_c0Hyw0Gb69Hr9jTC3MQ8
_s0._did. TXT 7200 id=dwn;t=DecentralizedWebNode;se=https://example.com/dwn1,https://example.com/dwn2

§ Operations

Entries to the DHT require a signed record as per BEP44. As such, the keypair used for the Mainline identifier is also used to sign the DHT record.

§ Create

To create a did:dht, the process is as follows:

  1. Generate an Ed25519 keypair and encode the public key using the format provided in the format section.

  2. Construct a conformant JSON representation of a DID Document.

    a. The document MUST include a Verification Method with the Identity Key encoded as a publicKeyJwk as per [RFC7517] with an id of 0 and type of JsonWebKey defined by VC-JOSE-COSE.

    b. The document can include any number of other core properties; always representing key material as a JWK as per [RFC7517]. In addition to the properties required by the JWK specification, the alg property MUST always be present. Default algorithms are defined per key type in the indexed types registry.

  3. Map the output DID Document to a DNS packet as outlined in property mapping.

  4. Compress the DNS packet as per [RFC1035] section 4.1.4.

  5. Construct a BEP44 conformant mutable put message.

    a. v MUST be set to a bencoded compressed DNS packet from the prior step.

    b. seq MUST be set to the current Unix Timestamp in seconds.

  6. Submit the result of to the DHT via a Mainline node, or a Gateway, with the identifier created in step 1.

NOTE

This specification does not make use of JSON-LD. As such DID DHT Documents MUST NOT include the @context property.

§ Read

To read a did:dht, the process is as follows:

  1. Take the suffix of the DID, that is, the z-base-32 encoded identifier key, and submit it to a Mainline node or a Gateway.

  2. Decode the resulting BEP44 response’s v value using bencode.

  3. Uncompress the DNS packet according to [RFC1035] section 4.1.4.

  4. Reverse the DNS property mapping process and re-construct a conformant DID Document.

    a. Expand all identifiers (i.e. Verification Methods, Services, etc.) to their fully-qualified form (e.g. did:dht:uodqi99wuzxsz6yx445zxkp8ddwj9q54ocbcg8yifsqru45x63kj#0 as opposed to 0 or #0, did:dht:uodqi99wuzxsz6yx445zxkp8ddwj9q54ocbcg8yifsqru45x63kj#service-1 as opposed to #service-1).

  5. If NS records are present this process should be repeated, making the initial request against the given Gateway. The document with the highest sequence number is to be treated as authoritative.

NOTE

As a fallback, if a did:dht value cannot be resolved via the network, it can be expanded to a conformant DID Document containing just the Identity Key.

§ Update

Any valid BEP44 record written to the DHT is an update. As long as control of the Identity Key is retained any update is made possibly by signing and writing records with a unique incremental sequence number with mutable items.

It is RECOMMENDED that updates are infrequent, as caching of the DHT is highly encouraged.

§ Deactivate

To deactivate a DID Document, there are a couple options:

  1. Let the DHT record expire and cease to publish it.

  2. Publish a new DHT record where the rdata of the root DNS record is the string “deactivated.”

Name Type TTL Rdata
_did.<ID>. TXT 7200 deactivated
NOTE

If you have published your DID through a Gateway, you may need to contact the operator to have them remove the record from their Retained DID Set.

TODO

Add guidance for rotating to a new DID after deactivation.

§ Designating Authoritative Gateways

Gateways provide additional benefits to did:dht, such as the ability to resolve historical DID Documents, or support type indexing. To enable the usage of these additional features, did:dht documents need to be published to Gateway(s) that with the necessary capabilities. Whether it’s accessing historical states, engaging with type indexes, or utilizing other specialized features, the resolution process must be directed towards a Gateway that maintains this supplementary data.

To facilitate the discovery of authoritative Gateways for a did:dht and to ensure consistent access to a DID’s state across different Gateways, DID controllers may designate one or more Gateways as authoritative sources for their DID. This designation is accomplished by incorporating DNS NS records within the DNS packet destined for storage in the DHT. A DID MAY have multiple NS records, enhancing redundancy and reliability. The format for these records is outlined as follows:

Name Type TTL Rdata
_did.<ID>. NS 7200 gateway1.example-did-dht-gateway.com.
_did.<ID>. NS 7200 gateway2.example-did-dht-gateway.com.

§ Type Indexing

Type indexing is an OPTIONAL feature that enables DIDs to become discoverable, by flagging themselves as being of a particular type. Types are not included as a part of the DID Document, but rather as part of the DNS packet. This allows for DIDs to be indexed by type by Gateways, and for DIDs to be resolved by type.

DIDs can be indexed by type by adding a _typ._did. record to the DNS packet. A DID MAY have AT MOST one type index record. This record is of the following format:

Example Type Index Record

Name Type TTL Rdata
_typ._did. TXT 7200 id=0,1,2

Types can be found and registered in the indexed types registry.

NOTE

Identifying entities through type-based indexing is a relatively unreliable practice. It serves as an initial step in recognizing the identity linked to a DID. To validate identity assertions more robustly, it is essential to delve deeper, employing tools like verifiable credentials and the examination of related data.

§ Gateways

Gateways serve as specialized servers, providing a range of DID-centric functionalities that extend beyond the capabilities of a standard Mainline DHT servers. This section elaborates on these unique features, outlines the operational prerequisites for managing a gateway, and discusses various other facets, including the optional integration of these gateways into a registry system.

NOTE

Gateways may choose to support interoperable methods in addition to did:dht as outlined in the section on interoperability.

§ Discovering Gateways

As an OPTIONAL feature of the DID DHT Method, operators of a Gateway may choose to make their server discoverable through a Gateway Registry. This feature allows for easy location through various internet-based discovery mechanisms. Gateway Registries can vary in nature, encompassing a spectrum from centrally managed directories to diverse decentralized systems including databases, ledgers, or other structures.

One such registry is provided by this specification.

§ Retained DID Set

A Retained DID Set refers to the set of DIDs a Gateway retains and republishes to the DHT. A Gateway may choose to surface additional APIs based on this set, such as providing a type index.

To safeguard equitable access to the resources of Gateways, which are publicly accessible and potentially subject to a high volume of requests, we suggest an OPTIONAL mechanism aimed at upholding fairness in the retention and republishing of record sets by Gateways. This mechanism, referred to as a Retention Proof, requires clients to generate a proof value for write requests. This process guarantees that the amount of work done by a client is proportional to the duration of data retention and republishing a Gateway performs. This mechanism enhances the overall reliability and effectiveness of Gateways in managing requests.

§ Generating a Retention Proof

A Retention Proof is a form of Proof of Work performed over a DID identifier concatenated with the retention value of a given DID operation. The retention value is composed of a hash value specified by the gateway, and a random nonce using the SHA-256 hashing algorithm. The resulting Retention Proof Hash is used to determine the retention duration based on the number of leading zeros of the hash, referred to as the difficulty, which MUST be no less than 26 bits of the 256-bit hash value. The algorithm, in detail, is as follows:

  1. Obtain a DID identifier and set it to DID.

  2. Get the difficulty and recent hash from the server set to DIFFICULTY and HASH, respectively.

  3. Generate a random 32-bit integer nonce value set to NONCE.

  4. Compute the SHA-256 hash over ATTEMPT where ATTEMPT = (DID + HASH + NONCE).

  5. Inspect the result of ATTEMPT, and ensure it has >= DIFFICULTY bits of leading zeroes.

a. If so, ATTEMPT = RETENTION_PROOF.

b. Otherwise, regenerate NONCE and go to step 3.

  1. Submit the RETENTION_PROOF to the Gateway API.

§ Managing the Retained DID Set

Gateways adhering to the Retention Set rules SHOULD sort DIDs they are retaining by the number of leading 0s in their Retention Proofs in descending order, followed by the block hash’s index number in descending order. When a Gateway needs to reduce its retained set of DID entries, it SHOULD remove entries from the bottom of the list following this sort.

§ Reporting on Retention Status

Gateways MUST include the approximate time until retention fall-off in the DID Resolution Metadata of a resolved DID Document, to aid clients in being able to assess whether resubmission is required.

TODO

Specify how gateways can report on retention guarantees and provide guidance for clients to work with these guarantees.

§ Gateway API

At a minimum, a Gateway MUST support the Relay API inspired by Pkarr, which is specified in the subsequent section.

Expanding on this API, a fully conformant Gateway MUST support the following API, which is made available via an OpenAPI document.

§ Relay

Public relays will need to set up Cross-origin resource sharing (CORS) headers as follows:

§ Put

On receiving a PUT request the server verifiers the sig and submits a mutable put to Mainline as per BEP44.

§ Get

On receiving a GET request the server submits a mutable get query to Mainline as per BEP44.

§ Get the Current Difficulty

Difficulty is exposed as an OPTIONAL endpoint based on support of retention proofs.

{
  "hash": "000000000000000000022be0c55caae4152d023dd57e8d63dc1a55c1f6de46e7",
  "difficulty": 26
}

§ Register or Update a DID

{
  "did": "did:dht:example",
  "sig": "<unpadded-base64URL-encoded-signature>",
  "seq": 1234,
  "v": "<unpadded-base64URL-encoded bencoded DNS packet>"
}

Upon receiving a request to register a DID, the Gateway MUST verify the signature of the request and if valid publish the DID Document to the DHT. If the DNS Packets contain a _typ._did. record, the Gateway MUST index the DID by its type.

§ Resolving a DID

{
  "did": {
    "id": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y",
    "verificationMethod": [
      {
        "id": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#0",
        "type": "JsonWebKey",
        "controller": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y",
        "publicKeyJwk": {
          "kid": "0",
          "alg": "Ed25519",
          "crv": "Ed25519",
          "kty": "OKP",
          "x": "r96mnGNgWGOmjt6g_3_0nd4Kls5-kknrd4DdPW8qtfw"
        }
      }
    ],
    "authentication": [
      "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#0"
    ],
    "assertionMethod": [
      "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y#0"
    ]
  },
  "dht": "<unpadded-base64URL-encoded bep44 payload as [sig][seq][v]>",
  "types": [1, 4],
  "sequence_numbers": [1700356854, 1700461736]
}

Upon receiving a request to resolve a DID, the Gateway MUST query the DHT for the DID Document, and if found, return the document. If the records are not found in the DHT, the Gateway MAY fall back to its local storage. If the DNS Packets contain a _typ._did. record, the Gateway MUST return the type index.

This API is returns a dht property which matches the payload of a Relay GET Request, when encoded as an unpadded base64URL string. Implementers are RECOMMENDED to verify the integrity of the response using the dht data and reconstruct the DID Document themselves. The did property is provided as a utility which, without independent verification, SHOULD NOT be trusted.

§ Historical Resolution

Gateways MAY choose to support historical resolution, which is to surface different versions of the same DID Document, sorted by sequence number, according to the rules set out in the section on conflict resolution.

Upon resolving a DID, the Gateway will return the parameter sequence_numbers if there exists historical state for a given DID. The following API can be used with specific sequence numbers to fetch historical state:

§ Deactivating a DID

To intentionally deactivate a DID, as opposed to letting the record cease being published to the DHT, a DID controller follows the same process as updating a DID, but with a record format outlined in the section on deactivation.

Upon receiving a request to deactivate a DID, the Gateway MUST verify the signature of the request, and if valid, stop republishing the DHT. If the DNS Packets contain a _typ._did. record, the Gateway MUST stop indexing the type(s) for the DID.

§ Type Indexing

Get Info

[
  {
    "type": 1,
    "description": "Organization"
  },
  {
    "type": 7,
    "description": "Financial Institution"
  }
]

Get a Specific Type

[
  "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y",
  "did:dht:uodqi99wuzxsz6yx445zxkp8ddwj9q54ocbcg8yifsqru45x63kj"
]

A query to the type index returns an array of DIDs matching the associated type. If the type is not found, a 404 is returned. If no DIDs match the type, an empty array is returned.

§ Interoperability With Other DID Methods

As an OPTIONAL extension, some existing DID methods can leverage did:dht to expand their feature set. This enhancement is most useful for DID methods that operate based on a single key and are compatible with the Ed25519 key format. By adopting this optional extension, users can maintain their current DIDs without any changes. Additionally, they gain the ability to add extra information to their DIDs. This is achieved by either publishing or retrieving data from Mainline.

Interoperable DID methods MUST be registered in this specification’s registry.

§ Implementation Considerations

§ Conflict Resolution

Per BEP44, Gateway servers can leverage the seq sequence number to handle conflicts:

Gateways receiving a put request where seq is lower than or equal to what’s already stored on the server, MUST reject the request. If the sequence number is equal, and the value is also the same, the server SHOULD reset its timeout counter.

When the sequence number is equal, but the value is different, servers need to decide which value to accept and which to reject. To make this determination Gateways MUST compare the payloads lexicographically to determine a lexicographical order, and reject the payload with a lower lexicographical order.

§ Size Constraints

BEP44 payload sizes are limited to 1000 bytes. Accordingly, we specify an efficient representation of a DID Document and leveraged DNS packet encoding to optimize our payload sizes. With this encoding format, we recommend additional considerations to minimize payload sizes:

§ Representing Keys

The following guidance on representations of keys and their identifiers using the JsonWebKey type defined by VC-JOSE-COSE are REQUIRED:

§ Historical Key State

Rotating keys is a widely recommended security practice. However, if you frequently rotate keys in a DID Document, this can lead to an increase in the document’s size due to the accumulation of old keys. This, in turn, can enlarge the size of the corresponding DNS packet. To manage this issue, while still distinguishing between currently active keys and those that are no longer in use (but were valid in the past), users MAY utilize the service property. This property allows for the specification of services that are dedicated to storing signed records of the historical key states. By doing this, it helps to keep the DID Document more concise.

§ Republishing Data

Mainline offers a limited duration (approximately 2 hours) for retaining records in the DHT. To ensure the verifiability of data signed by a DID, consistent republishing of DID Document records is crucial. To address this, it is RECOMMENDED to use Gateways equipped with Retention Proofs support.

§ Rate Limiting

To reduce the risk of Denial of Service Attacks, spam, and other unwanted traffic, it is RECOMMENDED that Gateways require Retention Proofs. The use of Retention Proofs can act as an attack prevention measure, as it would be costly to scale retention proof calculations. Gateways MAY choose to explore other rate limiting techniques, such as IP-limiting, or an access-token-based approach.

§ DID Resolution

The process for resolving a DID DHT Document via a Gateway is outlined in the read section above. However, we provide additional guidance for DID Resolvers supplying DID Document Metadata and DID Resolution Metadata as follows:

§ DID Document Metadata

§ DID Resolution Metadata

TODO

Register types and gateway in the DID Specification Registry.

§ Security and Privacy Considerations

When implementing and using the did:dht method, there are several security and privacy considerations to be aware of to ensure expected and legitimate behavior.

§ Data Conflicts

Malicious actors may try to force Gateways into uncertain states by manipulating the sequence number associated with a record set. There are three such cases to be aware of:

§ Data Availability

Given the nature of decentralized distributed systems, there are no firm guarantees that all Gateways have access to the same state. It is RECOMMENDED to publish and read from multiple Gateways to reduce such risks. As an optional enhancement Gateways MAY choose to share state amongst themselves via mechanisms such as a gossip protocol.

§ Data Authenticity

To enter into the DHT using BEP44 records MUST be signed by an Ed25519 private key, known as the Identity Key. When retrieving records either through a Mainline Server or a Gateway is it RECOMMENDED that one verifies the cryptographic integrity of the record themselves instead of trusting a server to have done the validation. Servers that do not return a signature value MUST NOT be trusted.

§ Key Compromise

Since the did:dht uses a single, un-rotatable root key, there is a risk of root key compromise. Such a compromise may be tough to detect without external assurances of identity. Implementers are encouraged to be aware of this possibility and devise strategies that support entities transitioning to new DIDs over time.

§ Public Data

Mainline is a public network. As such, there is risk in storing private, sensitive, or personally identifying information (PII) on such a network. Storing such sensitive information on the network or in the contents of a did:dht document is strongly discouraged.

§ Data Retention

It is RECOMMENDED that Gateways implement measures supporting the “Right to be Forgotten,” enabling precise control over the data retention duration.

§ Cryptographic Risk

The security of data within the Mainline DHT which relies on mutable records using Ed25519 keys—is intrinsically tied to the strength of these keys and their underlying algorithms, as outlined in [RFC8032]. Should vulnerabilities be discovered in Ed25519 or if advancements in quantum computing compromise its cryptographic foundations, the Mainline method could become obsolete.

§ Appendix

§ Test Vectors

§ Vector 1

A minimal DID Document.

Identity Public Key JWK:

{
  "kid": "0",
  "alg": "Ed25519",
  "crv": "Ed25519",
  "kty": "OKP",
  "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE"
}

DID Document:

{
  "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
  "verificationMethod": [
    {
      "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
      "type": "JsonWebKey",
      "controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
      "publicKeyJwk": {
        "kid": "0",
        "alg": "Ed25519",
        "crv": "Ed25519",
        "kty": "OKP",
        "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE"
      }
    }
  ],
  "authentication": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "assertionMethod": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "capabilityInvocation": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "capabilityDelegation": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ]
}

DNS Resource Records:

Name Type TTL Rdata
_did.cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo. TXT 7200 v=0;vm=k0;auth=k0;asm=k0;inv=k0;del=k0
_k0._did. TXT 7200 id=0;t=0;k=YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE

§ Vector 2

A DID Document with two keys (Identity Key and an uncompressed secp256k1 key), a service with multiple endpoints, a gateway, two types to index, an aka, and controller properties.

Identity Public Key JWK:

{
  "kid": "0",
  "alg": "Ed25519",
  "crv": "Ed25519",
  "kty": "OKP",
  "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE"
}

secp256k1 Public Key JWK:

With controller: did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y.

{
  "kid": "0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw",
  "alg": "ES256K",
  "crv": "secp256k1",
  "kty": "EC",
  "x": "1_o0IKHGNamet8-3VYNUTiKlhVK-LilcKrhJSPHSNP0",
  "y": "qzU8qqh0wKB6JC_9HCu8pHE-ZPkDpw4AdJ-MsV2InVY"
}

Key Purposes: Assertion Method, Capability Invocation.

Service:

{
  "id": "service-1",
  "type": "TestService",
  "serviceEndpoint": ["https://test-service.com/1", "https://test-service.com/2"]
}

Gateway:: gateway1.example-did-dht-gateway.com..

Types: 1, 2, 3.

DID Document:

{
  "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
  "controller": "did:example:abcd",
  "alsoKnownAs": ["did:example:efgh", "did:example:ijkl"],
  "verificationMethod": [
    {
      "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
      "type": "JsonWebKey",
      "controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
      "publicKeyJwk": {
        "kid": "0",
        "alg": "Ed25519",
        "crv": "Ed25519",
        "kty": "OKP",
        "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE"
      }
    },
    {
      "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw",
      "type": "JsonWebKey",
      "controller": "did:dht:i9xkp8ddcbcg8jwq54ox699wuzxyifsqx4jru45zodqu453ksz6y",
      "publicKeyJwk": {
        "kid": "0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw",
        "alg": "ES256K",
        "crv": "secp256k1",
        "kty": "EC",
        "x": "1_o0IKHGNamet8-3VYNUTiKlhVK-LilcKrhJSPHSNP0",
        "y": "qzU8qqh0wKB6JC_9HCu8pHE-ZPkDpw4AdJ-MsV2InVY"
      }
    }
  ],
  "authentication": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "assertionMethod": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw"
  ],
  "capabilityInvocation": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw"
  ],
  "capabilityDelegation": [
    "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
  ],
  "service": [
    {
      "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#service-1",
      "type": "TestService",
      "serviceEndpoint": ["https://test-service.com/1", "https://test-service.com/2"]
    }
  ]
}

DNS Resource Records:

Name Type TTL Rdata
_did.cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo. NS 7200 gateway1.example-did-dht-gateway.com.
_did.cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo. TXT 7200 v=0;vm=k0,k1;auth=k0;asm=k0,k1;inv=k0,k1;del=k0;svc=s0
_cnt.did. TXT 7200 did:example:abcd
_aka.did. TXT 7200 did:example:efgh,did:example:ijkl
_k0.did. TXT 7200 id=0;t=0;k=YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE;c=did:example:abcd
_k1.did. TXT 7200 t=1;k=Atf6NCChxjWpnrfPt1WDVE4ipYVSvi4pXCq4SUjx0jT9
_s0.did. TXT 7200 id=service-1;t=TestService;se=https://test-service.com/1,https://test-service.com/2
_typ.did. TXT 7200 id=1,2,3

§ Vector 3

A DID Document with two keys – the Identity Key and an X25519 key used with a different alg value than what is specified in the registry. The DID also has two gateway records and a service with an endpoint greater than 255 characters.

Identity Public Key JWK:

{
  "kid": "0",
  "alg": "Ed25519",
  "crv": "Ed25519",
  "kty": "OKP",
  "x": "sTyTLYw-n1NI9X-84NaCuis1wZjAA8lku6f6Et5201g"
}

X25519 Public Key JWK:

{
  "kid": "WVy5IWMa36AoyAXZDvPd5j9zxt2t-GjifDEV-DwgIdQ",
  "alg": "ECDH-ES+A128KW",
  "crv": "X25519",
  "kty": "OKP",
  "x": "3POE0_i2mGeZ2qiQCA3KcLfi1fZo0311CXFSIwt1nB4"
}

Key Purposes: Key Agreement.

Service:

{
  "id": "service-1",
  "type": "TestLongService",
  "serviceEndpoint": ["https://test-lllllllllllllllllllllllllllllllllllooooooooooooooooooooonnnnnnnnnnnnnnnnnnngggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssseeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrvvvvvvvvvvvvvvvvvvvviiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiccccccccccccccccccccccccccccccceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.com/1"]
}

Gateways:: gateway1.example-did-dht-gateway.com., gateway2.example-did-dht-gateway.com..

DID Document:

{
  "id": "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy",
  "verificationMethod": [
    {
      "id": "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy#0",
      "type": "JsonWebKey",
      "controller": "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy",
      "publicKeyJwk": {
        "kid": "0",
        "alg": "Ed25519",
        "crv": "Ed25519",
        "kty": "OKP",
        "x": "sTyTLYw-n1NI9X-84NaCuis1wZjAA8lku6f6Et5201g"
      }
    },
    {
      "id": "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy#WVy5IWMa36AoyAXZDvPd5j9zxt2t-GjifDEV-DwgIdQ",
      "type": "JsonWebKey",
      "controller": "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy",
      "publicKeyJwk": {
        "kid": "WVy5IWMa36AoyAXZDvPd5j9zxt2t-GjifDEV-DwgIdQ",
        "alg": "ECDH-ES+A128KW",
        "crv": "X25519",
        "kty": "OKP",
        "x": "3POE0_i2mGeZ2qiQCA3KcLfi1fZo0311CXFSIwt1nB4"
      }
    }
  ],
  "authentication": [
    "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy#0"
  ],
  "assertionMethod": [
    "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy#0"
  ],
  "keyAgreement": [
    "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy#WVy5IWMa36AoyAXZDvPd5j9zxt2t-GjifDEV-DwgIdQ"
  ],
  "capabilityInvocation": [
    "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy#0"
  ],
  "capabilityDelegation": [
    "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy#0"
  ],
  "service": [
    {
      "id": "did:dht:sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy#service-1",
      "type": "TestLongService",
      "serviceEndpoint": ["https://test-lllllllllllllllllllllllllllllllllllooooooooooooooooooooonnnnnnnnnnnnnnnnnnngggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssseeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrvvvvvvvvvvvvvvvvvvvviiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiccccccccccccccccccccccccccccccceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.com/1"]
    }
  ]
}

DNS Resource Records:

Name Type TTL Rdata
_did.sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy. NS 7200 gateway1.example-did-dht-gateway.com.
_did.sr6jgmcc84xig18ix66qbiwnzeiumocaaybh13f5w97bfzus4pcy. TXT 7200 v=0;vm=k0,k1;auth=k0;asm=k0;agm=k1;inv=k0;del=k0;svc=s0
_k0.did. TXT 7200 id=0;t=0;k=sTyTLYw-n1NI9X-84NaCuis1wZjAA8lku6f6Et5201g
_k1.did. TXT 7200 id=WVy5IWMa36AoyAXZDvPd5j9zxt2t-GjifDEV-DwgIdQ;t=3;k=3POE0_i2mGeZ2qiQCA3KcLfi1fZo0311CXFSIwt1nB4;a=ECDH-ES+A128KW
_s0.did. TXT 7200 id=service-1;t=TestLongService;se=https://test-lllllllllllllllllllllllllllllllllllooooooooooooooooooooonnnnnnnnnnnnnnnnnnngggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssseeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrvvvvvvvvvvvvvvvvvvvviiiiiiiiiiiiiiii iiiiiiiiiiiiiiiccccccccccccccccccccccccccccccceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee.com/1

§ Open API Definition

openapi: 3.0.1
info:
  title: DID DHT Gateway API
  description: "The [DID DHT API](https://did-dht.com)"
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
  version: v0.1
paths:
  /{id}:
    get:
      tags:
        - DHT
      summary: Get DNS-encoded BEP44 records from the DHT
      description: Get a DNS-encoded BEP44 record set from the DHT
      parameters:
        - name: id
          in: path
          description: ID to get
          required: true
          schema:
            type: string
      responses:
        "200":
          description: "64 bytes sig, 8 bytes u64 big-endian seq, 0-1000 bytes of v."
          content:
            application/octet-stream:
              schema:
                type: array
                items:
                  type: integer
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                type: string
        "404":
          description: Not found
          content:
            application/json:
              schema:
                type: string
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                type: string
    put:
      tags:
        - DHT
      summary: Put DNS-encoded BEP44 records into the DHT
      description: Put a DNS-encoded BEP44 record set into the DHT
      parameters:
        - name: id
          in: path
          description: ID to put
          required: true
          schema:
            type: string
      requestBody:
        description: "64 bytes sig, 8 bytes u64 big-endian seq, 0-1000 bytes of v."
        content:
          application/octet-stream:
            schema:
              type: array
              items:
                type: integer
        required: true
      responses:
        "200":
          description: OK
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                type: string
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                type: string
  /dids/{id}:
    put:
      tags:
        - DID
      summary: Publish a DID
      description: Register or Update a DID in the DHT
      parameters:
        - name: id
          in: path
          description: DID to publish.
          required: true
          schema:
            type: string
      requestBody:
        description: A deconstructed DNS-encoded BEP44 request object
        content:
          application/json:
            schema:
              type: object
              properties:
                sig:
                  type: string
                  description: A base64URL-encoded signature of the BEP44 payload.
                seq:
                  type: integer
                  description: A sequence number for the request, recommended to be a unix timestamp in seconds.
                v:
                  type: string
                  description: A base64URL-encoded bencoded DNS packet containing the DID Document.
                retention_proof:
                  type: string
                  description: A retention proof calculated according to the spec-defined retention proof algorithm.
              required: [ did, sig, seq, v ]
      responses:
        "202":
          description: Accepted. The server has accepted the request as valid and will publish it to the
          content:
            application/json:
              schema:
                type: string
        "400":
          description: Invalid request.
          content:
            application/json:
              schema:
                type: string
        "401":
          description: Invalid signature.
          content:
            application/json:
              schema:
                type: string
        "409":
          description: DID already exists with a higher sequence number. May still be accepted if the Gateway supports historical resolution.
          content:
            application/json:
              schema:
                type: string
    get:
      tags:
        - DID
      summary: Resolve a DID
      description: Resolve a DID from the DHT first, with a fallback to local storage.
      parameters:
        - name: id
          in: path
          description: DID to resolve.
          required: true
          schema:
            type: string
        - name: seq
          in: query
          description: Sequence number of the DID to resolve.
          required: false
          schema:
            type: integer
      responses:
        "200":
          description: The resolved DID Document.
          content:
            application/json:
              schema:
                type: object
                properties: 
                  did:
                    type: object
                    description: "The DID Document."
                  dht:
                    type: string
                    description: "An unpadded base64URL-encoded representation of a full DNS-encoded BEP44 payload, represented as 64 bytes sig, 8 bytes u64 big-endian seq, 0-1000 bytes of v concatenated; enabling independent verification."
                  types:
                    type: array
                    items:
                      type: integer
                    description: "The types associated with the DID."
                  sequence_numbers:
                    type: array
                    items:
                      type: integer
                    description: "The sequence numbers available for querying for this node."
                required: [ did, dht ]
        "400":
          description: Invalid request.
          content:
            application/json:
              schema:
                type: string
        "404":
          description: DID could not be resolved.
          content:
            application/json:
              schema:
                type: string
  /dids/types:
    get:
      tags:
        - DID
      summary: Retrieve a list of supported types for indexing.
      description: Retrieve a list of supported indexing types, according to the spec-defined type list.
      responses:
        "200":
          description: A list of types support, alongside their human-readable description.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    type:
                      type: integer
                    description:
                      type: string
                  required: [ type, description ]
        "404":
          description: Type indexing not supported by this gateway.
          content:
            application/json:
              schema:
                type: string
  /dids/types/{id}:
    get:
      tags:
        - DID
      summary: Retrieve a list of DIDs indexed under a given type.
      description: Retrieve a list of DIDs indexed under a given type, according to the spec-defined type index.
      parameters:
        - name: id
          in: path
          description: Type to query.
          required: true
          schema:
            type: integer
        - name: offset
          in: query
          description: Specifies the starting position from where the type records should be retrieved. Default is 0.
          schema:
            type: integer
        - name: limit
          in: query
          description: Specifies the maximum number of type records to retrieve. Default is 100.
          schema:
            type: integer
      responses:
        "200":
          description: A list of DIDs indexed under the given type.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
        "404":
          description: Type not found.
          content:
            application/json:
              schema:
                type: string
  /difficulty:
    get:
      tags:
        - DID
      summary: Get information about the current difficulty.
      description: Get information needed to calculate a retention proof for DID PUT operations.
      responses:
        "200":
          description: The current hash and difficulty to calculate a retention proof against.
          content:
            application/json:
              schema:
                type: object
                properties:
                  hash:
                    type: string
                  difficulty:
                    type: integer
                required: [ hash, difficulty ]
        "404":
          description: Retention proofs not supported by this gateway.
          content:
            application/json:
              schema:
                type: string     

§ References

Ed25519
Ed25519. D. J. Bernstein, N. Duif, T. Lange, P. Schwabe, B.-Y. Yang; 26 September 2011. ed25519.cr.yp.to.
BEP44
BEP44. Storing arbitrary data in the DHT. A. Norberg, S. Siloti; 19 December 2014. Bittorrent.org.
Bencode
Bencode. A way to specify and organize data in a terse format. Bittorrent.org.
z-base-32
z-base-32. Human-oriented base-32 encoding. Z. O’Whielacronx; November 2002.
Pkarr
Pkarr. Public-Key Addressable Resource Records. Nuhvi.
VC-JOSE-COSE
Securing Verifiable Credentials using JOSE and COSE. O. Steele, M. Jones, M. Prorock, G. Cohen; 26 February 2024. W3C.

DID-CORE
Decentralized Identifiers (DIDs) v1.0. Drummond Reed; Manu Sporny; Markus Sabadello; Dave Longley; Christopher Allen; Jonathan Holt; 2020-09-07. Status: WD.
DID-SPEC-REGISTRIES
DID Specification Registries. Orie Steele; Manu Sporny; 2020-06-18. Status: NOTE.
RFC1034
Domain names - concepts and facilities. P.V. Mockapetris; 1987-11. Status: Internet Standard.
RFC1035
Domain names - implementation and specification. P.V. Mockapetris; 1987-11. Status: Internet Standard.
RFC2119
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner; 1997-03. Status: Best Current Practice.
RFC4648
The Base16, Base32, and Base64 Data Encodings. S. Josefsson; 2006-10. Status: Proposed Standard.
RFC7517
JSON Web Key (JWK). M. Jones; 2015-05. Status: Proposed Standard.
RFC7638
JSON Web Key (JWK) Thumbprint. M. Jones; N. Sakimura; 2015-09. Status: Proposed Standard.
RFC8032
Edwards-Curve Digital Signature Algorithm (EdDSA). S. Josefsson; I. Liusvaara; 2017-01. Status: Informational.
RFC8174
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba; 2017-05. Status: Best Current Practice.

Table of Contents