did:webhash is:

DIDs that require a distributed ledger or trusted clients for resolutions face significant practical challenges in anchoring trust for many use-cases targeted by the DID WG at W3C. Conversely, however, DNS-based methods have little in the way of verifiability and are susceptible to malicious or duplicitous DID controllers abusing control of domains under their control, as DID documents in the classic did:web model are neither signed nor self-certifying, with no standardized mechanisms defined for witnessing structures to vouchsafe historical authenticity. We propose a new DID method extending did:web with additional trust and verification properties based on standard hashing methods that can be extended in implementation-specific ways, while also offering backwards compatibility for the trust models and use-cases supported by did:web.

Introduction

Preface

The Webhash DID method specification conforms to the requirements specified in the Decentralized Identifiers v1.0 Specification [[DID-CORE]]. For more information about DIDs and DID method specifications, please also see the [[?DID-PRIMER]]

Design Constraints and Motivation

This DID method was developed with the following design constraints:

  1. Static web hosting: DID Documents must be able to be hosted on static web servers (with no support for query parameters or custom HTTP headers).
  2. Prefer Backwards compatibility: Whenever possible, `did:webhash` DIDs should be resolvable by did:web resolvers. That is, for a given DID, if the webhash method keyword is changed to web, an existing DID Web resolver is able to fetch and process it.
  3. Modular Trait-Based Design: The various security features added to this method (as compared with did:web) should be modular, and reusable by any other DID Method.

Trust Model

Add section on the did:webhash Trust Model (requires DNS/ICANN/CA infrastructure for resolution, website operator has the power to disrupt key rotation chains, which means Witnesses are ultimately necessary).

Separation of Server Operator and DID Controller

The division of responsibilities into two different parties, separating the web server Operator from the DID Controller, is a primary motivation for creating a new DID method instead of continuing to use did:web.

  • Is crucial in "multi-tenancy" scenarios (either via subdomains or subdirectories).
  • Allows for greater availability, archiving, and migration to other domains or other DID methods.

Relationship to Other DID Methods

This DID method is an iteration over the original did:web method, and exists in conversation with similar web-derived microledger-based methods currently under development.

Add text comparing did:webhash to did:webs and similar methods.

Enhancements and Differences from did:web

The differences are nonbreaking and additive (see the Design Constraints section).

  • Introduces the prev term for backwards chaining, as well as a corresponding algorithm for chain verification.
  • DID Documents must be signed.
  • Requires the use of the controller term (specifically, DID document update and key rotation events must be signed by the controller DID (specifically, by a key authorized in its assertionMethod section).
  • Requires the use of a path fragment which binds a given DID document to the initial inception event.
  • Because there is always a path fragment, no .well-known/ directory mechanism is used for a DID at the "top" domain level.
  • Requires the use of Tombstones when a DID is deactivated.
  • Provides affordances for DID migration and archiving (for end-of-life and migration from non-cooperative server scenarios).
  • Specifies optional but recommended Witness mechanism.
  • Specifies optional but recommended Cache Control property.

Examples

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/did/webhash/v0.1",
    "https://w3id.org/security/suites/jws-2020/v1"
  ],
  "id": "did:webhash:example.com",

  // Note that in this example, the controller is a different DID
  "controller": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",

  // This is the first DID Document in the chain; no previous version exists
  prev: null,

  // Keys to be used for DID Authentication only
  "authentication": [
    {
      "id": "did:webhash:example.com#key-1",
      "type": "JsonWebKey2020",
      "controller": "did:webhash:example.com",
      "publicKeyJwk": {
        "kty": "OKP",
        "crv": "Ed25519",
        "x": "0-e2i2_Ua1S5HbTYnVB0lj2Z2ytXu2-tYmDFf8f5NjU"
      }
    }
  ],
  // Keys to be used for signing VCs, DIDs, key rotation events, etc
  "assertionMethod": [
    {
      "id": "did:webhash:example.com#key-2",
      "type": "JsonWebKey2020",
      "controller": "did:webhash:example.com",
      "publicKeyJwk": {
        "kty": "EC",
        "crv": "P-256",
        "x": "38M1FDts7Oea7urmseiugGW7tWc3mLpJh6rKe7xINZ8",
        "y": "nDQW6XZ7b_u2Sy9slofYLlG03sOEoug3I0aAPQ0exs4"
      }
    }
  ],
  // Keys to be used for encryption (key agreement) only
  "keyAgreement": [
    {
      "id": "did:webhash:example.com#key-3",
      "type": "JsonWebKey2020",
      "controller": "did:webhash:example.com",
      "publicKeyJwk": {
        "kty": "OKP",
        "crv": "X25519",
        "x": "9GXjPGGvmRq9F6Ng5dQQ_s31mfhxrcNZxRGONrmH30k"
      }
    }
  ],

  "service": [{
    "type": "TransparencyService",
    "serviceEndpoint": "https://key-log.example.com"
  }],

  proof: {
     // ... DID Doc signed by controller's 'assertionMethod' key
  }
}
        
