did:webhash
is:
did:web
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.
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]]
This DID method was developed with the following design constraints:
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.
did:web
) should be modular, and reusable by any other
DID Method.
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
.
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.
did:web
- No key rotation history; the DID Document
contains only the latest valid keys. Unsigned DID docs.did:webs
- see the
DID Method did:webs Specification.
Key rotation events at a separate location (in KERI format).
did:webplus
- see
https://github.com/LedgerDomain/did-webplusdid:plc
- key rotation events at a separate locationdid:web
The differences are nonbreaking and additive (see the Design Constraints section).
prev
term for backwards chaining,
as well as a corresponding algorithm for chain verification.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).
.well-known/
directory mechanism is used for a DID at the "top" domain level.{ "@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
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).
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.
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
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.
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.
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:
https
URL scheme.
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:
proof
object) that will be hashed and then signed with all the relevant
keys referenced at absolute DID URLs without a hash
segment appended.
proof
objects to the DID document containing and describing said signature
(See the section "Signing DID Documents" for default method and
alternatives).
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
The following steps MUST be executed to resolve the DID document from a webhash DID:
https://
.
/did.json
to complete the URL.
GET
request to the URL using an agent
that can successfully negotiate a secure HTTPS connection, which
enforces the security requirements as described in .
GET
request, the client SHOULD utilize [[RFC8484]] in order to prevent
tracking of the identity being resolved.
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.
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).
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.
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.
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
prev
DID until a DID without a prev
is
resolved), thenversionId
, 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 thenThis 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 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.
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
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:
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
[[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:
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.