§ ToIP did:webs Method Specification
Specification Status: v0.10.3
In order to further validate and improve the specification and to demonstrate interoperability between multiple implementations of did:webs, we encourage additional did:webs implementations to the original did:webs Reference Implementation.
Latest Draft:
https://github.com/trustoverip/kswg-did-method-webs-specification
Editors:
- Phil Feairheller, GLEIF
- Daniel Hardman, Provenant, Inc
- Sam Smith, Prosapien
- Lance Byrd, GLEIF and RootsID
- Jonathan Rayback, Future Forge Innovation LLC
- Kent Bull, Kent Bull
Contributors:
- Markus Sabadello, Danube Tech and DIF
- Kevin Griffin, GLEIF
- Charles Lanahan
- Nuttawut Kongsuwan, Finema
- Darrell O’Donnell, Continuum Loop Inc.
- Henk van Cann, Blockchainbird
- Participate:
- GitHub repo
- Commit history
§ Introduction
DID methods answer many questions. Two noteworthy ones are:
- How is information about DIDs (in the form of DID documents) published and discovered?
- How is the trustworthiness of this information evaluated?
The previously released did:web method merges these two questions, giving
one answer: Information is published and secured using familiar web
mechanisms. This has wonderful adoption benefits, because the processes
and tooling are familiar to millions of developers.
Unfortunately, this answer works better for the first question than the second. The current web is simply not very trustworthy. Websites get hacked. Sysadmins are sometimes malicious. DNS can be hijacked. X509 certs often prove less than clients wish. Browser validation checks are imperfect. Different certificate authorities have different quality standards. The processes that browser vendors use to pre-approve certificate authorities in browsers are opaque and centralized. TLS is susceptible to man-in-the-middle attacks on intranets with customized certificate chains. Governance is weak and inconsistent…
Furthermore, familiar web mechanisms are almost always operated by corporate IT staff. This makes them an awkward fit for the ideal of decentralized autonomy — even if individuals can publish a DID on corporate web servers, those individuals are at the mercy of IT personnel for their security.
The did:webs method described in this spec separates these two questions
and answers them distinctively. Information about DIDs is still
published on the web, but its trustworthiness derives from mechanisms
entirely governed by individual DID controllers. This preserves most of the
delightful convenience of did:web, while drastically upgrading security
through authentic data that is end-verifiable.
Within the context of did:webs the term decentralized trust includes
verifiability, confidentiality, and privacy, but excludes veracity of the
content. The latter is always a matter of (personal) evaluation of
available reputational data and verifiable credentials (VCs).
As a preview of syntax, see the below sample did:webs DID:
did:webs:example.com%3a3000:users:alice:EKYGGh-FtAphGmSZbsuBs_t4qpsjYJ2ZqvMKluq9OxmP
│ │ │ │ │ │
│ │ │ │ │ └─ AID (KERI identifier)
│ │ │ │ └─────── Path component
│ │ │ └───────────── Path component
│ │ └───────────────────── Port (URL-encoded)
│ └──────────────────────────────── Host
└───────────────────────────────────────── Method
§ Status of This Memo
Information about the current status of this document, any errata, and how to provide feedback on it, may be obtained at https://github.com/trustoverip/kswg-did-method-webs-specification.
§ Copyright Notice
This specification is subject to the OWF Contributor License Agreement 1.0 - Copyright available at https://www.openwebfoundation.org/the-agreements/the-owf-1-0-agreements-granted-claims/owf-contributor-license-agreement-1-0-copyright.
If source code is included in the specification, that code is subject to the Apache 2.0 license unless otherwise marked. In the case of any conflict or confusion between the OWF Contributor License and the designated source code license within this specification, the terms of the OWF Contributor License MUST apply.
These terms are inherited from the Technical Stack Working Group at the Trust over IP Foundation. Working Group Charter.
§ Terms of Use
These materials are made available under and are subject to the OWF CLA 1.0 - Copyright & Patent license. Any source code is made available under the Apache 2.0 license.
THESE MATERIALS ARE PROVIDED “AS IS.” The Trust Over IP Foundation, established as the Joint Development Foundation Projects, LLC, Trust Over IP Foundation Series (“ToIP”), and its members and contributors (each of ToIP, its members and contributors, a “ToIP Party”) expressly disclaim any warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to the materials. The entire risk as to implementing or otherwise using the materials is assumed by the implementer and user. IN NO EVENT WILL ANY ToIP PARTY BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES OF ACTION OF ANY KIND WITH RESPECT TO THESE MATERIALS, ANY DELIVERABLE OR THE ToIP GOVERNING AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
§ Scope
This document specifies a DID
Method,
did:webs, that is web-based but innovatively secure. Like its
interoperable cousin, did:web, the
did:webs method uses traditional web infrastructure to publish DIDs and
make them discoverable. Unlike did:web, this method’s trust is not rooted in
DNS, webmasters, X509, and certificate authorities. Instead, it uses KERI to provide a secure chain of cryptographic key events by those who
control the identifier including any of its delegators.
The did:webs method does not need blockchains to establish trust.
However, its use of KERI allows for arbitrary blockchains to be
referenced as an extra, optional publication mechanism. This offers a
potential interoperability bridge from (or between) blockchain
ecosystems. Also, without directly supporting environments where the
web is not practical (e.g., IOT, Lo-Ra, Bluetooth, NFC), the method builds on a
foundation that can fully support those environments, making future interop of
identifiers between web and non-web a manageable step for users of did:webs identifiers.
All DID methods make tradeoffs. The ones in did:webs result in a method that
is cheap, easy to implement, and scalable. No exotic or unproven cryptography is
required. Deployment is straightforward. Cryptographic trust is strongly
decentralized and governance is transparent. Signing authority is scalable through
the support of delegated identifiers. Regulatory challenges around the issue of
blockchains vanish. Any tech community or legal jurisdiction can use it. However,
did:webs does depend on the web for publication and discovery. This may
color its decentralization and privacy. For its security, it adds KERI. For users, the method also raises the bar of accountability,
thoughtfulness, and autonomy; this can be viewed as
either a drawback or a benefit (or both).
§ Normative references
The normative documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.
- ISO/IEC 7498-1:1994 Information technology — Open Systems Interconnection — Basic Reference Model: The Basic Model, including Requirement Levels (IETF RFC-2119).
See Bibliography - Normative Section
§ Terms and Definitions
For the purposes of this document, the following terms and definitions apply.
ISO and IEC maintain terminological databases for use in standardization at the following addresses:
- ISO Online browsing platform: available at https://www.iso.org/obp
- IEC Electropedia: available at http://www.electropedia.org/
:::
- AID controlled identifier (AID-controlled-identifiers)
- Any identifier, including
did:websDIDs, that have the same AID are by - definition referencing the same identity. As defined in the KERISuite
- glossary: designated aliases
- authentic chained data container (ACDC, ACDCs, authentic-chained-data-container)
- a variant of Verifiable Credentials Data Model that
- inherits the security model derived from KERI, as defined by the
- ACDC specification.
- See [[xref: keri1, authentic-chained-data-container, authentic chained data
- container]] in the KERISuite glossary for more detail.
- autonomic identifier (AID, AIDs, autonomic-identifier)
- BADA-RUN
-
Best available data acceptance - Read/Update/Nullify provides a medium level
-
of security because events are ordered in a consistent way, using a
-
combination of date-time and a key state. The latest event is the one with
-
the latest date-time for the latest key state.
-
More detail:
- compact event streaming representation (CESR, compact-event-streaming-representation)
-
An encoding format that enables round-trip text-binary conversion of
-
concatenated cryptographic primitives and general data types, as defined by
-
the CESR specification and
-
More detail:
-
CESR.
- controller
- cryptographically verifiable (cryptographically-verifiable)
- decentralized identifier (Decentralized Identifiers, DID, DIDs, decentralized-identifier)
- A globally unique persistent identifier, as defined by
- DID Core.
- designated aliases (designated alias, designated-aliases)
-
An array of AID controlled identifiers that have been designated by
-
the AID controller to be used as aliases for
equivalentIdand -
alsoKnownAsDID document metadata and to foster verification of -
redirection to different did:webs identifiers.
-
More detail:
- DID document (DID documents, DID-document)
- A set of data describing the subject of a decentralized identifier
- (DID), as defined by
- DID Core. See also
- section DID Documents.
- DID document metadata (DID-document-metadata)
-
DID document metadata is metadata about the DID and the DID document
-
that is the result of the DID Resolution process.
-
See also:
-
in the DID Core specification.
- DID resolution metadata (DID-resolution-metadata)
-
DID resolution metadata is metadata about the DID Resolution process that
-
was performed in order to obtain the DID document for a given DID.
-
See also:
-
in the DID Core specification.
- direct mode (direct-mode)
- hosts (host name, host names, host)
- The part of a URL that can be either a domain name or an IP address. This
- component specifies the server that the client needs to communicate with in
- order to access the desired resource on the web.
- identifier
-
A single attribute—typically a character string—that uniquely identifies an
-
entity within a specific context (which may be a global context). Examples
-
include the name of a party, the URL of an organization, or a serial number
-
for a man-made thing.
-
Supporting definitions:
-
*General IT: identifier,
-
identifier~* Trust-over-IP: identifier.
- inception event (inception events, inception-event)
- indirect mode (indirect-mode)
- interaction event (interaction events, interaction-event)
- KEL backed data (KEL-backed-data)
-
KEL backed data in
did:websprovides the highest level of data -
security assurance and such data can be found either in the KEL or anchored
-
to an event in the KEL. This means that the signatures on the events in the
-
KEL are strongly bound to the key state at the time the events are entered
-
in the KEL, that is the data.
-
Explanation: This provides strong guarantees of non-duplicity to any
-
verifiers receiving a presentation as the KELs are protected and can be
-
watched by agents (watcher) of the verifiers. The information is
-
end-verifiable and any evidence of duplicity in the events is evidence that
-
the data or presentation should not be trusted.
-
More detail:
- KERI event stream (KERI event streams, KERI-event-stream)
-
A stream of verifiable KERI data, consisting of the key event log
-
(KEL) and other data such as a transaction event log
-
and may be serialized in a file using CESR encoding. We refer to
-
these CESR stream resources as KERI event streams to simplify the vocabulary.
-
More detail:
- KERI Request Authentication Mechanism (KRAM, KERI-request-authentication-mechanism)
-
A non-interactive replay attack protection algorithm that uses a sliding
-
window of date-time stamps and key state (similar to the tuple in
-
BADA-RUN) but the date-time is the replier’s not the querier’s.
-
KRAM is meant to protect a host.
-
More detail:
- key event (key events, key-event)
- key event log (KEL, KELs, key-event-log)
- key event receipt (key-event-receipt)
- key event receipt infrastructure (KERI, key-event-receipt-infrastructure)
- key event receipt log (KERL, key-event-receipt-log)
- key state (key states, key-state)
- method-specific identifier (MSI, method-specific-identifier)
- The
method-specific-idpart of DID Syntax, as defined in - DID Core. See section
- Method-Specific Identifier.
- Multi-signature (multi-signatures, multisig, multi-sig, multi-signature)
- out-of-band introduction (OOBI, OOBIs, OOBI specification, out-of-band-introduction)
- Pre-rotation (pre-rotated, pre-rotation)
- rotation event (rotation events, rotation-event)
- self-addressing identifier (SAID, SAIDs, self-addressing-identifier)
- transaction event log (TEL, TELs, transaction-event-log)
- verifiable identifier (VID, VIDs, verifiable-identifier)
- Verifier (verifiers, verifier)
- Watcher (watchers, watcher)
- Witness (witnesses, witness)
§ Core Characteristics
This section is normative.
§ Method Name
- The method name that identifies this DID method SHALL be:
webs. - A DID that uses this method MUST begin with the following prefix:
did:webs:. - Per the DID specification, this string MUST be lower case.
- The remainder of the DID, after the prefix, MUST be the case-sensitive method-specific identifier (MSI) described below.
Note: when pronounced aloud, “webs” should become two syllables: the word “web” and the letter “s” (which stands for “secure”). Separating the final letter this way emphasizes that the method offers a security upgrade surpassing the one HTTPS gives to HTTP.
§ Method-Specific Identifier
- The
did:websmethod-specific identifier MUST have two parts, a host with an optional path (identical todid:web), plus a KERI AID (autonomic identifier) that is always the final component of the path. - The ABNF definition of a
did:websDID MUST be as follows:
; did:webs DID structure
webs-did = "did:webs:" host [pct-encoded-colon port] *(":" path) ":" aid
; Simplified host character class for illustration only.
; Normative domain-name rules: RFC 1035, RFC 1123, and RFC 2181.
; Normative URI host/authority (including IP forms): RFC 3986.
; Implementations SHOULD use a mature URI/host parsing library.
host = 1*( ALPHA / DIGIT / "-" / "." )
; 'pct-encoded-colon' represents a percent-encoded colon
pct-encoded-colon = "%3A" / "%3a" ; Percent encoding for ':'
; 'port' number (simplified version)
port = 1*5(DIGIT)
; Path segment between colons (no '/'; path separators in the DID are ':')
path = 1*(ALPHA / DIGIT / "-" / "_" / "~" / ".")
aid = said
; AID is a KERI SAID; SAID structure:
said = said-256 / said-512
; Base64URLSafe characters (RFC 4648, excluding padding)
base64urlsafe = ALPHA / DIGIT / "-" / "_"
; The complete SAID primitive MUST conform to the CESR code tables.
; The following currently defined digest codes produce 256-bit or
; 512-bit SAIDs of 44 or 88 characters total.
; 256-bit SAIDs: 44 characters total (1 char code + 43 Base64URLSafe)
one-char-code = "E" / "F" / "G" / "H" / "I"
said-256 = one-char-code 43base64urlsafe
; 512-bit SAIDs: 88 characters total (2 char code + 86 Base64URLSafe)
two-char-code = "0D" / "0E" / "0F" / "0G"
said-512 = two-char-code 86base64urlsafe
- When the host is a domain name, it MUST abide by the formal rules describing valid domain name syntax found in RFC 1035, RFC 1123, and RFC 2181.
- When interpreting the host as part of a URI authority — including port
handling and IP-literal forms — the host MUST also conform to the
hostproduction in RFC 3986. Implementations SHOULD use a mature URI/host parsing library rather than relying solely on the simplified ABNFhostrule above. - A port MAY be included and the colon MUST be percent encoded, like
%3a, to prevent a conflict with paths. - Directories and subdirectories MAY optionally be included, delimited by
colons rather than slashes. Path segments MUST NOT contain
/. - The KERI AID is a unique identifier and MUST be derived from the inception event of a KERI identifier.
To be compatible with did:web, the AID is “just a path”, the final (and
perhaps only) path element. The presence of the required AID as a path
element means that a did:webs always has a path, and so the “no path”
version of a did:web that implicitly uses the .well-known location is not
supported by did:webs. Any did:webs can be expressed as a did:web but
the inverse is not true–a did:webs must include an AID.
§ Target System(s)
The following rules indicate where the two did:webs artifacts, did.json and
keri.cesr, are to be hosted on target systems and how they are to be resolved
for both did:webs and did:web resolution.
- As with
did:web,did:websMUST read data from whatever web server is referenced when the host portion of one of its DIDs is resolved. - A
did:websDID MUST resolve to a DID document using a simple text transformation to an HTTPS URL in the same way as adid:webDID. - A
did:webDID anddid:websDID with the same method-specific-identifier SHOULD return the same DID document, except for minor differences in theid,controller, andalsoKnownAstop-level properties that pertain to the identifiers themselves. - As with
did:web, the location of thedid:websDID document MUST be determined by transforming the DID to an HTTPS URL as follows:- MUST replace
did:webswithhttps:// - MUST replace the "
:"s in the method-specific identifier with path separators, "‘/’"s - MUST convert the optional port percent encoding (
%3Aor%3a) to a colon if present. - MUST append “
/did.json” to the resulting string.
- MUST replace
- A GET on that URL MUST return the DID document.
- The location of the KERI event stream MUST be determined by
transforming the previous URL as follows:
- MUST replace the trailing “
/did.json” with “/keri.cesr”. - A GET on that URL MUST return the KERI event stream for the AID in
the
did:websidentifier. - The KERI event stream MUST be CESR-formatted, MUST have the
media type of
application/cesr, and the KERI events MUST be verifiable using the KERI rules.
- MUST replace the trailing “
- The
did:webversion of the DIDs MUST be the same (minus thes) and point to the samedid.jsonfile.
§ Sample did:webs URLs
The below example did:webs DIDs and their corresponding DID
documents and KERI event stream URLs, based on the examples from the
did:web specification, but with the sample AID EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR added:
did:webs:w3c-ccg.github.io:EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR- The DID document URL would look like:
https://w3c-ccg.github.io/EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR/did.json - KERI event stream URL would look like:
https://w3c-ccg.github.io/EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR/keri.cesr
- The DID document URL would look like:
did:webs:w3c-ccg.github.io:user:alice:EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR- The DID document URL would look like:
https://w3c-ccg.github.io/user/alice/EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR/did.json - KERI event stream URL would look like:
https://w3c-ccg.github.io/user/alice/EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR/keri.cesr
- The DID document URL would look like:
did:webs:example.com%3a3000:user:alice:EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR- The DID document URL would look like:
https://example.com:3000/user/alice/EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR/did.json - KERI event stream URL would look like:
https://example.com:3000/user/alice/EKTh4PkRBiNWHQd263Eueu39gWmg7AfIfnEmNy6jinGR/keri.cesr
- The DID document URL would look like:
§ KERI puts the “s” in did:webs
For more information, see the following sections in the implementors guide:
- the set of KERI features needed to
support
did:webs
A target system cannot forge or tamper with data protected by KERI, and if
it deliberately serves an outdated copy, the duplicity is often detectable.
Thus, any given target system in isolation can be viewed by this method as a
dumb, untrusted server of content. It is the combination of target systems
and some KERI mechanisms, together, that constitutes this method’s
verifiable data registry. In short, verifying the DID document by
processing the KERI event stream using KERI puts the “s” of
“security” in did:webs.
§ AID controlled identifiers
- AID controlled identifiers MAY vary in how quickly they reflect
the current identity information, DID document and KERI event stream.
Notably, as defined in section
Stable Identifiers On An Unstable Web,
the
idproperty in the DID document will differ based on the web location of the DID document. - Different versions of the DID document and KERI event stream MAY reside in different locations depending on the replication capabilities of the controlling entity.
- If the KERI event streams differ for
did:websDIDs with the same AID, the smaller KERI event stream MUST be a prefix of the larger KERI event stream (e.g., the only difference in the KERI event streams being the extra events in one of the KERI event streams, not yet reflected in the other). - If the KERI event streams diverge from one another (e.g., one is not a subset of the other), both the KERI event streams and the DIDs MUST be considered invalid.
- The verification of the KERI event stream SHOULD provide mechanisms for detecting the forking of the KERI event stream by using mechanisms such as KERI witnesses and watchers.
Since an AID is a unique cryptographic identifier that is inseparably bound
to the KERI event stream it is associated with any AIDs and any
did:webs DIDs that have the same AID component. It can be verifiably
proven that they have the same controller(s).
§ Handling Web Redirection
-
A
did:websDID MAY be a “stable” (long-lasting) identifier that can be put into documents such as verifiable credentials, to be useful for a very long time – generations. -
When a
did:websDID is updated for another location the following rules MUST apply:- Its AID MUST NOT change.
- The same KERI event stream MUST be used to verify the DID document, with the only change being the designated aliases list reflecting the new location identifier.
- If a resolver can find a newly named DID that uses the same AID, and the KERI event stream verifies the DID, then the resolver MAY consider the resolution to be successful and should note it in the resolution metadata.
-
The following resolution paths that
did:websidentifiers SHALL leverage to help in the face of resolution uncertainty include:- The
did:websDID SHALL provide other designated aliases DID(s) that are anchored to the KERI event stream. - When a
did:websDID is permanently moved to some other location the resolver MAY redirect to any otherequivalentIddesignated aliases.- The
idin the DID document MUST be set to the new location. - An
equivalentIdentry of the old location SHOULD remain for historical purposes and be anchored to the KERI event stream using designated aliases. See section Use ofequivalentIdfor more details. - If possible, the controller of the DID MAY use web redirects to allow resolution of the old location of the DID to the new location.
- The
- If the previously published location of a
did:websDID is not redirected, an entity trying to resolve the DID MAY be able to find the data for the DID somewhere else using just the AID.
- The
The implementors guide contains more information about did:webs
stable identifiers on an unstable web.
§ DID Method Operations
This section is normative.
The four DID Method Operations, create, read, update, and deactivate conceptually map to the following events for a did:webs DID:
- Create:
did:websidentifier creation maps to the combination of- a KERI inception event and
- initial issuance of a designated aliases ACDC with the initial host and path
segments of the
did:websDID.
- Read: plain HTTP GET of the following resources. Similar to a KERI
OOBI resolution.
did.jsondocument (derived from thekeri.cesrstream)keri.cesrstream- includes:
- KERI events (KEL) for the
did:websDID and any delegators - ACDC TEL events, issuance and revocation, for designated alias ACDCs
- ACDCs for designated aliases
- KERI Reply messages (Location Scheme, Endpoint Role Authorization)
- KERI events (KEL) for the
- includes:
- Update: involves changing values in the DID document. These might include:
- key change: a KERI key rotation event changes the verification methods in a
did:websDID document. - alsoKnownAs or equivalentId change: revoking and/or issuing designated aliases ACDCs that update
alsoKnownAsandequivalentId. - service endpoint change: witness rotation, Location Scheme, or Endpoint Role Authorization updates that change the
servicearray.
- key change: a KERI key rotation event changes the verification methods in a
- Deactivate: rotating the underlying KERI identifier to null, or no next keys.
§ Create
The create operation includes creation (inception) of the backing KERI
AID and issuance of the first designated aliases ACDC containing the
host and path segment present in the did:webs DID.
Once these actions are complete then the did.json and keri.cesr data may be
generated and hosted at the URLs specified in the following rules.
- Creating a
did:websDID MUST follow these rules:- MUST choose the web URL where the DID document for the DID will be published, excluding the last element that will be the AID, once defined.
- MUST create a KERI AID and add it as the last element of the web URL for the DID.
- MUST authorize the full
did:websidentifier as a designated alias ACDC anchored to the KERI AID (see Method-Specific Identifier). - If desired, a
did:webform of the identifier MAY be authorized in the same manner. - MUST add the appropriate KERI events to the AID’s KERI logs that will correspond to properties of the DID document, such as verification methods and service endpoints.
- MUST derive the
did:websDID document by processing the KERI event stream according to section DID documents. - For compatibility reasons, transformation of the derived
did:websDID document to the correspondingdid:webDID document MUST be according to section Transformation to did:web DID document. - MUST make the did:web DID document resource (
did.json) and the KERI event stream resource (keri.cesr) available at the selected location. See section Target System(s) for further details about the locations of these resources.
Of course, the web server that serves the resources when asked might be a simple file server (as implied above) or an active component that generates them dynamically. Further, the publisher of the resources placed on the web can use capabilities like [CDNs] to distribute the resources. How the resources are posted at the required location is not defined by this spec; complying implementations need not support any HTTP methods other than GET.
An active component might be used by the controller of the DID to automate the process of publishing and updating the DID document and KERI resources.
§ Read (Resolve)
This section is normative.
Resolving a did:webs DID MUST follow the procedure below. If any step
fails, the resolver MUST NOT return a DID document as a successful
resolution result. When producing a DID Resolution result, the resolver
MUST include an error in didResolutionMetadata as specified by
DID Resolution and
DID Core, leave didDocument empty, and leave
didDocumentMetadata empty.
- Convert the
did:websDID to the HTTPS URLs fordid.jsonandkeri.cesras described in Target System(s). If the DID is not a validdid:websidentifier, resolution MUST fail. - Perform HTTP GET on both URLs.
- If either request fails to return a successful response with a usable body, resolution MUST fail.
- The
did.jsonresource MUST be adid:webDID document suitable for transformation under Transformation todid:websDID document (published per Transformation todid:webDID document). - The
keri.cesrresource MUST be a CESR-formatted KERI event stream with media typeapplication/cesr.
- Process
keri.cesraccording to the KERI specification.- If cryptographic verification fails, resolution MUST fail.
- If event-stream divergence or forking is detected (see AID controlled identifiers), resolution MUST fail.
- If an optional
versionIdDID parameter is present, only events up to and including that sequence number MUST be used for the remainder of this procedure (see Support forversionId).
- Confirm that a valid, unrevoked designated aliases ACDC in the KERI event
stream as limited by step 3 authorizes the resolved
did:websDID and the correspondingdid:webDID. If not, resolution MUST fail. See Designated Aliases and Use ofequivalentId. - Derive the
did:websDID document from the verified KERI event stream according to DID documents. - Transform the fetched
did:webDID document to adid:websDID document according to Transformation todid:websDID document. If the transformation cannot be applied, resolution MUST fail. - The derived DID document MUST equal the transformed DID document. If they differ, resolution MUST fail.
- Return the
did:websDID document, together with any DID document metadata required by this specification (for exampleversionIdand, when applicable,equivalentIdandnextVersionId).
KERI-aware applications MAY use the KERI event stream for capabilities beyond DID document verification. Those uses are outside the scope of this specification.
§ Update
The did:webs identifier string itself — host, path, and AID — MUST NOT change.
Updates change content derived from the KERI event stream (keys,
aliases, and service endpoints) and MUST be reflected by regenerating and
republishing did.json and keri.cesr as soon as practical. If the resources
are statically hosted, they MUST be overwritten at the published location.
§ Key rotation update
- If the AID of the
did:websDID is transferable, key rotation updates MUST be made by adding KERI key rotation events to the KERI event stream. - Rotating keys MUST change the keys that appear in the DID document and MUST NOT change the identifier (AID).
Note: the
versionIdquery parameter is not part of the identifier. It may be used to request a point-in-time version of a DID document as of a given KERI key event sequence number. See Support forversionId.
§ Designated alias update
- Updates that add, remove, or replace authorized aliases (affecting
alsoKnownAsandequivalentId) MUST be performed by revoking and/or issuing designated aliases ACDCs anchored to the KERI event stream, according to section Designated Aliases. - After the KERI event stream reflects the updated aliases, the controller
MUST regenerate the DID document and republish
did.jsonandkeri.cesr.
§ Service endpoint update
- Updates that change witness lists, Location Scheme records, or Endpoint Role
Authorization records MUST be performed by adding the corresponding KERI
events (rotation events for witness lists;
rpyevents for Location Scheme and Endpoint Role Authorization) to the KERI event stream, according to section Service Endpoint Event Details. - After the KERI event stream reflects the updated endpoints, the controller
MUST regenerate the DID document and republish
did.jsonandkeri.cesr.
§ Deactivate
- To deactivate a
did:websDID, a controller MUST execute a KERI event that has the effect of rotating the key(s) to null (or otherwise committing to no next keys), rendering the AID non-transferable. - Once the deactivation event has been applied, the controller MUST
regenerate the DID document from the KERI event stream and
republish both
did.jsonandkeri.cesrat the published location, overwriting the existing files, so that resolvers can discover the deactivated state. - A controller MUST NOT make the DID document or KERI event stream
resources unavailable at the location where they have been published.INFORMATIVE SECTION
Removing the DID resources prevents resolvers from distinguishing an offline host from a deactivated DID. Keeping the deactivated artifacts published preserves end-verifiable evidence of deactivation.
§ DID documents
This section is normative.
did:websDID documents MUST be generated or derived from the KERI event stream of the corresponding AID.did:websDID documents MUST be pure JSON. They MAY be processed as JSON-LD by prepending an@contextif consumers of the documents wish.- All hashes, cryptographic keys, and signatures MUST be represented as CESR strings. This is an approach similar to multibase, making them self-describing and terse.
To better understand the cryptographically verifiable data structures used,
see the implementors guide description of the
KERI event stream chain of custody.
To understand the KERI AID commands resulting in the
KERI event stream and the corresponding did:webs DID document see
the original
did:webs Reference Implementation getting started guide.
In KERI the calculated values that result from processing the KERI event stream are referred to as the “current key state” and expressed in the Key State Notice (KSN) record. An example of a KERI KSN record can be seen here:
{
"v": "KERI10JSON000274_",
"i": "EeS834LMlGVEOGR8WU3rzZ9M6HUv_vtF32pSXQXKP7jg",
"s": "1",
"t": "ksn",
"p": "ESORkffLV3qHZljOcnijzhCyRT0aXM2XHGVoyd5ST-Iw",
"d": "EtgNGVxYd6W0LViISr7RSn6ul8Yn92uyj2kiWzt51mHc",
"f": "1",
"dt": "2021-11-04T12:55:14.480038+00:00",
"et": "ixn",
"kt": "1",
"k": ["DTH0PwWwsrcO_4zGe7bUR-LJX_ZGBTRsmP-ZeJ7fVg_4"],
"nt": 1,
"n": ["E6qpfz7HeczuU3dAd1O9gPPS6-h_dCxZGYhU8UaDY2pc"],
"bt": "3",
"b": [
"BGKVzj4ve0VSd8z_AmvhLg4lqcC_9WYX90k03q-R_Ydo",
"BuyRFMideczFZoapylLIyCjSdhtqVb31wZkRKvPfNqkw",
"Bgoq68HCmYNUDgOz4Skvlu306o_NY-NrYuKAVhk3Zh9c"
],
"c": [],
"ee": {
"s": "0",
"d": "ESORkffLV3qHZljOcnijzhCyRT0aXM2XHGVoyd5ST-Iw",
"br": [],
"ba": []
},
"di": ""
}
Using this key state as reference, we can identify the fields from the current key state that will translate to values in the DID document. The following table lists the values from the example KSN and their associated values in a DID document:
| Key State Field | Definition | DID document value |
|---|---|---|
i |
The AID value | The DID Subject and DID Controller |
k |
Current set of public signing keys | Verification Methods |
kt |
Current signing keys threshold | Threshold in ConditionalProof2022 |
In several cases above, the value from the key state is not enough by itself to populate the DID document. The following sections detail the algorithm to follow for each case.
§ DID Subject
This section is normative.
- The value of the
idproperty in the DID document MUST be thedid:websDID that is being created or resolved. - The value from the
ifield of the key state notice MUST be the value after the last:in the method-specific identifier (MSI) of thedid:websDID, per section Method-Specific Identifier.
{
"id": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M"
}
§ DID Controller
This section is normative.
- The value of the
controllerproperty MUST be a single string that is the same as theid(the DID Subject).
{
"controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M"
}
§ Also Known As
This section is normative.
-
The
alsoKnownAsproperty in the root of the DID document MAY contain any DID that has the same AID.INFORMATIVE SECTIONSee the designated aliases section for information on how an AID anchors the
alsoKnownAsidentifiers to their KERI event stream.- As long as the identifier is resolvable, a designated alias ACDC
containing a given identifier MUST always be present in the
keri.cesrstream in order for any identifier to be included in thealsoKnownAssection of adid:websDID document.INFORMATIVE SECTIONPresence of designated alias ACDCs containing both
did:websanddid:webidentifiers are required to support the transformation rules betweendid:websanddid:webversions of adid:websDID document while adhering to the security posture of KERI and ACDC.One potential way to implement this requirement is to ensure that resolving a given version of a
did:websDID document via theversionIdparameter will return the DID document as of a given sequence number by analyzing the designated aliases ACDCs that were valid and unrevoked at that time.
- As long as the identifier is resolvable, a designated alias ACDC
containing a given identifier MUST always be present in the
-
The
did:websversion of the DID document MAY include thedid:webversion of the DID as analsoKnownAsidentifier, provided that there is a valid, unrevoked designated aliases ACDC present in thekeri.cesrstream. -
The
did:webversion of the DID document MUST include thedid:websversion of the DID as analsoKnownAsidentifier, meaning it MUST also be in a valid, unrevoked designated aliases ACDC present in thekeri.cesrstream. -
In order for the
did:websDID document to be valid, thekeri.cesrstream MUST contain at least ONE designated aliases ACDC in which the host and path are committed to.INFORMATIVE SECTIONCommitted to means placed in a designated aliases ACDC.
This implies that the
did.jsonfor both thedid:websanddid:webversions of adid:websDID document will always contain a reciprocal link to one another that is also committed to by an event anchored into the KEL of the DID controller.A consumer of a DID document can only know that a given
did:webDID is trustable and committed to by the controller of the AID supporting adid:websDID only when thatdid:webDID is included in an unrevoked designated aliases ACDC.This protects against DID document malleability attacks where a malicious DID resolver host could inject fraudulent
did:webDIDs into a DID document. As such, the consumer of adid:websDID document should only trustdid:webDIDs that are found in an unrevoked designated aliases ACDC present in thekeri.cesrstream. -
did:websDIDs MUST provide the correspondingdid:kerias analsoKnownAsidentifier. -
The same AID MAY be associated with multiple
did:websDIDs, each with a different host and/or path, but with the same AID. -
did:websDIDs MUST be listed in the Designated aliases attestation of the AID. -
For each AID controlled identifier DID defined above, an entry in the
alsoKnownAsarray in the DID document MUST be created.
For the example DID
did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe
the following alsoKnownAs entries could be created:
{
"alsoKnownAs": [
"did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:keri:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
]
}
§ Verification Methods
This section is normative.
Each verification method for a did:webs DID is generated from signing keys
located in the KERI event stream of the controller of the
did:webs DID.
-
For each key listed in the array value of the
kfield of the KSN, a corresponding verification method MUST be generated in the DID document. -
The
typeproperty in the verification method for each public key MUST be determined by the algorithm used to generate the public key, as specified in the following subsections. -
The
idproperty of the verification method MUST be a relative DID URL and use the KERI key CESR value as the value of the fragment component, e.g.,"id": "#<identifier>". -
The
controllerproperty of the verification method MUST be the value of theidproperty of the DID document.INFORMATIVE SECTIONDID Core requires each verification method to have a
controllerproperty whose value is a valid DID, but does not require that value to equal theidof the DID document (e.g., delegation may use a different controller). This specification requires that fordid:websthecontrollerof every verification method equals the documentid, since all verification material is derived from the same AID’s key state.
KERI identifiers express public signing keys as Composable Event Streaming
Representation (CESR) encoded strings in the k field of establishment
events and the key state notice. CESR encoding encapsulates all the
information needed to determine the cryptographic algorithm used to
generate the key pair.
At the time of this writing, KERI currently supports public key generation for Ed25519, Secp256k1 and Secp256r1 keys, and the protocol allows for others to be added at any time.
For example, the key DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr in the
DID document for the AID
ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe becomes:
"verificationMethod": [
{"id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"type": "JsonWebKey",
"controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"publicKeyJwk": {
"kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"kty": "OKP",
"crv": "Ed25519",
"x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs"
}
}
]
§ Ed25519
- Ed25519 public keys MUST be converted to a verification method with a
type of
JsonWebKeyandpublicKeyJwkproperty whose value is generated by decoding the CESR representation of the public key out of the KEL and into its binary form (minus the leading ‘B’ or ‘D’ CESR codes) and generating the corresponding representation of the key in JSON Web Key form.
For example, a KERI AID with only the following inception event in its KEL:
{
"v":"KERI10JSON00012b_",
"t":"icp",
"d":"ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"i":"ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"s":"0",
"kt":"1",
"k":["DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"],
// ...
}
would result in a DID document with the following verification methods array:
"verificationMethod": [
{
"id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"type": "JsonWebKey",
"controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"publicKeyJwk": {
"kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"kty": "OKP",
"crv": "Ed25519",
"x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs"
}
}
]
§ Secp256k1
- Secp256k1 public keys MUST be converted to a verification method with a
type of
JsonWebKeyandpublicKeyJwkproperty whose value is generated by decoding the CESR representation of the public key out of the KEL and into its binary form (minus the leading ‘1AAA’ or ‘1AAB’ CESR codes) and generating the corresponding representation of the key in JSON Web Key form.
For example, a KERI AID with only the following inception event in its KEL:
{
"v": "KERI10JSON0001ad_",
"t": "icp",
"d": "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2",
"i": "EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2",
"s": "0",
"kt": "1",
"k": [
"1AAAAmbFVu-Wf8NCd63B9V0zsy7EgB_ocX2_n_Nh1FCmgF0Y",
]
// ...
}
would result in a DID document with the following verification methods array:
"verificationMethod": [
{
"id": "#1AAAAmbFVu-Wf8NCd63B9V0zsy7EgB_ocX2_n_Nh1FCmgF0Y",
"type": "JsonWebKey",
"controller": "did:webs:example.com:EDP1vHcw_wc4M__Fj53-cJaBnZZASd-aMTaSyWEQ-PC2",
"publicKeyJwk": {
"kid": "1AAAAmbFVu-Wf8NCd63B9V0zsy7EgB_ocX2_n_Nh1FCmgF0Y",
"kty": "EC",
"crv": "secp256k1",
"x": "ZsVW75Z_w0J3rcH1XTOzLsSAH-hxfb-Q82HUUKaAXRg",
"y": "Lu6Uw785U3K05D-NPNoUInHPNUz9cGqWwjKjm5KL8FI"
}
}
]
§ Secp256r1
- Secp256r1 public keys MUST be converted to a verification method with a
type of
JsonWebKeyandpublicKeyJwkproperty whose value is generated by decoding the CESR representation of the public key out of the KEL and into its binary form (minus the leading ‘1AAI’ or ‘1AAJ’ CESR codes) and generating the corresponding representation of the key in JSON Web Key form.
The following example shows the encoding shape for a Secp256r1 key. The AID and key material are illustrative of structure only and are not a verified live inception event.
For example, a KERI AID with only the following inception event in its KEL:
{
"v": "KERI10JSON0001ad_",
"t": "icp",
"d": "EHs9k2mQpL7vNxR4wYtUcA1bZdF3gJhK8mNoPqRsTuVw",
"i": "EHs9k2mQpL7vNxR4wYtUcA1bZdF3gJhK8mNoPqRsTuVw",
"s": "0",
"kt": "1",
"k": [
"1AAIKs8mNpQ2vWxYzAbCdEfGhIjKlMnOpQrStUvWxYz01234"
]
// ...
}
would result in a DID document with the following verification methods array:
"verificationMethod": [
{
"id": "#1AAIKs8mNpQ2vWxYzAbCdEfGhIjKlMnOpQrStUvWxYz01234",
"type": "JsonWebKey",
"controller": "did:webs:example.com:EHs9k2mQpL7vNxR4wYtUcA1bZdF3gJhK8mNoPqRsTuVw",
"publicKeyJwk": {
"kid": "1AAIKs8mNpQ2vWxYzAbCdEfGhIjKlMnOpQrStUvWxYz01234",
"kty": "EC",
"crv": "secp256r1",
"x": "xYz9AbCdEfGhIjKlMnOpQrStUvWx0123456789abcde",
"y": "yZ0BcDeFgHiJkLmNoPqRsTuVwXyZaBcDeFgHiJkLmNo"
}
}
]
§ Thresholds
- If the current signing keys threshold (the value of the
ktfield) is a string containing a number that is greater than 1, or if it is an array containing fractionally weighted thresholds, then in addition to the verification methods generated according to the rules in the previous sections, another verification method with a type ofConditionalProof2022MUST be generated in the DID document.-
It MUST be constructed according to the following rules:
- The
idproperty of the verification method MUST be a relative DID URL and use the AID as the value of the fragment component, e.g.,"id": "#<aid>". - The
controllerproperty of the verification method MUST be the value of theidproperty of the DID document. - If the value of the
ktfield is a string containing a number that is greater than 1 then the following rules MUST be applied:- The
thresholdproperty of the verification method MUST be the integer value of thektfield in the current key state. - The
conditionThresholdproperty of the verification method MUST contain an array. For each key listed in the array value of thekfield in the key state:- The relative DID URL corresponding to the key MUST be added
to the array value of the
conditionThresholdproperty.
- The relative DID URL corresponding to the key MUST be added
to the array value of the
- The
- If the value of the
ktfield is an array containing fractionally weighted thresholds then the following rules MUST be applied:- The
thresholdproperty of the verification method MUST be the lowest common denominator (LCD) of all the fractions in thektarray. - The
conditionWeightedThresholdproperty of the verification method MUST contain an array. For each key listed in the array value of thekfield in the key state, and for each corresponding fraction listed in the array value of thektfield:- A JSON object MUST be added to the array value of the
conditionWeightedThresholdproperty. - The JSON object MUST contain a property
conditionwhose value is the relative DID URL corresponding to the key. - The JSON object MUST contain a property
weightwhose value is the numerator of the fraction after it has been expanded over the lowest common denominator (LCD) of all the fractions.
- A JSON object MUST be added to the array value of the
- The
For example, a KERI AID with only the following inception event in its KEL, and with a
ktvalue greater than 1:{ "v": "KERI10JSON0001b7_", "t": "icp", "d": "Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "i": "Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "s": "0", "kt": "2", // Signing Threshold "k": [ "1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", // Secp256k1 Key "DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", // Ed25519 Key "DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu" // Ed25519 Key ], }results in a DID document with the following verification methods array:
{ "verificationMethod": [ { "id": "#Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "type": "ConditionalProof2022", "controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "threshold": 2, "conditionThreshold": [ "#1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", "#DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", "#DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu" ] }, { "id": "#1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", "type": "JsonWebKey", "controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "publicKeyJwk": { "kid": "1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", "kty": "EC", "crv": "secp256k1", "x": "NtngWpJUr-rlNNbs0u-Aa8e16OwSJu6UiFf0Rdo1oJ4", "y": "qN1jKupJlFsPFc1UkWinqljv4YE0mq_Ickwnjgasvmo" } }, { "id": "#DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", "type": "JsonWebKey", "controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "publicKeyJwk": { "kid": "DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", "kty": "OKP", "crv": "Ed25519", "x": "A-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE" } }, { "id": "#DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu", "type": "JsonWebKey", "controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "publicKeyJwk": { "kid": "DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu", "kty": "OKP", "crv": "Ed25519", "x": "LWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNws" } } ] }For example, a KERI AID with only the following inception event in its KEL, and a
ktcontaining fractionally weighted thresholds:{ "v": "KERI10JSON0001b7_", "t": "icp", "d": "Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "i": "Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "s": "0", "kt": ["1/2", "1/3", "1/4"], // Signing Threshold "k": [ "1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", // Secp256k1 Key "DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", // Ed25519 Key "DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu" // Ed25519 Key ], }would result in a DID document with the following verification methods array:
{ "verificationMethod": [ { "id": "#Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "type": "ConditionalProof2022", "controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "threshold": 12, "conditionWeightedThreshold": [ { "condition": "#1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", "weight": 6 }, { "condition": "#DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", "weight": 4 }, { "condition": "#DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu", "weight": 3 } ] }, { "id": "#1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", "type": "JsonWebKey", "controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "publicKeyJwk": { "kid": "1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", "kty": "EC", "crv": "secp256k1", "x": "NtngWpJUr-rlNNbs0u-Aa8e16OwSJu6UiFf0Rdo1oJ4", "y": "qN1jKupJlFsPFc1UkWinqljv4YE0mq_Ickwnjgasvmo" } }, { "id": "#DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", "type": "JsonWebKey", "controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "publicKeyJwk": { "kid": "DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", "kty": "OKP", "crv": "Ed25519", "x": "A-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE" } }, { "id": "#DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu", "type": "JsonWebKey", "controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M", "publicKeyJwk": { "kid": "DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu", "kty": "OKP", "crv": "Ed25519", "x": "LWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNws" } } ] } - The
-
Alternate verification method encodings such as Ed25519VerificationKey2020,
publicKeyMultibase, or CesrKey MAY be returned when requested via the
transformKeys DID parameter. See
Support for transformKeys.
§ Verification Relationships
This section is normative.
did:webs commits the same keys for both authentication and assertion, a
design facilitated by being built upon KERI. A conforming did:webs DID
document MUST include both the authentication and assertionMethod
properties, generated according to the rules below. A did:webs DID
document MAY also include other verification relationship properties.
- If the value of
kt== 1 then the following rules MUST be applied:- For each public key in
kand its corresponding verification method, the DID document MUST include that verification method in bothauthenticationandassertionMethod.- The
authenticationverification relationship SHALL define that the DID controller can authenticate using each key. - The
assertionMethodverification relationship SHALL define that the DID controller can express claims using each key.
- The
- For each public key in
- If the value of
kt> 1 or if the value ofktis an array containing fractionally weighted thresholds then the following rules MUST be applied:- For the verification method of type
ConditionalProof2022(see section Thresholds), the DID document MUST include that verification method in bothauthenticationandassertionMethod.- The
authenticationverification relationship SHALL define that the DID controller can authenticate using a combination of multiple keys above the threshold. - The
assertionMethodverification relationship SHALL define that the DID controller can express claims using a combination of multiple keys above the threshold.
- The
- For the verification method of type
- References to verification methods in the DID document MUST use the
relative form of the identifier, e.g.,
"authentication": ["#<identifier>"].
For example, a KERI AID with only the following inception event in its KEL:
{
"v":"KERI10JSON00012b_",
"t":"icp",
"d":"ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"i":"ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"s":"0",
"kt":"1",
"k":["DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"],
// ...
}
would result in a DID document with the following verification methods array and verification relationships:
"verificationMethod": [
{
"id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"type": "JsonWebKey",
"controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"publicKeyJwk": {
"kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"kty": "OKP",
"crv": "Ed25519",
"x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs"
}
}
],
"authentication": [
"#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"
],
"assertionMethod": [
"#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"
]
Private keys of a KERI AID can be used to sign a variety of data. This includes but is not limited to logging into a website, challenge-response exchanges, credential issuances, etc.
For more information, see the key agreement and other key commitments section in the Implementors Guide.
§ Service Endpoints
This section is normative.
did:websDIDs MUST support service endpoints, including types declared in the DID Specification Registries, such as DIDCommMessaging.
For additional details about the mapping between KERI events and the Service Endpoints in the DID document, such as
- witness,
- mailbox,
- delegator OOBI, and
- agent service endpoints,
see Service Endpoint KERI events.
It is important to note that DID document service endpoints are different than the KERI service endpoints detailed in KERI Service Endpoints as DID document metadata.
§ KERI Service Endpoints as DID document metadata
-
did:websendpoints MUST be specified using the two data sets KERI uses to define service endpoints: Location Schemes and Endpoint Role Authorizations.- Both MUST be expressed in KERI
rpyevents. - For URL scheme endpoints that an AID has exposed,
did:websDIDs MUST use Location Schemes URLs. - For endpoints that relate a role of one AID to another,
did:websDIDs MUST use KERI Endpoint Role Authorizations.
For example, the following
rpymethod declares that the AIDEIDJUg2eR8YGZssffpuqQyiXcRVz2_Gw_fcAVWpUMie1exposes the URLhttp://127.0.0.1:3901/for schemehttp:{ // ... "t": "rpy", "r": "/loc/scheme", "a": { "eid": "EIDJUg2eR8YGZssffpuqQyiXcRVz2_Gw_fcAVWpUMie1", "scheme": "http", "url": "http://127.0.0.1:3901/" } }For example, the AID listed in
cidis the source of the authorization, theroleis the role and the AID listed in theeidfield is the target of the authorization. So in this exampleEOGL1KGpOnRaZDIB11uZDCkhHs52_MtMXHd7EqUqwtA3is being authorized as an Agent forEIDJUg2eR8YGZssffpuqQyiXcRVz2_Gw_fcAVWpUMie1.{ // ... "t": "rpy", "r": "/end/role/add", "a": { "cid": "EIDJUg2eR8YGZssffpuqQyiXcRVz2_Gw_fcAVWpUMie1", "role": "agent", "eid": "EOGL1KGpOnRaZDIB11uZDCkhHs52_MtMXHd7EqUqwtA3" } } - Both MUST be expressed in KERI
-
KERI service endpoints roles beyond
witnessSHOULD be defined using Location Scheme and Endpoint Authorization records in KERI. See the KERI specification for more information about KERI roles.
In KERI, service endpoints are defined by 2 sets of signed data using Best Available Data - Read, Update, Nullify (BADA-RUN) rules for data processing. The protocol ensures that all data is signed in transport and at rest and versioned to ensure only the latest signed data is available.
§ Transformation to did:web DID document
This section is normative.
When transforming a did:webs DID document to the corresponding did:web DID document
the following rules determine what MUST change to make a valid, transformed did:web
version of the did:webs DID document.
- A conforming implementation MUST NOT perform this transformation unless a
valid, unrevoked designated aliases ACDC in the KERI event stream
authorizes both the
did:webssubject DID and the correspondingdid:webDID formed by replacing thedid:websprefix withdid:web. See Designated Aliases and Also Known As.
Without that authorization, a did:web form of a did:webs DID document is
not a valid did:webs publication. When the precondition holds, this
transformation rewrites subject-identifying DIDs that use the did:webs
prefix: the top-level id and controller, every verificationMethod
controller that equals the subject DID, and the reciprocal entry in
alsoKnownAs.
-
Transformation of the
did:websform of the DID document to adid:webDID document MUST do the following:- Starting from the top-level
id(adid:websDID), form the correspondingdid:webDID by replacing thedid:websprefix withdid:web. - The top-level
idandcontrollerproperty values MUST be set to that correspondingdid:webDID. - For every
verificationMethodentry whosecontrollerequals the originaldid:webssubject DID, thecontrollerMUST be set to the correspondingdid:webDID. - The
alsoKnownAsarray MUST replace the correspondingdid:webentry with the originaldid:webssubject DID, so the transformed document lists thedid:websform as an alias of thedid:websubject. - All other content of the DID document MUST NOT be modified.
For example, this transformation is used during the Create DID method operation, given the following
did:websDID document:{ "id": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "verificationMethod": [ { "id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr", "type": "JsonWebKey", "controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "publicKeyJwk": { "kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr", "kty": "OKP", "crv": "Ed25519", "x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs" } } ], "authentication": [ "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr" ], "assertionMethod": [ "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr" ], "service": [], "alsoKnownAs": [ "did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:keri:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe" ] }the result of the transformation algorithm is the following
did:webDID document:{ "id": "did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "controller": "did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "verificationMethod": [ { "id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr", "type": "JsonWebKey", "controller": "did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "publicKeyJwk": { "kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr", "kty": "OKP", "crv": "Ed25519", "x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs" } } ], "authentication": [ "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr" ], "assertionMethod": [ "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr" ], "service": [], "alsoKnownAs": [ "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:keri:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe" ] } - Starting from the top-level
§ Transformation to did:webs DID document
This section is normative.
When transforming a did:web DID document to the corresponding did:webs
DID document the following rules determine what MUST change to make a valid,
transformed did:webs version of the did:web DID document.
- A conforming implementation MUST NOT perform this transformation unless a
valid, unrevoked designated aliases ACDC in the KERI event stream
authorizes both the
did:websubject DID and the correspondingdid:websDID formed by replacing thedid:webprefix withdid:webs. An arbitrarydid:webDID document MUST NOT be treated as adid:websDID document merely because its method-specific identifier ends in an AID. See Designated Aliases and Also Known As.
When the precondition holds, this transformation rewrites subject-identifying
DIDs that use the did:web prefix: the top-level id and controller, every
verificationMethod controller that equals the subject DID, and the
reciprocal entry in alsoKnownAs.
-
Transformation of the
did:webDID document to adid:websDID document MUST do the following:- Starting from the top-level
id(adid:webDID), form the correspondingdid:websDID by replacing thedid:webprefix withdid:webs. - The top-level
idandcontrollerproperty values MUST be set to that correspondingdid:websDID. - For every
verificationMethodentry whosecontrollerequals the originaldid:websubject DID, thecontrollerMUST be set to the correspondingdid:websDID. - The
alsoKnownAsarray MUST replace the correspondingdid:websentry with the originaldid:websubject DID, so the transformed document lists thedid:webform as an alias of thedid:webssubject. - All other content of the DID document MUST NOT be modified.
- Starting from the top-level
-
A
did:websresolver MUST use this transformation during the Read (Resolve) DID method operation.For example, given the following
did:webDID document:{ "id": "did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "controller": "did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "verificationMethod": [ { "id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr", "type": "JsonWebKey", "controller": "did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "publicKeyJwk": { "kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr", "kty": "OKP", "crv": "Ed25519", "x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs" } } ], "authentication": [ "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr" ], "assertionMethod": [ "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr" ], "service": [], "alsoKnownAs": [ "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:keri:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe" ] }the result of the transformation algorithm is the following
did:websDID document:{ "id": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "verificationMethod": [ { "id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr", "type": "JsonWebKey", "controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "publicKeyJwk": { "kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr", "kty": "OKP", "crv": "Ed25519", "x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs" } } ], "authentication": [ "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr" ], "assertionMethod": [ "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr" ], "service": [], "alsoKnownAs": [ "did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe", "did:keri:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe" ] }
§ Full Example
To walk through a real-world example, please see the GETTING STARTED guide in the did:webs Reference Implementation as it walks users through many did:webs related tasks (and associated KERI commands) to demonstrate how they work together.
The following blocks contain a fully annotated example of a KERI event stream
for a KERI AID, including an inception event, interaction events
that anchor TEL and ACDC data, reply (rpy) events for a witness endpoint, TEL
registry and issuance events, and a designated aliases ACDC.
- The inception event designates a witness in the
bfield, a signing key in thekfield, and a pre-rotated next key in thenfield. - Interaction events cryptographically anchor the designated aliases TEL and ACDC.
- Reply (
rpy) events specify Location Scheme and Endpoint Role Authorization data for the witness. - The designated aliases ACDC authorizes the
did:websanddid:webhost and path for the AID.
Below, we show the KERI event stream associated with the resulting DID document.
{
"v": "KERI10JSON000159_",
"t": "icp",
"d": "EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"i": "EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP", // controller AID
"s": "0",
"kt": "1", // Signing Threshold
"k": [
"DJg7AQUSKAEo-Pkgj4tVF7L0-FqJt0QFxFh5878AcZv6" // Ed25519 Key
],
"nt": "1",
"n": [
"EIzv5mDvyc-ftAyn06LyO0HvzfG7dJqx1zvYWGGIGiYp"
],
"bt": "1",
"b": [
"BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q"
],
"c": [],
"a": []
}
// series of events establishing a witness service
{
"v": "KERI10JSON00013a_",
"t": "ixn",
"d": "EMllQ2kDZp9OnErTfJkzqbZN4hoH-rATBvVyASczJFIN",
"i": "EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"s": "1",
"p": "EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"a": [
{
"i": "EBXOxFQrvOxBPb7DiRaTlZNLvX5RbL5cO05MdA35Z0vl",
"s": "0",
"d": "EBXOxFQrvOxBPb7DiRaTlZNLvX5RbL5cO05MdA35Z0vl"
}
]
}
{
"v": "KERI10JSON00013a_",
"t": "ixn",
"d": "EGZKcIKf9euYtsGJI5RxWoL6sprJS8Rt6Em97X85tJPq",
"i": "EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"s": "2",
"p": "EMllQ2kDZp9OnErTfJkzqbZN4hoH-rATBvVyASczJFIN",
"a": [
{
"i": "EA7VoZA6B9hmhmJAuWUU4lNxRBIQ3sv6JZXGeLnJCRGZ",
"s": "0",
"d": "EBCVtYB15CiJg79EciGiAkQaU3L-4oCx7qcPqUsQGZqr"
}
]
}
{
"v": "KERI10JSON000109_",
"t": "rpy",
"d": "EAVexvYonCqxXNNQ8208SLo3Afcg9W7d7eiNJ2FC8tMe",
"dt": "2025-04-16T16:50:26.283032-07:00",
"r": "/loc/scheme",
"a": {
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q",
"scheme": "https",
"url": "https://wit1.did-webs-service:5641/"
}
}
{
"v": "KERI10JSON000105_",
"t": "rpy",
"d": "ENAFmV935lXzYQfDKwgjU08o-AC5ZfqhGR2dtgka1kvq",
"dt": "2025-04-16T16:50:26.283032-07:00",
"r": "/loc/scheme",
"a": {
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q",
"scheme": "tcp",
"url": "tcp://wit1.did-webs-service:5631/"
}
}
{
"v": "KERI10JSON000116_",
"t": "rpy",
"d": "EIUHDBQmdOf7B0TwHqREnB-_gGYa2b9exOcLJMylrp6P",
"dt": "2025-04-16T16:50:26.283032-07:00",
"r": "/end/role/add",
"a": {
"cid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q",
"role": "controller",
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q"
}
}
// issuance of designated alias ACDC authorizing host information for did:webs and did:web
{
"v": "KERI10JSON0000ff_",
"t": "vcp",
"d": "EBXOxFQrvOxBPb7DiRaTlZNLvX5RbL5cO05MdA35Z0vl",
"i": "EBXOxFQrvOxBPb7DiRaTlZNLvX5RbL5cO05MdA35Z0vl",
"ii": "EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"s": "0",
"c": [
"NB"
],
"bt": "0",
"b": [],
"n": "0AAuhv_GQrchdHyeZGXUMFw1"
}
{
"v": "KERI10JSON0000ed_",
"t": "iss",
"d": "EBCVtYB15CiJg79EciGiAkQaU3L-4oCx7qcPqUsQGZqr",
"i": "EA7VoZA6B9hmhmJAuWUU4lNxRBIQ3sv6JZXGeLnJCRGZ",
"s": "0",
"ri": "EBXOxFQrvOxBPb7DiRaTlZNLvX5RbL5cO05MdA35Z0vl",
"dt": "2026-02-06T21:44:36.788115+00:00"
}
{
"v": "ACDC10JSON000574_",
"d": "EA7VoZA6B9hmhmJAuWUU4lNxRBIQ3sv6JZXGeLnJCRGZ",
"i": "EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"ri": "EBXOxFQrvOxBPb7DiRaTlZNLvX5RbL5cO05MdA35Z0vl",
"s": "EN6Oh5XSD5_q2Hgu-aqpdfbVepdpYpFlgz6zvJL5b_r5",
"a": {
"d": "ELt92UqnBvlk8UOWpK2uUWlXEohe6j_JEVP4zvRY3HB-",
"dt": "2026-02-06T21:44:36.788115+00:00",
"ids": [
"did:web:did-webs-service%3a7702:EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"did:webs:did-webs-service%3a7702:EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP"
]
},
"r": {
"d": "EEVTx0jLLZDQq8a5bXrXgVP0JDP7j8iDym9Avfo8luLw",
"aliasDesignation": {
"l": "The issuer of this ACDC designates the identifiers in the ids field as the only allowed namespaced aliases of the issuer's AID."
},
"usageDisclaimer": {
"l": "This attestation only asserts designated aliases of the controller of the AID, that the AID controlled namespaced alias has been designated by the controller. It does not assert that the controller of this AID has control over the infrastructure or anything else related to the namespace other than the included AID."
},
"issuanceDisclaimer": {
"l": "All information in a valid and non-revoked alias designation assertion is accurate as of the date specified."
},
"termsOfUse": {
"l": "Designated aliases of the AID must only be used in a manner consistent with the expressed intent of the AID controller."
}
}
}
Resulting DID document:
{
"id": "did:webs:did-webs-service%3a7702:EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"controller": "did:webs:did-webs-service%3a7702:EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"verificationMethod": [
{
"id": "#DJg7AQUSKAEo-Pkgj4tVF7L0-FqJt0QFxFh5878AcZv6",
"type": "JsonWebKey",
"controller": "did:webs:did-webs-service%3a7702:EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"publicKeyJwk": {
"kid": "DJg7AQUSKAEo-Pkgj4tVF7L0-FqJt0QFxFh5878AcZv6",
"kty": "OKP",
"crv": "Ed25519",
"x": "mDsBBRIoASj4-SCPi1UXsvT4Wom3RAXEWHnzvwBxm_o"
}
}
],
"authentication": [
"#DJg7AQUSKAEo-Pkgj4tVF7L0-FqJt0QFxFh5878AcZv6"
],
"assertionMethod": [
"#DJg7AQUSKAEo-Pkgj4tVF7L0-FqJt0QFxFh5878AcZv6"
],
"service": [
{
"id": "#BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q/witness",
"type": "witness",
"serviceEndpoint": {
"https": "https://wit1.did-webs-service:5641/",
"tcp": "tcp://wit1.did-webs-service:5631/"
}
}
],
"alsoKnownAs": [
"did:web:did-webs-service%3a7702:EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP",
"did:keri:EEOqE46OOSl1k1JO3ggQTGuQR3nnWE8bYjOPnJ53m8CP"
]
}
§ Basic KERI event details
This section is normative.
DID documents introduced the core KERI event stream and related DID document concepts. This section provides additional details regarding the basic types of KERI events and how they relate to the DID document.
§ Key state events
- When processing the KERI event stream
did:websMUST account for two broad types of key state events (KERI parlance is ‘establishment events’) that can alter the key state of the AID. - Any change in key state of the AID MUST be reflected in the DID document.
- If a key state event does not commit to a future set of rotation key hashes, then the AID SHALL NOT be rotated to new keys in the future (KERI parlance is that the key state of the AID becomes ‘non-transferable’).
- If a key state event does commit to a future set of rotation key hashes,
then any future key state rotation MUST be to those commitment keys.
This foundation of pre-rotation is post-quantum safe and allows
the
did:webscontroller to recover from key compromise. - The Inception event MUST be the first event in the KEL
that establishes the AID.
- This MUST define the initial key set
- If the controller(s) desire future key rotation (transfer) then the inception event MUST commit to a set of future rotation key hashes.
- When processing the KERI event stream, if there are no rotation events after the inception event, then this is the current key state of the AID and MUST be reflected in the DID document as specified in Verification Methods and Verification Relationships.
- Rotation events MUST come after inception events.
- If the controller(s) desires future key rotation (transfer) then the rotation event MUST commit to a set of future rotation key hashes.
- Rotation events MUST only change the key state to the previously committed to rotation keys.
- Either the inception event or the last rotation event, if any, is the current key state of the AID and MUST be reflected in the DID document as specified in Verification Methods and Verification Relationships.
For inception events, rotation events, and pre-rotation (future rotation key commitment), see the KERI specification and Pre-rotation in this document. Worked examples of inception and interaction events appear in Full Example.
§ Delegation KERI event details
This section focuses on delegation relationships between KERI AIDs. DID documents introduced the core KERI event stream and related DID document concepts. This section provides additional details regarding the types of KERI delegation events and how they relate to the DID document. See Basic KERI event details for further detail on basic KERI event types including how they relate to the DID document.
§ Delegation key state events
- All delegation relationships MUST start with a delegated inception event.
- Any change to the delegated inception event key state or delegated rotation event key state MUST be the result of a delegated rotation event.
Delegated inception event: Establishes a delegated identifier and identifies its delegator. Acceptance of the event requires verification of the corresponding anchoring seal in the delegator’s KEL.
Delegated rotation event: Updates the delegated identifier
key state. Acceptance of the event requires verification of the corresponding
anchoring seal in the delegator’s KEL. A delegated rotation with an empty Next
(n) field rotates to a null set of pre-rotated keys, thereby abandoning the
delegated identifier; no further key events are allowed in its KEL.
See the KERI specification for an example of a delegated inception and rotation events.
Delegation service endpoints in the DID document are defined in the next section.
§ Service Endpoint Event Details
This section is normative.
In did:webs, KERI-derived service endpoints are defined by Location Scheme
(/loc/scheme) reply (rpy) messages and, for roles other than witness,
Endpoint Role Authorization (/end/role/add) rpy messages in the
KERI event stream. Location Scheme records declare URL(s) for a
given scheme for an AID; Endpoint Role Authorization relates a role (e.g.
mailbox, agent) of one AID to another. See
KERI Service Endpoints as DID document metadata.
For resolution of the current DID state, a did:webs resolver projects
services only from accepted current KERI key state and the latest reply state
accepted under KERI BADA rules. The effective KEL witness list supplies witness
authorization. Current Endpoint Role Authorization state supplies mailbox and
agent authorization, and current Location Scheme state supplies endpoint URLs.
Superseded, cut, nullified, escrowed, or otherwise unaccepted state is not
projected.
When versionId selects historical state, the selected KEL version supplies
KEL-derived authorization, while endpoint discovery continues to use the latest
reply state accepted under KERI BADA rules at resolution time, as described in
Support for versionId.
When the event stream (or equivalent key state and endpoint data) for a
did:webs DID establishes a witness, mailbox, or agent the DID document
MUST include the associated service endpoint(s) in its service array.
§ Witness Service Endpoint
- A witness service endpoint is produced when (1) the controller AID’s
KEL designates the witness in its witness list (inception or
latest rotation event
bfield), and (2) one or more Location Schemerpymessages withr/loc/schemedeclare URLs for that witness AID (a.eid) per scheme. The witness role is thus established by key state, not by an Endpoint Role Authorizationrpy. - The DID document service entry SHALL use
typewitness,idrelative to the DID of the form#<witness-aid>/witness, andserviceEndpointas an object whose keys are scheme names and values are the declared URLs.
Location Scheme examples (witness AID declares https and tcp URLs):
{
// ...
"t": "rpy",
"r": "/loc/scheme",
"a": {
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q",
"scheme": "https",
"url": "https://wit1.example.com:5641/"
}
}
{
// ...
"t": "rpy",
"r": "/loc/scheme",
"a": {
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q",
"scheme": "tcp",
"url": "tcp://wit1.example.com:5631/"
}
}
Resulting witness service entry:
{
"id": "#BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q/witness",
"type": "witness",
"serviceEndpoint": {
"https": "https://wit1.example.com:5641/",
"tcp": "tcp://wit1.example.com:5631/"
}
}
§ Mailbox Service Endpoint
- A mailbox service endpoint is produced when (1) an Endpoint Role
Authorization
rpywithr/end/role/addanda.rolemailboxdesignates the mailbox AID (a.eid) for the controller AID (a.cid), and (2) one or more Location Schemerpymessages withr/loc/schemedeclare URLs for that mailbox AID. Implementations obtain mailbox endpoints from Endpoint Role data (e.g. KERIendstable keyed by controller and role) plus Location Scheme data (e.g.locstable). - The DID document service entry SHALL use
typemailbox,idrelative to the DID of the form#<mailbox-aid>/mailbox, andserviceEndpointas an object mapping scheme names to URLs (or a single URL when only one scheme applies).
Endpoint Role Authorization example (controller designates mailbox):
{
// ...
"t": "rpy",
"r": "/end/role/add",
"a": {
"cid": "Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M",
"role": "mailbox",
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q"
}
}
Location Scheme example (mailbox AID declares http URL):
{
// ...
"t": "rpy",
"r": "/loc/scheme",
"a": {
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q",
"scheme": "http",
"url": "http://mailbox.example.com:5635/"
}
}
Resulting mailbox service entry:
{
"id": "#BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q/mailbox",
"type": "mailbox",
"serviceEndpoint": {
"http": "http://mailbox.example.com:5635/"
}
}
§ Delegator Service Endpoint
If the first event in the KEL for a did:webs DID is a delegated
inception event of type dip then it MUST include a delegator service
endpoint in its DID document as follows.
- A delegated AID MUST include a service endpoint in its DID document that references its delegator.
- When a delegator service endpoint is present, it MUST conform to the
following requirements:
- The service
typeproperty MUST be set toDelegatorOOBI. - The service
idproperty MUST be the self-addressing identifier (SAID) of the seal (anchor block) in the delegator’s KEL that commits to the delegate’s delegated inception event. - The service
serviceEndpointproperty MUST be a valid out-of-band introduction (OOBI) URL that resolves to the delegator’s AID.
- The service
- The delegator service endpoint only indicates where the delegator’s KERI state may be retrieved. Its presence MUST NOT be treated as proof or validation of the delegation relationship. A KERI-aware verifier validates the relationship independently by retrieving the delegator’s KEL and verifying the source seal that authorizes the delegated event.
For example, a did:webs DID that is a delegated AID MUST include, in its
service array of the DID document, a delegator service endpoint similar
to the following:
{
"service": [{
"id": "EDEvmKvGFjuip-J5dDw7sbVHxXA22s-pBO764CivsFt4",
"type": "DelegatorOOBI",
"serviceEndpoint": "http://example.com:3902/oobi/ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
}]
}
In this example, the id field contains the bare SAID of the seal in
the delegator’s KEL that anchors the delegation commitment. This is an
opaque, KERI-specific correlation value, not a DID-resolution target; generic
DID clients are not required to interpret or dereference it. A KERI-aware
verifier can use the serviceEndpoint OOBI URL to retrieve the delegator’s key
state and use the seal SAID to locate the source seal in the authorizing event,
such as an interaction event, in the delegator’s KEL. Neither the bare SAID, the
OOBI URL, nor the presence of the service entry proves delegation.
§ Agent Service Endpoint
- An agent service endpoint is produced when (1) an Endpoint Role
Authorization
rpywithr/end/role/addanda.roleagentdesignates the agent AID (a.eid) for the controller AID (a.cid), and (2) one or more Location Schemerpymessages withr/loc/schemedeclare URLs for that agent AID. Implementations obtain agent endpoints from Endpoint Role data (e.g. KERIendstable) plus Location Scheme data (e.g.locstable). - The DID document service entry SHALL use
typeagentandserviceEndpointas an object mapping scheme names to URLs or a single URL, consistent with KERI Service Endpoints as DID document metadata.
Endpoint Role Authorization example (controller designates agent):
{
// ...
"t": "rpy",
"r": "/end/role/add",
"a": {
"cid": "Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M",
"role": "agent",
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q"
}
}
Location Scheme example (agent AID declares http URL):
{
// ...
"t": "rpy",
"r": "/loc/scheme",
"a": {
"eid": "BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q",
"scheme": "http",
"url": "http://agent.example.com:5636/"
}
}
Resulting agent service entry:
{
"id": "#BJqHtDoLT_K_XyOgr2ejBOqD9276TYMTg2EEqWKs-V0q/agent",
"type": "agent",
"serviceEndpoint": {
"http": "http://agent.example.com:5636/"
}
}
§ Designated Aliases
- An AID controller SHALL authorize designated aliases by issuing a
Designated aliases verifiable attestation as an ACDC.
- This attestation MUST contain a set of AID controlled identifiers that the AID controller authorizes.
- Authorized identifiers MUST be reflected in the DID document and DID document metadata according to the following rules:
| Identifier kind | DID document (alsoKnownAs) |
DID document metadata (equivalentId) |
|---|---|---|
Other same-AID did:webs DIDs |
MUST appear in alsoKnownAs |
MUST appear in equivalentId |
Corresponding or alternate did:web DIDs with the same AID |
MUST appear in alsoKnownAs |
MUST NOT appear in equivalentId |
did:keri:<AID> |
MUST appear in alsoKnownAs |
MUST NOT appear in equivalentId |
The resolved DID itself appears as the document id and need not also appear
in equivalentId. Authorization of the resolved DID comes from its presence
in a valid, unrevoked designated aliases ACDC (see
Also Known As and
Use of equivalentId).
equivalentId is DID document metadata, not a DID document property.
§ Designated Aliases event details
This is an example designated aliases ACDC attestation showing five designated aliases:
{
"v": "ACDC10JSON000574_",
"d": "EA7VoZA6B9hmhmJAuWUU4lNxRBIQ3sv6JZXGeLnJCRGZ",
"i": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"ri": "EBXOxFQrvOxBPb7DiRaTlZNLvX5RbL5cO05MdA35Z0vl",
"s": "EN6Oh5XSD5_q2Hgu-aqpdfbVepdpYpFlgz6zvJL5b_r5",
"a": {
"d": "ELt92UqnBvlk8UOWpK2uUWlXEohe6j_JEVP4zvRY3HB-",
"dt": "2026-02-06T21:44:36.788115+00:00",
"ids": [
"did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
]
},
"r": {
...rules section
}
}
The resulting resolution result based on the designated aliases attestation above contains:
alsoKnownAsidentifiers as follows:- the authorized
did:webversion of the identifier. did:web:example.comis an alternative, authorizeddid:webidentifier.- the
did:webs:foo.comidentifier offers an alternativedid:websendpoint. - the authorized
did:webequivalent of thedid:webs:foo.comidentifier. - the
did:keriidentifier is always included inalsoKnownAs(see Also Known As).
- the authorized
equivalentIdmetadata listing the other authorized same-AIDdid:websidentifier (did:webs:foo.com:...). Only otherdid:websidentifiers appear inequivalentId; the resolved DID itself is the documentid, not anequivalentIdentry. See Use ofequivalentId.
{
"didDocument": {
"id": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"verificationMethod": [
{
"id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"type": "JsonWebKey",
"controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"publicKeyJwk": {
"kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"kty": "OKP",
"crv": "Ed25519",
"x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs"
}
}
],
"authentication": [
"#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"
],
"assertionMethod": [
"#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"
],
"service": [],
"alsoKnownAs": [
"did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:keri:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
]
},
"didResolutionMetadata": {
"contentType": "application/did+json",
"retrieved": "2024-04-01T17:43:24Z"
},
"didDocumentMetadata": {
"witnesses": [],
"versionId": "2",
"equivalentId": [
"did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
],
"didDocUrl": "http://did-webs-service:7676/ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe/did.json",
"keriCesrUrl": "http://did-webs-service:7676/ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe/keri.cesr"
}
}
§ DID Parameters
This section is normative.
This section describes the support of the did:webs method for certain
DID parameters.
§ Support for versionId
The did:webs DID method supports the versionId DID parameter. This DID
parameter is defined in the DID specification.
This allows clients to instruct a DID Resolver to return a specific version
of a DID document, as opposed to the latest version. The did:webs DID
method is ideally suited for this functionality, since a continuous,
self-certifying stream of events lies at the heart of the DID method’s
design, see section KERI Fundamentals.
- Valid values for this DID parameter MUST be the sequence numbers of events in the KERI event stream.
- When a
did:websDID is resolved with this DID parameter, adid:websresolver MUST construct the DID document based on an AID’s associated KERI events from the KERI event stream only up to (and including) the event with the sequence number (i.e. thesfield) that corresponds to the value of theversionIdDID parameter.
The version selected by versionId applies to the AID’s KEL and to TEL and
ACDC data whose anchoring KEL events are included at or before the selected
version. It does not select historical KERI reply (rpy) messages used for
endpoint discovery.
Any endpoint-discovery rpy messages returned during resolution are the latest
messages accepted under KERI BADA rules at resolution time. Location Scheme and
Endpoint Role Authorization state is projected from that current reply state.
Consequently, services in a historical DID document represent current discovery
information, not endpoint state as it existed at the requested KEL version.
Historical rpy discovery state is not supported or normatively required by
this specification, and changes only to that state do not create a versionId
or nextVersionId.
See section DID documents for details.
Example:
did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M?versionId=1
§ Support for transformKeys
The did:webs DID method supports the transformKeys DID parameter.
This DID parameter is defined as a DID method
extension.
- This parameter MUST be implemented for a DID Resolver to return
verification methods in a DID document in a desired format, such as
JsonWebKey,Ed25519VerificationKey2020, orCesrKey.
Example:
did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M?transformKeys=CesrKey
§ CesrKey and publicKeyCesr
This specification defines the following DID document extensions:
- Verification method
typeCesrKeyMAY be available in adid:websDID document to express a public key encoded in CESR format. - Verification method property
publicKeyCesrMAY be available in adid:websDID document to provide a string value whose content is the CESR representation of a public key. - The verification method type
CesrKeyMAY be used as the value of thetransformKeysDID parameter.
For example, a KERI AID with only the following inception event in its KEL:
{
"v": "KERI10JSON0001b7_",
"t": "icp",
"d": "Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M",
"i": "Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M",
"s": "0",
"kt": "1",
"k": [
"1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk", // Secp256k1 Key
"DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE", // Ed25519 Key
"DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu" // Ed25519 Key
],
// ...
}
and given the following the DID URL:
did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M?transformKeys=CesrKey
would result in a DID document with the following verification methods array:
{
"verificationMethod": [
{
"id": "#1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk",
"type": "CesrKey",
"controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M",
"publicKeyCesr": "1AAAAg299p5IMvuw71HW_TlbzGq5cVOQ7bRbeDuhheF-DPYk"
},
{
"id": "#DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE",
"type": "CesrKey",
"controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M",
"publicKeyCesr": "DA-vW9ynSkvOWv5e7idtikLANdS6pGO2IHJy7v0rypvE"
},
{
"id": "#DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu",
"type": "CesrKey",
"controller": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M",
"publicKeyCesr": "DLWJrsKIHrrn1Q1jy2oEi8Bmv6aEcwuyIqgngVf2nNwu"
}
]
}
§ DID Metadata
This section is normative.
This section describes the support of the did:webs method for metadata,
including DID resolution metadata and DID document metadata.
This metadata is returned by a DID Resolver in addition to the
DID document. Also see the DID Resolution
specification for further details.
§ DID Resolution Metadata
At the moment, this specification does not define the use of any specific
DID resolution metadata properties in the did:webs method, but
may in the future include various metadata, such as which KERI Watchers were
used during the resolution process.
§ DID document metadata
This section of the specification defines how various DID document metadata
properties are used by the did:webs method.
§ Use of versionId
The versionId DID document metadata property indicates the current
version of the DID document that has been resolved.
- The
did:websversionId MUST be the sequence number (i.e. thesfield) of the last event in the KERI event stream that was used to construct the DID document according to the rules in section DID documents. - If the DID parameter
versionId(see section Support forversionId) was used when resolving thedid:websDID, and if the DID Resolution process was successful, then this corresponding DID document metadata property MUST be guaranteed to be equal to the value of the DID parameter.
Example:
{
"didDocument": {
"id": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M"
// ... other properties
},
"didResolutionMetadata": {
},
"didDocumentMetadata": {
"versionId": "2"
}
}
§ Use of nextVersionId
The nextVersionId DID document metadata property indicates the next
version of the DID document after the version that has been resolved.
- The
did:websnextVersionIdMUST be the sequence number (i.e. thesfield) of the next event in the KERI event stream after the last one that was used to construct the DID document according to the rules in section DID documents. - This DID document metadata property MUST be present if the DID
parameter
versionId(see section Support forversionId) was used when resolving thedid:websDID, and if the value of that DID parameter was not the sequence number of the last event in the KERI event stream.
Example:
{
"didDocument": {
"id": "did:webs:example.com:Ew-o5dU5WjDrxDBK4b4HrF82_rYb6MX6xsegjq4n0Y7M"
// ... other properties
},
"didResolutionMetadata": {
},
"didDocumentMetadata": {
"versionId": "1",
"nextVersionId": "2"
}
}
§ Use of equivalentId
The equivalentId DID document metadata property indicates other DIDs that
refer to the same subject and are logically equivalent to the DID that has
been resolved. It is similar to the alsoKnownAs DID document property (see
section Also Known As), but it has even stronger
semantics, insofar as the logical equivalence is guaranteed by the DID
method itself.
- A
did:websDID MUST NOT successfully resolve unless the resolved DID appears in a valid, unrevoked designated aliases ACDC in the KERI event stream. - The
did:websequivalentIdmetadata property SHOULD contain the other designated aliases that aredid:websDIDs sharing the same AID but differing in the host, port, and/or path portion of the method-specific identifier. Also see section AID controlled identifiers and Designated Aliases. - The resolved DID itself MUST NOT be required to appear in
equivalentId;equivalentIdlists other authorized same-AIDdid:websDIDs.
Note that AID controlled identifiers like
did:webanddid:keriidentifiers with the same AID are not listed inequivalentIdbecause they do not have the same DID method. Adid:webidentifier with the same domain and AID does not have the same security characteristics as thedid:websidentifier. Conversely, adid:keriidentifier with the same AID has the same security characteristics but not the same dependence on the web. For these reasons, they are not listed inequivalentId.
Example:
{
"didDocument": {
"id": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"verificationMethod": [
{
"id": "#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"type": "JsonWebKey",
"controller": "did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"publicKeyJwk": {
"kid": "DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr",
"kty": "OKP",
"crv": "Ed25519",
"x": "evT4j6Yw3uHpwsw5NEmSR8-4x3S-BA-s6Thjd51oeOs"
}
}
],
"authentication": [
"#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"
],
"assertionMethod": [
"#DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"
],
"service": [],
"alsoKnownAs": [
"did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:keri:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
]
},
"didResolutionMetadata": {
"contentType": "application/did+json",
"retrieved": "2024-04-01T17:43:24Z"
},
"didDocumentMetadata": {
"witnesses": [],
"versionId": "2",
"equivalentId": [
"did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
],
"didDocUrl": "http://did-webs-service:7676/ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe/did.json",
"keriCesrUrl": "http://did-webs-service:7676/ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe/keri.cesr"
}
}
§ Security Considerations
This section is normative.
The security of did:webs separates discovery (finding did.json and
keri.cesr on the web) from authenticity (cryptographically verifying the
KERI event stream and deriving the DID document). Authenticity of a
resolved did:webs DID document MUST NOT depend on host honesty. A
conforming resolver MUST establish authenticity by verifying the KERI event
stream and applying the rules in Read (Resolve) and
DID documents.
§ Common security threats
The following maps common threats to the mechanisms this method uses. MUST requirements below are limited to behaviors already required elsewhere in this specification; optional KERI infrastructure is expressed with SHOULD.
- Forgery, malleability, and impersonation of DID document content. A
resolver MUST accept a DID document only when it is derived from a
verified KERI event stream and equals the transformed hosted
did.json, per Read (Resolve). Hosted JSON alone MUST NOT be trusted. - Unauthorized host or path aliases. A resolver MUST NOT treat a
did:websor correspondingdid:webidentifier as authorized unless it appears in a valid, unrevoked designated aliases ACDC, per Designated Aliases. - Key compromise. Controllers SHOULD use KERI pre-rotation and key rotation so that compromise of current signing keys does not allow an attacker to permanently seize the AID. See Key state events.
- Duplicity and eclipse. Controllers and resolvers SHOULD use KERI witnesses and watchers to detect forked or inconsistently published event streams, per AID controlled identifiers.
- Deletion or withholding of history. A single host MAY omit, delay, or
serve stale copies of
did.jsonorkeri.cesr. Controllers MUST continue to publish deactivated artifacts per Deactivate. Resolvers MAY discover alternate locations via designated aliases,equivalentId, or other AID-based discovery; the method does not by itself guarantee availability. - Replay. KERI event verification and, where used, KRAM constrain
replay of signed protocol messages. Resolvers MUST apply KERI verification
rules to the event stream; additional replay protections for discovery
traffic SHOULD follow the KEL / BADA-RUN / KRAM guidance in
Concepts for securing
did:websinformation. - Denial of service and BOLA. Availability of hosts and authorization bugs in surrounding applications are largely outside the scope of this DID method. Hosting SHOULD follow accepted operational practice. The method’s authenticity guarantees remain those of KERI verification even when a host is unavailable or untrustworthy.
§ Using HTTPS
HTTPS protects the confidentiality and integrity of the transport used to
fetch did.json and keri.cesr. It does not, by itself, establish the
authenticity of a did:webs DID document. Perfect protection from
eavesdropping is not always possible with HTTPS.
- URLs of DID documents and KERI event streams SHOULD be hosted according to accepted cybersecurity practice for public HTTPS resources (for example, rate limiting and monitoring appropriate to the deployment).
- A host that uses a fully qualified domain name of the
method-specific identifier MUST be secured by a TLS/SSL
certificate.
- The fully qualified domain name MUST match the common name (or an appropriate subject alternative name) used in the SSL/TLS certificate.
- The name in the SSL/TLS certificate from the server MUST correspond to
the way the server is referenced in the URL. For example, if the URL
includes
www.example.com, the certificate MUST coverwww.example.comas well.
- Unlike
did:web, the URL MAY use an IP address instead.- If it does, then the certificate MUST identify that IP address (for example via common name or subject alternative name).
- The URL and the certificate MUST NOT identify the server in contradictory
ways; subject to that constraint, how the server is identified is flexible.
- The server certificate MAY be self-issued
- OR it MAY chain back to an unknown certificate authority. However, it
MUST be valid for the client to accept it for the HTTPS session:
- The certificate MUST satisfy the client’s active trust requirements such that the client accepts it and uses it to establish the encrypted session.
- Even if the client is permissive about certificate authorities, the certificate MUST have a valid signature, MUST NOT be expired, revoked, or deny-listed, and MUST NOT have broken links in its chain of trust.
- If a URL of a DID document or KERI event stream results in a redirect, each URL in the redirect chain MUST satisfy the same security requirements.
§ International Domain Names
- As with
did:web, implementers ofdid:websSHOULD consider how non-ASCII characters manifest in URLs and DIDs.did:websMUST follow the DID Core identifier syntax which does not allow the direct representation of such characters in method name or method specific identifiers. This prevents adid:websvalue from embodying a homograph attack.- However,
did:websMAY hold data encoded with punycode or percent encoding. This means that IRIs constructed from DID values could contain non-ASCII characters that were not obvious in the DID, surprising a casual human reader. - Caution is RECOMMENDED when treating a
did:websas the equivalent of an IRI. - Treating it as the equivalent of a URL, instead, is RECOMMENDED as it preserves the punycode and percent encoding and is therefore safe.
§ Concepts for securing did:webs information
The following security concepts are used to secure the data, files,
signatures and other information in did:webs.
- All security features and concepts in
did:websMUST use one or more of the following mechanisms:- All data that requires the highest security MUST be KEL backed. This includes any information that needs to be end-verifiably authentic over time:
- All data that does not need to incur the cost of KEL backing
for security but can benefit from the latest data-state such as a
distributed data-base MUST use Best Available Data - Read, Update,
Nullify (BADA-RUN).
- BADA-RUN information MUST be ordered in a consistent way, using the following:
- date-time MUST be used.
- key state MUST be used.
- Discovery information MAY use BADA-RUN because the worst-case
attack on discovery information is a DDoS attack where nothing
gets discovered.
- The controller(s) of the AID for a
did:websidentifier MAY use BADA-RUN for service end-points as discovery mechanisms.
- The controller(s) of the AID for a
- BADA-RUN information MUST be ordered in a consistent way, using the following:
- All data that does not need the security of being KEL backed nor
BADA-RUN SHOULD be served using
KERI Request Authentication Mechanism (KRAM).
- For a
did:websresolver to be trusted it SHOULD use KRAM to access the service endpoints providing KERI event streams for verification of the DID document.
- For a
§ Reducing the attack surface
The above considerations have led us to focus on KEL backed DID document blocks and data (designated alias ACDCs, signatures, etc) so that the trusted (local) did:webs resolver is secure. Any future features that could leverage BADA-RUN and KRAM should be considered carefully according to the above considerations.
See the implementors guide for more details about KEL backed, BADA-RUN, and KRAM:
§ Privacy Considerations
This section addresses the privacy considerations from
RFC6973 section 5.
For privacy considerations related to web infrastructure, see
did:web privacy considerations.
Below we discuss privacy considerations related to the KERI infrastructure.
§ Surveillance
In KERI, a robust witness network along with consistent witness rotation provides protection from monitoring and association of an individual’s activity inside a KERI network.
§ Stored Data Compromise
For resolvers that simply discover the Key State endorsed by another party in a discovery network, caching policies of that network would guide stored data security considerations. In the event that a resolver is also the endorsing party, meaning they have their own KERI identifier and are verifying the KEL and signing the Key State themselves, leveraging the facilities provided by the KERI protocol (key rotation, witness maintenance, multi-sig) should be used to protect the identities used to sign the Key State.
§ Unsolicited Traffic
DID documents are not required to provide endpoints and thus not subject to unsolicited traffic.
§ Misattribution
This DID Method relies on KERI’s duplicity detection to determine when the non-repudiable controller of a DID has been inconsistent and can no longer be trusted. This establishment of non-repudiation enables consistent attribution.
§ Correlation and Identification
The root of trust for KERI identifiers is entropy. A did:webs AID therefore
offers no inherent correlatable or identifying attributes beyond the AID
string itself and whatever the controller chooses to publish. In addition,
KERI provides direct mode and indirect mode communication;
direct mode supports pairwise (and n-wise) relationships that can
limit correlation across contexts.
See the KERI specification for direct and indirect modes and secure bindings and prefix derivation.
§ Secondary Use
The Key State made available in the metadata of this DID method is generally available and can be used by any party to retrieve and verify the state of the key event receipt log (KERL) for the given identifier.
§ Disclosure
No data beyond the Key State for the identifier is provided by this DID method.
§ Exclusion
This DID method provides no opportunity for correlation and identification or disclosure and therefore there is no opportunity to exclude the controller from knowing about data that others have about them.
§ IANA Considerations
This section is normative.
KERI event streams use the registered
application/cesr media type with IANA. The media type is
application/cesr. The registration follows the template in
RFC6838.
§ Implementors Guide
These sections are informative.
§ Key Agreement
There are multiple ways to establish key agreement in KERI. We detail common considerations and techniques:
- If the ‘k’ field references a Ed25519 key, then key agreement may be established using the corresponding x25519 key for Diffie-Hellman key exchange.
- If the key is an ECDSA or other NIST algorithms key then it will be the same key for signatures and encryption and can be used for key agreement.
- BADA-RUN for key agreement: Normally in KERI we would use BADA-RUN, similar to how we specify endpoints, host migration info, etc. This would allow the controller to specify any Key Agreement key, without unnecessarily adding KERI events to their KEL.
- Key agreement from
kfield keys: It is important to note that KERI is cryptographically agile and can support a variety of keys and signatures. - Key agreement anchored in KEL: It is always possible to anchor arbitrary
data, like a key agreement key, to the KEL.
- The best mechanism is to anchor an ACDC to a TEL which is anchored to the KEL. The data would be the basis of the key agreement information. The concept is similar to how we anchor designated aliases as verifiable data on a TEL.
§ Other Key Commitments
This section is informative: Data structures similar to Location Scheme and Endpoint Authorizations and managed in KERI using BADA-RUN may be created and used for declaring other types of keys, for example encryption keys, etc
To support new data structures, propose them in KERI and detail the transformation in the spec.
§ On-Disk Storage
This section is informative: Both KEL backed data and BADA-RUN security approaches are suitable for storing information on disk because both provide a link between the keystate and date-time on some data when a signature by the source of the data was created. BADA-RUN is too weak for important information because an attacker who has access to the database on disk can overwrite data on disk without being detected by a verifier hosting the on-disk data either through a replay of stale data (data regression attack) or if in addition to disk access the attacker has compromised a given key state, then the attacker can forge new data with a new date-time stamp for a given compromised key and do a regression attack so that the last seen key state is the compromised key state.
With BADA, protection from a deletion (regression) attack requires redundant disk storage. At any point in time where there is a suspicion of loss of custody of the disk, a comparison to the redundant disks is made and if any disk has a later event given BADA-RUN rules then recovery from the deletion attack is possible.
KRAM on a query is not usable for on disk storage by itself because it’s just a bare signature (the datetime is not of the querier but of the host at the time of a query). However, the reply to a query can be stored on disk if the querier applies BADA to the reply. To elaborate, Data obtained via a KRAMed query-reply may be protected on-disk by using BADA on the reply. This is how KERI stores service endpoints. However, KERI currently only uses BADA for discovery data not more important data. More important data should be wrapped (containerized) in an ACDC that is KEL backed and then stored on-disk
In the hierarchy of attack surfaces, exposure as on disk (unencrypted) is the weakest. Much stronger is exposure that is only in-memory. To attack in-memory usually means compromising the code supply chain which is harder than merely gaining disk access. Encrypting data on disk does not necessarily solve attacks that require a key compromise (because decryption keys can be compromised), and it does not prevent a deletion attack. Encryption does not provide authentication protection. However, encryption does protect the confidentiality of data.
The use of DH key exchange as a weak form of authentication is no more secure than an HMAC for authentication. It is sharing secrets, so anyone with the secret can impersonate any other member of the group that has the shared secret.
Often, DID methods have focused on features that erode security
characteristics. The paper
Five DID Attacks
highlights some attacks to which did:webs should NOT be vulnerable. So
when a pull request exposes did:webs to a known attack, it should not be
accepted.
§ Alignment of Information to Security Posture
This section is informative: As a general security principle each block of information should have the same security posture for all the sub-blocks. One should not attempt to secure a block of information that mixes security postures across its constituent sub-blocks. The reason is that the security of the block can be no stronger than the weakest security posture of any sub-block in the block. Mixing security postures forces all to have the lowest common denominator security. The only exception to this rule is if the block of information is purely informational for discovery purposes and where it is expected that each constituent sub-block is meant to be verified independently.
This means that any recipient of such a block of information with mixed security postures across its constituent sub-blocks must explode the block into sub-blocks and then independently verify the security of each sub-block. However, this is only possible if the authentication factors for each sub-block are provided independently. Usually when information is provided in a block of sub-blocks, only one set of authentication factors are provided for the block as a whole and therefore there is no way to independently verify each sub-block of information.
Unfortunately, what happens in practice is that users are led into a false sense of security because they assume that they don’t have to explode and re-verify, but merely may accept the lowest common denominator verification on the whole block of information. This creates a pernicious problem for downstream use of the data. A downstream use of a constituent sub-block doesn’t know that it was not independently verified to its higher level of security. This widens the attack surface to any point of down-stream usage. This is a root cause of the most prevalent type of attack called a BOLA.
§ Applying the concepts of KEL, BADA-RUN, and KRAM to did:webs
This section is informative. Let’s explore the implications of applying these
concepts to various did:webs elements.
Using KEL backed elements in a DID doc simplifies the security
concerns. However, future discovery features related to endpoints might
consider BADA-RUN. For instance, ‘whois’ data could be used with
BADA-RUN whereas did:web aliases should not because it could lead
to an impersonation attack. We could have a DID document that uses
BADA-RUN if we modify the DID CRUD semantics to be RUN semantics without
necessarily changing the verbs but by changing the semantics of the verbs.
Then any data that fits the security policy of BADA (i.e. where BADA is
secure enough) can be stored in a DID document as a database in the sky. For
sure this includes service endpoints for discovery. One can sign with
CESR or JWS signatures. The payloads are essentially KERI reply
messages in terms of the fields (with modifications as needed to be more
palatable), but are semantically the same. The DID doc just relays those
replies. Anyone reading from the DID document is essentially getting a KERI
reply message, and they then should apply the BADA rules to their local
copy of the reply message.
To elaborate, these security concepts point us to modify the DID CRUD
semantics to replicate RUN semantics. Create becomes synonymous with
Update where Update uses the RUN update. Delete is modified to use the
Nullify semantics. Read data is modified so that any recipient of the Read
response can apply BADA to its data (Read is a GET). So we map the CRUD of
DID docs to RUN for the did:webs method. Now you have reasonable security
for things like signed data. If its KEL backed data you could even
use an ACDC as a data attestation for that data and the did
resolver would become a caching store for ACDCs issued by the AID
controller.
Architecturally, a Read (GET) from the did resolver acts like how KERI reply messages are handled for resolving service endpoint discovery from an OOBI. The query is the read in RUN and so uses KRAM. The reply is the response to the READ request. The controller of the AID updates the DID resolvers cache with updates(unsolicited reply messages). A trustworthy DID resolver applies the BADA rules to any updates it receives. Optionally the DID resolver may apply KRAM rules to any READ requests to protect it from replay attacks.
In addition, a DID doc can be a discovery mechanism for an ACDC caching server by including an index (label: said) of the SAIDs of the ACDCs held in the resolvers cache.
§ The set of KERI features needed
Generally the full feature set of KERI, ACDC, and CESR are needed for did:webs
though specific use cases may depend on a smaller subset of KERI and ACDC.
KERI means key event receipt infrastructure. ACDC means authentic chained data container. CESR means compact event streaming representation.
Full support of did:webs depends on the following KERI, ACDC, and CESR features:
| Source | Feature | Usage in did:webs |
Purpose |
|---|---|---|---|
| KERI | Key Event Log (KEL) | did:webs DIDs use a KERI AID backed by a KEL. |
The KEL provides the security for a did:webs DID, including key rotation. |
| KERI | Location Scheme Message | URL Discovery. Part of the keri.cesr stream. Service endpoints (witnesses, etc.) use these to list authorized URLs. |
Witness service endpoint section construction in the service DID doc section providing the backing witness URLs for the did:webs AID. |
| KERI | Endpoint Role Authorization Message | Service endpoint authorizations. Part of the keri.cesr stream. Authorizes an infrastructure component in a role. |
Provides the type attribute of service endpoints in the service DID doc section for witnesses or other infrastructure components. |
| KERI | Out of Band Identifier (OOBI) | The serviceEndpoint for a delegated identifier uses a KERI OOBI |
Indicates where a did:webs resolver would check to retrieve the KERI event stream for a given did:webs AID or its delegator. |
| ACDC | Credential Graph (DAG) | Every did:webs DID defines authorized host and path with a designated aliases ACDC (credential) |
Designated aliases ACDC provides did:webs DID host and path segment verifiability. |
| KERI | Key Rotation | versionId allows requesting a did:webs DID document at a point in time as of a given KEL sequence number. |
Long term auditability and verifiability depend on versioned DID documents. |
| KERI | Multi-signature Identifiers | A did:webs DID may use multi-signature identifiers with ConditionalProof2022 for advanced identifier control. |
Enterprise and personal identifier usage often include multi-signature, multi-person setups. Multi-sig facilitates this. |
| KERI | Delegated Identifiers | The DelegatorOOBI service type in did:webs relies upon the delegated identifier feature of KERI. |
Delegated identifiers support structured, hierarchical identifier control often modelled in enterprise, personal, or guardianship scenarios. |
| ACDC | Transaction Event Log (TEL) | Anchoring of designated alias credentials to a KEL consists of anchoring TEL events to a KEL for that ACDC. | TELs are a fundamental, critical component of anchoring an ACDC and are required to be in thedid:webs DID’s keri.cesr stream. |
| CESR | Text or binary representation | All did:webs DIDs present a CESR-encoded keri.cesr stream. Also, an AID is a CESR encoded string. |
CESR is the text and binary wire protocol fundamental to KERI, ACDC, and did:webs |
These basics are
summarized in the KERI Fundamentals section of this
specification. This specification assumes a working knowledge of the
concepts there. The inclusion of KERI in did:webs enables a number of
capabilities for securing a did:webs identifier, including multi-signature
support, delegated identifier support for signing scalability, and the
creation of pre-rotated keys to prevent loss of control of the
identifier if the current private key were to be compromised.
You may find the
did:webs feature dependency diagram
helpful as a visual guide to the features and dependencies of did:webs.
§ Stable identifiers on an unstable web
This section is informative: The web is not a very stable place, and
documents are moved around and copied frequently. When two or more companies
merge, often the web presence of some of the merged entities “disappears”.
It may not be possible to retain a permanent did:webs web location.
The purpose of the history of designated aliases for the AID is so
that if the did:webs DID has been put in long-lasting documents, and its
URL instantiation is redirected or disappears, the controller can explicitly
indicate that the new DID is an equivalentId to the old one.
Since the AID is globally unique and references the same identifier,
regardless of the rest of the string that is the full did:webs, web
searching could yield either the current location of the DID document, or a
copy of the DID that may be useful. For example, even the
Internet Archive: Wayback Machine could be used
to find a copy of the DID document and the KERI event stream at
some point in the past that may be sufficient for the purposes of the
entity trying to resolve the DID. This specification does not rely on the
Wayback Machine, but it might be a useful did:webs discovery tool.
The DID document, KERI event stream and other files related to a
DID may be copied to other web locations. For example, someone might want
to keep a cache of DIDs they use, or an entity might want to run a
registry of “useful” DIDs for a cooperating group. While the combination of
DID document and KERI event stream make the DID and DID document verifiable,
just as when published in their “intended” location, the absence of the
did:webs in the designated aliases for those locations in the
DID document equivalentId means that the controller of the DID is not
self-asserting any sort of tie between the DID and the location to which
the DID-related documents have been copied. In contrast, if the controller
confirms the link between the source and the copy with an equivalentId,
the related copies will have to be kept in sync.
Were the AID of a did:webs identifier to change, it would be an altogether
new DID, unconnected to the first DID. Furthermore, changing the host or path
of a did:webs DID also makes a new DID, albeit with the same backing AID.
A did:webs could be moved to use another DID method that uses the AID for
uniqueness and the KERI event stream for validity, but that is
beyond the scope of this specification.
§ KERI event stream chain of custody
The KERI event stream represents a cryptographic chain of trust originating
from the AID of the controller to the current operational set of
keys (signing and otherwise) as well as the cryptographic commitments to the
keys the controller will rotate to in the future. The KERI event stream also
contains events that do not alter the AID key state, but are useful
metadata for the DID document such as, the supported hosts, the
current set of service endpoints, etc. A did:webs resolver produces the
DID document by processing the KERI event stream to determine the
current key state. We detail the different events in “Basic KERI event
details” and show how they change the DID document. The mapping from the
KERI event stream to the DID document properties compose the core of the
did:webs resolver logic. Understanding the optimal way to update and
maintain the KERI event stream (publish static keri.cesr files, dynamically
generate the keri.cesr resource, etc) is beyond the scope of the spec,
but the did:webs Reference Implementation of the resolver
demonstrate some of these techniques. The important concept is that the
entire KERI event stream is used to produce and verify the DID document.
§ Verifiable data on a TEL
This section is informative: Below is an example highlighting how verifiable data is anchored to a KEL using a TEL. We use this spec’s designated aliases feature as a real-world example. You can walk through this example in the did:webs Reference Implementation. The attestation (self-issued credential) is as follows:
{
"v": "ACDC10JSON0005f2_",
"d": "EIGWggWL2IHiUzj1P2YuPA0-Uh55LTIu14KTvVQGrfvT",
"i": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"ri": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"s": "EN6Oh5XSD5_q2Hgu-aqpdfbVepdpYpFlgz6zvJL5b_r5",
"a": {
"d": "EJJjtYa6D4LWe_fqtm1p78wz-8jNAzNX6aPDkrQcz27Q",
"dt": "2023-11-13T17:41:37.710691+00:00",
"ids": [
"did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
]
},
"r": {
"d": "EEVTx0jLLZDQq8a5bXrXgVP0JDP7j8iDym9Avfo8luLw",
"aliasDesignation": {
"l": "The issuer of this ACDC designates the identifiers in the ids field as the only allowed namespaced aliases of the issuer's AID."
},
"usageDisclaimer": {
"l": "This attestation only asserts designated aliases of the controller of the AID, that the AID controlled namespaced alias has been designated by the controller. It does not assert that the controller of this AID has control over the infrastructure or anything else related to the namespace other than the included AID."
},
"issuanceDisclaimer": {
"l": "All information in a valid and non-revoked alias designation assertion is accurate as of the date specified."
},
"termsOfUse": {
"l": "Designated aliases of the AID must only be used in a manner consistent with the expressed intent of the AID controller."
}
}
}
Now we show that the information is anchored to the KEL in a way that allows for changes in key state while not invalidating it. We will:
- chain an interaction event on the KEL, to a registry we call a TEL
- The TEL maintains the ‘state’ of issued or revoked for the attestation. If the controller wants to update the list they would revoke the attestation and issue a new attestation with the updated list of aliases that they want to designate.
- The TEL must chain to the attestation itself. This is what forms the end-to-end verifiability from the attestation to the AID itself. Here is the KERI event stream of each part:
§ The interaction event on the KEL
This interaction event connects the TEL registry to the KEL. Notice the a
field with the nested i field that references the registry
"v": "KERI10JSON00013a_",
"t": "ixn",
"d": "ED-4iQIVxwMcrTOW6fVs9oPpLTIxtqh_vcvLmE999zsU",
"i": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"s": "1",
"p": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"a": [
{
"i": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"s": "0",
"d": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx"
}
]
§ The TEL registry
This TEL registry connects the KEL interaction event to the registry status.
Notice the d field matches the nested i field of the a field of the
interaction event demonstrating that they are cryptographically chained
together.
"v": "KERI10JSON000113_",
"t": "vcp",
"d": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"i": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"ii": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"s": "0",
"c": [
"NB"
],
"bt": "0",
"b": [],
"n": "AAfqHwMDdBoIWk_4Z6hvVJuhtvjA_gk8Y9bEUoP_rC_p"
§ The attestation status
The current status of the attestation is in the t field. iss means
issued. Notice the ri field cryptographically binds this issued status to
the registry above. Likewise, the i field cryptographically binds to the
attestation d field.
"v": "KERI10JSON0000ed_",
"t": "iss",
"d": "EJQvCZQYn8oO1z3_f8qhxXjk7TcLol4G3RdHVTwfGV3L",
"i": "EIGWggWL2IHiUzj1P2YuPA0-Uh55LTIu14KTvVQGrfvT",
"s": "0",
"ri": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"dt": "2023-11-13T17:41:37.710691+00:00"
§ The full KERI event stream
This snippet demonstrates how these events occur in the full keri.cesr file.
Notice the CESR encoded verifiable signatures that are interleaved between
events.
{
"v": "KERI10JSON00012b_",
"t": "icp",
"d": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"i": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"s": "0",
"kt": "1",
"k": [
"DHr0-I-mMN7h6cLMOTRJkkfPuMd0vgQPrOk4Y3edaHjr"
],
"nt": "1",
"n": [
"ELa775aLyane1vdiJEuexP8zrueiIoG995pZPGJiBzGX"
],
"bt": "0",
"b": [],
"c": [],
"a": []
}-VAn-AABAADjfOjbPu9OWce59OQIc-y3Su4kvfC2BAd_e_NLHbXcOK8-3s6do5vBfrxQ1kDyvFGCPMcSl620dLMZ4QDYlvME-EAB0AAAAAAAAAAAAAAAAAAAAAAA1AAG2024-04-01T17c40c48d329209p00c00{
"v": "KERI10JSON00013a_",
"t": "ixn",
"d": "ED-4iQIVxwMcrTOW6fVs9oPpLTIxtqh_vcvLmE999zsU",
"i": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"s": "1",
"p": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"a": [
{
"i": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"s": "0",
"d": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx"
}
]
}-VAn-AABAACNra5mDg7YHFtBeXiwIGqnHkyq7F55FGNYG1wH95akjSWCb1HzNI3E05ufT0HffClDxnJF_DmAUW2SBb0EJeoO-EAB0AAAAAAAAAAAAAAAAAAAAAAB1AAG2024-04-01T17c42c37d704426p00c00{
"v": "KERI10JSON00013a_",
"t": "ixn",
"d": "EBjw0a_L8M0F4xYND99dvahlrkpxODi9Wc9VzUvkhD0t",
"i": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"s": "2",
"p": "ED-4iQIVxwMcrTOW6fVs9oPpLTIxtqh_vcvLmE999zsU",
"a": [
{
"i": "EIGWggWL2IHiUzj1P2YuPA0-Uh55LTIu14KTvVQGrfvT",
"s": "0",
"d": "EJQvCZQYn8oO1z3_f8qhxXjk7TcLol4G3RdHVTwfGV3L"
}
]
}-VAn-AABAABo_okwAmWIYWI93EtUONZiEvsGuSRkKnj0mopX_RoXwWHZ_1V5hQ0BxcntsmAi21DbusyCmK-fHwTNtSxUSsoN-EAB0AAAAAAAAAAAAAAAAAAAAAAC1AAG2024-04-01T17c42c39d995867p00c00{
"v": "KERI10JSON000113_",
"t": "vcp",
"d": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"i": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"ii": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"s": "0",
"c": [
"NB"
],
"bt": "0",
"b": [],
"n": "AAfqHwMDdBoIWk_4Z6hvVJuhtvjA_gk8Y9bEUoP_rC_p"
}-VAS-GAB0AAAAAAAAAAAAAAAAAAAAAABED-4iQIVxwMcrTOW6fVs9oPpLTIxtqh_vcvLmE999zsU{
"v": "KERI10JSON0000ed_",
"t": "iss",
"d": "EJQvCZQYn8oO1z3_f8qhxXjk7TcLol4G3RdHVTwfGV3L",
"i": "EIGWggWL2IHiUzj1P2YuPA0-Uh55LTIu14KTvVQGrfvT",
"s": "0",
"ri": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"dt": "2023-11-13T17:41:37.710691+00:00"
}-VAS-GAB0AAAAAAAAAAAAAAAAAAAAAACEBjw0a_L8M0F4xYND99dvahlrkpxODi9Wc9VzUvkhD0t{
"v": "ACDC10JSON0005f2_",
"d": "EIGWggWL2IHiUzj1P2YuPA0-Uh55LTIu14KTvVQGrfvT",
"i": "ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"ri": "EAtQJEQMkkvlWxyfLbcLyv4kNeAI5Qsqe65vKIWnHKpx",
"s": "EN6Oh5XSD5_q2Hgu-aqpdfbVepdpYpFlgz6zvJL5b_r5",
"a": {
"d": "EJJjtYa6D4LWe_fqtm1p78wz-8jNAzNX6aPDkrQcz27Q",
"dt": "2023-11-13T17:41:37.710691+00:00",
"ids": [
"did:web:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:did-webs-service%3a7676:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:example.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:web:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe",
"did:webs:foo.com:ENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe"
]
},
"r": {
"d": "EEVTx0jLLZDQq8a5bXrXgVP0JDP7j8iDym9Avfo8luLw",
"aliasDesignation": {
"l": "The issuer of this ACDC designates the identifiers in the ids field as the only allowed namespaced aliases of the issuer's AID."
},
"usageDisclaimer": {
"l": "This attestation only asserts designated aliases of the controller of the AID, that the AID controlled namespaced alias has been designated by the controller. It does not assert that the controller of this AID has control over the infrastructure or anything else related to the namespace other than the included AID."
},
"issuanceDisclaimer": {
"l": "All information in a valid and non-revoked alias designation assertion is accurate as of the date specified."
},
"termsOfUse": {
"l": "Designated aliases of the AID must only be used in a manner consistent with the expressed intent of the AID controller."
}
}
}-VA0-FABENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe0AAAAAAAAAAAAAAAAAAAAAAAENro7uf0ePmiK3jdTo2YCdXLqW7z7xoP6qhhBou6gBLe-AABAADQOX208DAmZEPb2v0XXF0N6WgxOdOxB3AsCBJds_vbAr7v1PQBA4MWNsXc8unk5UykbB8j538XGkzLtujekvIP
§ Adding service endpoint roles in KERI
- A hypothetical new role that could be submitted to KERI, would be the DIDCommMessaging role. It could be specified
{
"service": [
{
"id":"#Bgoq68HCmYNUDgOz4Skvlu306o_NY-NrYuKAVhk3Zh9c",
"type": "DIDCommMessaging",
"serviceEndpoint": "https://bar.example.com"
},
{
"id":"#BuyRFMideczFZoapylLIyCjSdhtqVb31wZkRKvPfNqkw",
"type": "agent",
"serviceEndpoint": {
"tcp": "tcp://bar.example.com:5542",
"https": "https://bar.example.com"
}
}
]
}
§ Annex
§ KERI Fundamentals
KERI is a protocol for managing
cryptographic keys, identifiers, and associated verifiable data structures.
KERI was first described in an
academic paper, and its
specification is
currently incubated under Trust Over IP Foundation.
The open source community that develops KERI-related technologies can be
found at https://github.com/WebOfTrust/keri. This section outlines the
fundamentals and components of the KERI protocol that are related to the
did:webs method.
§ Autonomic Identifier (AID)
An autonomic identifier is a globally-unique persistent
self-certifying verifiable identifier that serves as the primary
root-of-trust of the KERI protocol. An AID is cryptographically bound to a
KEL that
determines the evolution of its key state using the
pre-rotation mechanism. AIDs and the underlying KERI protocol, by
themselves, satisfy most of the
properties that DIDs require,
including decentralization, control, security, proof-based, and portability.
For example, DIDs that have the same AID component are considered
equivalent, allowing AIDs to be portable across
different DID methods such as did:webs and did:keri.
§ Key Event Log (KEL)
The binding between an AID and its cryptographic keys is proved by
a data structure called a key event log that allows the
key states of the AID to evolve. For a did:webs DID, a KEL is
an essential component in the KERI event stream that is used to
verify its authenticity.
A KEL is a hash-chain append-only log and can be considered a variant of blockchain. However, a KEL differs from the traditional blockchain technology in at least two important ways:
- It records the key event history of a single AID with a single controller, instead of an arbitrarily large collection updated by other participants in the network. This makes a KEL memory-efficient, fast, cheap, and trivially scalable.
- It is fully self-certifying, meaning its correctness can be proved by direct inspection, without a distributed consensus algorithm or assumptions about trust in an external data source or its governance.
These properties allows a KEL to be published anywhere, without special guarantees from its storage mechanism. For example, a KEL of an AID could be published and migrated between different KERI-compatible blockchain networks that use different DID methods. A KEL also records changes to key types and cryptographic algorithms, providing the AID portability and adaptability to multiple ecosystems throughout its lifecycle.
§ AID Derivation
The value of an AID is derived from the first key event,
called the inception event, of a KEL. The inception event
includes initial public key(s), called the current key(s), that can be used
to control the AID. The cryptographic relationship between the AID and its
keys eliminates an early chain-of-custody risk that plagues many other DID
methods where an attacker uses compromised keys to create a DID without the
DID controller’s knowledge. This derivation process is similar to techniques
used by did:key, did:peer, did:sov, and did:v1.
The simplest AIDs, called non-transferable direct mode AIDs, have
no additional input to the derivation function, and expose a degenerate KEL
that can hold only the inception event. This KEL is entirely derivable from
the AID itself, and thus requires no external data. Non-transferable direct
mode AIDs are ideal for ephemeral use cases and are excellent analogs to
did:key and did:peer with numalgo=0. This is by no means not the only
option as KERI offers richer choices that are especially valuable if an AID
is intended to have a long lifespan.
§ Pre-rotation
Public keys in the Verification Methods of a
did:webs DID can be changed via a mechanism called pre-rotation.
With pre-rotation, the inception event of the associated AID also includes
the hash(s) of the next key(s) that can be used to change the
key state of the AID. AIDs with one or more pre-rotated next keys
are called transferable AIDs because their control can be transferred to
new keys. AIDs that do not use pre-rotation cannot change their keys and are
thus non-transferable.
Pre-rotation has profound security benefits. If a malicious party steals the current private key for a transferable AID, they only accomplish temporary mischief, because the already-existing KEL contains a commitment to a future state. This prevents them from rotating the stolen AID’s key to an arbitrary value of their choosing. As soon as the AID controller suspects a compromise, they can change the key state of the AID using the pre-rotated next key and locks the attacker out again.
§ Weighted Multisig
The KERI protocol supports a weighted multi-signature scheme that allows for conditional proof in the Verification Methods. A multisig AID distributes its control among multiple key holders. This includes simple M-of-N rules such as “3 of 5 keys must sign to change the AID’s key state”. More sophisticated configurations are also supported: “Acme Corp’s AID is controlled by the keys of 4 of 7 board members, or by the keys of the CEO and 2 board members, or by the keys of the CEO and the Chief Counsel.”
The security and recovery benefits of this feature are obvious when an AID references organizational identity. However, even individuals can benefit from this, when stakes are high. They simply store different keys on different devices, and then configure how their devices constitute a management quorum. This decreases risks from lost phones, for example.
§ Witnesses
In the direct mode, the controller of an AID is responsible for the distribution of its KEL. Since the controller may not be highly available, the controller may designate additional supporting infrastructure, called witnesses, for the indirect mode distribution of the KELs. Witnesses may or may not be under direct control of the AID’s controller and could be deployed on either centralized or decentralized architectures, including blockchains. The witnesses are embedded in the AID’s key event and, if included in the inception event, alter the AID value.
Unlike a blockchain with a distributed consensus mechanism, witnesses do not coordinate or come to consensus with one another during an update to its AID’s key event history. Hence, they need not be deeply trustworthy; merely by existing, they improve trust. This is because anyone changing an AID’s key state or its set of witnesses, including the AID’s legitimate controller, has to report those changes to the witnesses that are currently active, to produce a valid evolution of the KEL. The AID controller and all witnesses thus hold one another accountable. Further, it becomes possible to distinguish between duplicity and imperfect replication of key states.
§ Transaction Event Log (TEL)
The KERI protocol supports a verifiable data structure, called the transaction event log, that binds an AID to non-repudiable data that is deterministically bound to the key event history in the KEL. Transactions that are recorded in a TEL may include things like the issuance and revocation of verifiable credentials or the fact that listeners on various service endpoints started or stopped. Like KELs, TELs are self-certifying and may also be published by KERI witnesses to enhance discoverability and provide watcher networks the ability to detect duplicity. For example, we demonstrate that in this spec in how we anchor designated aliases as verifiable data on a TEL.
§ Web Independence
Although this DID method depends on web technology, KERI itself does not. It’s as easy to create AIDs on IOT devices as it is on the web. AIDs offer the same features regardless of their origin and besides HTTP, they are shareable over Lo-Ra, Bluetooth, NFC, Low Earth Orbit satellite protocols, service buses on medical devices, and so forth. Thus, KERI’s AIDs offer a bridge between a web-centric DID method and lower-level IOT ecosystems.
§ Flexible Serialization
KELs and TELs of did:webs DIDs (i.e., AIDs) are included
in the KERI event streams for verification of the DID documents.
The KERI event streams use CESR for data serialization. Although CESR is a deep subject all
by itself, at a high level, it has two essential properties:
- Content in CESR is self-describing and supports serialization as binary and text: That is in CESR, a digital signature on a CESR data structure is stable no matter which underlying serialization format is used. In effect it supports multiple popular serialization formats like JSON, CBOR, and MsgPack with room for many more. These formats can be freely mixed and combined in a CESR stream because of the self-describing nature of these individual CESR data structures. The practical effect is that developers get the best of both worlds: they can produce and consume data as text to display and debug in a human-friendly form and they can store and transmit this data in its tersest form, all without changing the signature on the data structures.
- Cryptographic primitives are structured into compact standard
representations: Cryptographic primitives such as keys, hashes, digests,
sealed-boxes, signatures, etc… are structured strings with a
recognizable data type prefix and a standard representation in the stream.
This means they are very terse and there is no need for the variety of
representation methods that create interoperability challenges in other
DID methods (
publicKeyJwkversuspublicKeyMultibaseversus other; see the verification material section of the DID specification.
Despite this rich set of features, KERI imposes only light dependencies on
developers. The cryptography it uses is familiar and battle-hardened, exactly
what one would find in standard cryptography toolkits. For example, the
python implementation (keripy) only depends on the pysodium, blake3, and
cryptography python packages. Libraries for KERI exist in javascript, rust,
and python.
§ Bibliography
§ Normative section
. W3C, Data Integrity Proofs.
. IETF, RFC 7515 Section 3.2: JWS JSON Serialization.
. Multiformats, multihash.
. IETF, RFC 1035: Domain Names - Implementation and Specification.
. IETF, RFC 1123: Requirements for Internet Hosts - Application and Support.
. IETF, RFC 2181: Clarifications to the DNS Specification.
. IETF, RFC 3986: Uniform Resource Identifier (URI): Generic Syntax.
§ Trust-over-IP
. Trust over IP, Authentic Chained Data Containers (ACDC) specification.
. Trust over IP, Composable Event Streaming Representation (CESR).
. Trust over IP, CESR Proof Signatures specification.
. Trust over IP, Key Event Receipt Infrastructure (KERI) specification.
. Trust over IP, ACDC IPEX validation.
§ W3C
. W3C CCG, did:web Method Specification.
. W3C, Decentralized Identifiers (DIDs) v1.0.
. W3C, DID Spec Registries.
. W3C, DID URL path.
. W3C, Verifiable Credentials Data Model.
. W3C, Verifiable Presentations.
§ Informative section
. GLEIF, did:webs Reference Implementation and its getting started guide.
. Hyperledger Aries RFCs, Overlay Capture Architecture.
. IETF, RFC 5895: Mapping Characters for IDNA2008.
. W3C CCG, VC Status List 2021.
. Unicode Consortium, UTS #46: Unicode IDNA Compatibility Processing.
. W3C CCG, VC Rendering Methods specification.