{
  "@context": [
    "https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/secp256k1recovery-2020/v2"
  ],
  "id": "did:webhash:example.com",
  "verificationMethod": [{
      "id": "did:webhash:example.com#address-0",
      "type": "EcdsaSecp256k1RecoveryMethod2020",
      "controller": "did:webhash:example.com",
      "blockchainAccountId": "eip155:1:0x89a932207c485f85226d86f7cd486a89a24fcc12"
  }],
  "authentication": [
      "did:webhash:example.com#address-0"
  ]
}
        

webhash DID Method Specification

Target system

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

Method name

The namestring that shall identify this DID method is: webhash.

A DID that uses this method MUST begin with the following prefix: did:webhash. Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix, is 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 document. The formal rules describing valid domain name syntax are described in [[RFC1035]], [[RFC1123]], and [[RFC2181]].

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.

Additionally, a hash value for the unsigned "payload" of the currently-valid DID document (i.e., the "backwards-compatible" one that is also a valid did:web document) MAY be appended (delimited by a colon), after the path if present, to any webhash method identifiers.

The syntax of a webhash DID string, expressed as a pseudo regular expression, is:
did:webhash:{valid domain}[:[^/:#?]+]*[:{Initial creation event trust anchor}]{0,1}

webhash-did = "did:webhash:" domain-name
webhash-did = "did:webhash:" domain-name * (":" path)
        
did:webhash:w3c-ccg.github.io

did:webhash:w3c-ccg.github.io:user:alice

did:webhash:example.com%3A3000
        

Key Material and Document Handling

Due to the way most web servers present content, it is likely that a particular `did:webhash` document will be served with a media type of `application/json`. If a document is retrieved and it is named `did.json`, it can be parsed as a JSON object; depending on the contents of the proof object(s) attached, it can be verified as a valid JSON-LD document (see section 6.3.2 of the [[did-core]] specification.) and/or reconstructed to form a a valid JWS truple (see section 6.3.2 of the [[did-core]] specification) for verification.

Whenever a DID URL is present within a `did:webhash` document, it MUST be an absolute URL *without* the hash-segment appended.

This includes URLs inside of embedded key material and other metadata, and prevents key confusion attacks.

DID method operations

CRUD API

There is intentionally no HTTP API specified for the did:webhash method operations, leaving programmatic registrations and management to be defined by each implementation, or based on their own requirements in their web environment.

Add some example HTTP-based APIs for creating and editing resources, such as Solid, AtomPub, etc.

Create (Register)

To create a did:webhash DID and its corresponding document, you'll need a domain and a web server. Specifically, one must meet the following pre-requisite requirements:

  • Select a registered domain that has a valid domain certificate, that is running a web server able to serve static files. That is, a domain able to be resolved using the https URL scheme.
  • Have sufficient authorization/privileges to be able to create resources (folders and files), to be served by that web server. For example, to create a did:webhash DID at the domain https://webserver.example, you'll need to be able to create resources at the web path /. That is, to create a directory abcd12345, such that it'll be resolvable via https://webserver.example/abcd12345/

Once those pre-requisites are met, creating a DID is done by:

  1. Select a public-private signing key pair that will serve as the controller key. This key will be used to sign the initial DID Document, as well as to sign subsequent DID Document update events.
  2. Generate a JWK Thumbprint (see RFC7638) of the controller key.
  3. creating the payload DID document (without proof object) that will be hashed and then signed with all the relevant keys referenced at absolute DID URLs without a hash segment appended.
  4. signing the unproofed DID document with a approprate keypair from the DID document and appending one or more proof objects to the DID document containing and describing said signature (See the section "Signing DID Documents" for default method and alternatives).
  5. hashing the proofed DID document to generate the "hash segment" needed for both publishing and securely using the DID. (See the section "Generating entropic identifiers for DID documents" for more default method and alternatives).
  6. publishing the proofed DID Document as the file did.json at the domain (qualified or unqualifed) that the did identifier (without hash segment) translates to when :s are replaced with /s, as well as the domain (qualified or unqualified) that the did identifier (with hash segment) translates to when :s are replaced with /s.

For example, for the domain name `w3c-ccg.github.io`, the `did.json` will be available under the following URL:

did:webhash:w3c-ccg.github.io
 -> https://w3c-ccg.github.io/did.json
          

If an optional path is specified rather than a bare domain, the did.json will be available under the specified path:

did:webhash:w3c-ccg.github.io:user:alice
 -> https://w3c-ccg.github.io/user/alice/did.json
          

If an optional port is specified on the domain, the port colon splitting the host and the port MUST be percent encoded to prevent collision with the colons used as separators between domain, optional path, and entoropic identifier.

did:webhash:example.com%3A3000:user:alice
 -> https://example.com:3000/user/alice/did.json
        

Read (Resolve)

The following steps MUST be executed to resolve the DID document from a webhash DID:

  1. Replace ":" with "/" in the method specific identifier to obtain the fully qualified domain name and optional path, whether a hash segment is appended or not.
  2. If the domain contains a port, percent-decode the colon.
  3. Generate an HTTPS URL to the expected location of the DID document by prepending https://.
  4. Append /did.json to complete the URL.
  5. 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 .
  6. 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.

Update

When generating a new DID document, the value of root DID document property prev should be set to the current DID with the version-specific hash segment appended.

Once updated, the new DID document must be published. The did.json corresponding to the identifier without a hash segment appended must be replaced with a new (and newly-proofed) DID document. This new DID document MUST also be published at the path corresponding to the identifier with the new document's hash segment.

There is no HTTP API specified for the update process leaving programmatic registrations and management to be defined by each implementation.

Deactivate (Tombstone)

To delete the DID document without revoking or "disavowing" all previous history of the DID, a new DID did.json should be stripped of all values except `prev` and all key material, then signed and published as usual, making future updates unverifiable (as no future DID document can be signed by a key contained in the previous document).

Deactivate (Revoke)

To delete the DID document and revoke all previous history of the DID, the current did.json and those corresponding to all previous hash-segment-appended versions should be deleted from the corresponding domain.

Generating entropic identifiers for DID documents

As the name webhash would imply, each DID document published to the web is intended to be addressable stably and archivally by an entropic identifier, such as one produced by a deterministic and standard hash function. This allows a "microledger" style history of each DID, since each DID document after the first contains a back-link to the previous one in the form of a prev property, the value of which is includes the hash of the previous unproofed DID document. It also enables multiple witnessing structures to "mirror" or sync witnessed DID documents across architectures, and even for DID histories to span multiple domains (although these cannot be considered verified without some form of additional input from a witness of some kind).

To generate a deterministic hash, canonicalize an unproofed DID document according to RFC 8785, for which standard tooling is readily available at time of press. The hash function and expression used is a SHA256 ASCII-encoded as a 32 characters in the base58btc alphabet. This is commonly referred to as a "CIDv0" in IPFS-based systems for content-addressed key/value storage, and common IPFS tooling can be used to generate such hashes from canonicalized JSON objects regardless of an implementation's choice of storage or witnessing mechanisms.

Historical Query and Walking Backlinks

Dynamic web services or complex redirecting policies MAY be implemented to allow consumers to query by resolution metadata via query parameters like ?versionId= or ?versionTime= (see section 7.1.3 of the [[did-core]] specification), but this is not required for conformance. Publishing according to this specification allows witnesses and consumers alike to reconstruct the entire history of a given did by recursing through the prev property of each resolved and verified DID document starting at the presently-valid one (which can be queried without hash segment).

In low-trust environments, protection against duplicitous or inauthentic DID histories can be achieved by

  1. establishing a complete DID history walking back from the presently-valid DID document (i.e. querying without a hash segment and then resolving each prev DID until a DID without a prev is resolved), then
  2. querying a trusted witnessing service (e.g. by hash segment value, versionId, and/or versionTime) or querying any other form of external verifiable data registry, including git-based records, snapshotting systems, key-value stores that store resolution metadata, and/or by content-addressed archives, and then
  3. confirming the provenance of the requested current or historical DID document as per use-case and witnessing system properties.

Security and privacy considerations

Authentication and Authorization

This DID method does not specify any authentication or authorization mechanism for writing to, removing or creating the DID Document, leaving it up to implementations to protect did:webhash documents as with any other web resource.

It is up to implementer to secure their web environments according to industry best practices for updating or otherwise managing web content based on the specific needs of their threat environment.

DNS Considerations

DNS Security Considerations

DNS presents many of the attack vectors that enable active security and privacy attacks on the did:webhash method and it's important that implementors address these concerns via proper configuration of DNS. For example, without proper security of the DNS resolution via DNS over HTTPS it's possible for active attackers to intercept the result of the DNS resolution via a Man in the Middle attack which would point at a malicious server with the incorrect DID Document.

Additionally, implementors should be aware of issues presented by a Spoofed DNS records where the record returned by a malicious DNS Server is inauthentic and allows the record to be pointed at a malicious server which contains a different DID Document. To prevent this type of issue, usage of DNSSEC which is RFC4033, RFC4034, and RFC4035.

DNS Privacy Considerations

Due to the nature of the did:webhash method relying upon a DNS in order to resolve the web server, all resolutions of a did:webhash identifier have the potential to be tracked by a DNS provider. Additionally, due to the DID Document being stored on a web server, each time the DID Document resource is retrieved, the web server has the ability to track the resolution of the DID Document. To mitigate the issue of the relying party being tracked when resolving the DID Document the relying party should look to either use a trusted universal resolver service to gain herd privacy, utilize a VPN service or perform a resolution over the TOR network. Another emerging solution that will be useful to address this is draft-pauly-dprive-oblivious-doh-03

In-transit Security

Guidance from NIST SP 800-52 Rev. 2 or superceding, MUST be followed for delivery of a `did:webhash` document.

It is additionally recommended to adhere to the latest recommendations from OWASP's Transport Layer Protection Cheat Sheet [[OWASP-TRANSPORT]] for hardening TLS configurations.

Consult NIST SP 800-57 for guidance on cryptoperiod, which is the time span during which a specific key is authorized for use or in which the keys for a given system or application may remain in effect.

TLS configuration MUST use at least SHA256, and SHOULD use SHA384, POLY1305, or stronger, depending on the needs of your operating environment.

Delete action MAY be performed by domain name registrars or DNS lookup services.

As of this writing, TLS 1.2 or higher SHOULD be configured to use only strong ciphers suites and to use sufficiently large key sizes. As recommendations may be volatile these days, only the very latest recommendations should be used. However, as a rule of thumb, the following set of suites is a reasonable starting point:

  • ECDHE with one of the strong curves {X25519, brainpoolP384r1, NIST P-384, brainpoolP256r1, NIST P-256} shall be used as key exchange.
  • AESGCM or ChaCha20 with 256 bit large keys shall be used for bulk encryption
  • ECDSA with one of the strong curves {brainpoolP384r1, NIST P-384, brainpoolP256r1, NIST P-256} or RSA (at least 3072) shall be used.
  • Authenticated Encryption with Associated Data (AEAD) shall be used as Mac.

Examples of strong SSL/TLS configurations for now are:

  • ECDHE-ECDSA-AES256-GCM-SHA384, TLSv1.2, Kx=ECDH, Au=ECDSA, Enc=AESGCM(256), Mac=AEAD
  • ECDHE-RSA-AES256-GCM-SHA384, TLSv1.2, Kx=ECDH, Au=RSA Enc=AESGCM(256), Mac=AEAD
  • ECDHE-ECDSA-CHACHA20-POLY1305, TLSv1.2, Kx=ECDH, Au=ECDSA, Enc=ChaCha20-Poly1305, Mac=AEAD
  • ECDHE-RSA-CHACHA20-POLY1305, TLSv1.2, Kx=ECDH, Au=RSA, Enc=ChaCha20-Poly1305, Mac=AEAD
  • ECDHE-RSA-AES256-GCM-SHA384, TLSv1.2, Kx=ECDH, Au=RSA, Enc=AESGCM(256), Mac=AEAD
  • ECDHE-ECDSA-AES256-GCM-SHA384, TLSv1.2, Kx=ECDH, Au=ECDSA, Enc=AESGCM(256), Mac=AEAD

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 outside of the ASCII range.

See also:

Optional Path Considerations

When optional paths to DID documents are used to resolve documents rather than bare domains, verification with signed data proves that the entity in control of the file indicated in the path has the private keys. It does not prove that the domain operator has the private keys.

This example:

did:webhash:example.com:u:bob
          

resolves to the DID document at:

https://example.com/u/bob/did.json
        

In this scenario, it is probable that example.com has given user Bob control over the DID in question, and proofs of control refer to Bob rather than all of example.com.

Reference implementations