The did:cel Method v0.3

A DID Method based on witnessed cryptographic event logs

Draft Community Group Report

Latest published version:
none
Latest editor's draft:
https://w3c-ccg.github.io/did-cel-spec/
Editor:
Manu Sporny (Digital Bazaar)
Authors:
Dave Longley (Digital Bazaar)
Manu Sporny (Digital Bazaar)
Feedback:
GitHub w3c-ccg/did-cel-spec (pull requests, new issue, open issues)
Related Documents
Controlled Identifiers v1.0
Decentralized Identifiers v1.0
DID Use Cases and Requirements
Cryptographic Event Log v0.1
DID Core Implementation Report

Abstract

Decentralized Identifiers (DIDs) are a type of identifier for verifiable, decentralized digital identity. These identifiers are designed to enable the controller of a DID to prove control over the identifier in a way that is independent of any centralized registry, identity provider, or certificate authority. These sorts of identifiers often utilize a heavy-weight registry, such as ones utilizing Decentralized Ledger Technologies (DLT), to create, read, update, and deactivate DIDs. This specification describes a witness-based DID Method where each DID Document's history is contained in a cryptographic event log where each event is witnessed by one or more trusted entities. The approach avoids the need for complex decentralized consensus algorithms as well as expensive proof-of-work or proof-of-stake systems.

Status of This Document

This is a preview

Do not attempt to implement this version of the specification. Do not reference this version as authoritative in any way. Instead, see https://w3c-ccg.github.io/did-cel-spec/ for the Editor's draft.

This specification was published by the Credentials Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

GitHub Issues are preferred for discussion of this specification.

1. Introduction

This section is non-normative.

In today's digital world, your online identity is controlled by companies and organizations that maintain databases of usernames, passwords, and personal information. When you create an account with a service, that service owns your identity—they can lock you out, change the rules, or even shut down entirely, taking your identity and connections with it. The did:cel method offers a fundamentally different approach: it enables you to create and control your own digital identifier without relying on any single company, organization, or centralized database. Your DID belongs to you alone, stored and managed using cryptographic techniques that prove ownership without needing anyone's permission or approval.

What makes did:cel truly decentralized is its witness-based architecture, which eliminates any single point of control or failure. Unlike traditional systems where a company's servers must be online for you to prove who you are, or blockchain-based systems where you depend on a specific network to function, did:cel distributes trust across multiple independent witnesses that attest to changes in your identity information. These witnesses don't control your identity—they simply provide timestamped confirmations that certain changes occurred. You choose which witnesses to use, and because no single witness has special authority, no one entity can block your access, censor your identity, or force unwanted changes. This architectural choice means your identity remains under your control even if individual witnesses become unavailable or act maliciously.

This decentralization directly empowers individuals to own their identity and data online in meaningful ways. With did:cel, you can prove who you are and what credentials or permissions you hold without asking permission from gatekeepers. You can take your identity with you across different services and platforms, establishing trust relationships on your own terms. If a service you use shuts down or changes its policies in ways you disagree with, your underlying identity remains intact and under your control—you simply use it with a different service. This represents a fundamental shift from identity as something granted by institutions to identity as an inherent digital right that you exercise through cryptographic proofs. When you control your identifier, you control your digital presence, your relationships, and your data.

This specification describes the complete technical framework for the did:cel method. The Identifier Syntax section explains how DIDs are constructed using cryptographic hashes. The Operations section details how to create, update, read, witness, and deactivate DID documents, including the cryptographic event log that maintains the complete history of changes. The Privacy Considerations section examines privacy implications of maintaining public event logs and offers mitigation strategies. Finally, the Security Considerations section addresses potential security risks and provides guidance for secure implementation and deployment of the did:cel method.

1.1 Goals

This specification optimizes for the following design goals:

Minimal Infrastructure
A single individual with a file hosting location can create and control multiple DIDs in a way that the identifiers are highly-available and globally recognized.
Near-zero Cost
The cost to create and control multiple DIDs is not burdensome to at least 70% of the world's population, which are the number of people that have access to the Internet as of 2025.
Censorship and Coercion Resistant
The witness and file storage services used to manage a DID cannot censor or coerce an individual or organization to any significant degree.
No Centralization
Witness and file storage services are abundant, easy to operate at scale, and are easily interchangeable if they become non-responsive or compromised.

Readers might also find the Goals section in the Cryptographic Event Log v0.1 specification of interest.

1.2 Focal Use Cases

The following focal use cases have been identified as ones that this specification is capable of addressing.

Self-hosted Management
Joe would like to create and manage his DIDs using software and infrastructure that he controls.
Custodial Management
Wilhelm would like to use DIDs but does not have the technical expertise to self-host and uses a well-reviewed service provider to manage his DIDs on his behalf, but enables his friends to help him leave the service if they work against his interests.
Organizational Management
LittleCorp uses DIDs that represent operational divisions within the organization to issue verifiable credentials. The organization's security requirements related to government-approved cryptography, key rotation requirements, and recoverability after compromise are all addressable with the did:cel DID method.

Readers might also find the Use Cases and Requirements section in the Cryptographic Event Log v0.1 specification of interest.

1.3 Ecosystem

The interaction flow between DID controllers, witness services, storage services, and verifiers follows a standard process. When a DID controller creates or updates a DID document, they generate a signed event and append it to their cryptographic event log, creating a hashlink to the previous event. The controller then sends a cryptographic hash of this event to their chosen witness services, which each generate a data integrity proof attesting that they saw the cryptographic hash at a particular time, and then return the witness proof to the controller. The controller collects these witness proofs, attaches them to the event in the log, and publishes the complete cryptographic event log to one or more storage services.

When a verifier needs to validate a DID, the controller provides the DID and a storage location that can be used to retrieve the cryptographic event log from the storage services. The verifier then downloads the log and verifies the hashlinked chain integrity. It does this by checking that operation proofs are signed by authorized keys from the DID document, the hashlinks are correct, the operations performed are valid, and ensures that witness proofs meet their requirements. This separation of concerns between controllers, witnesses, storage, and verification enables a fully decentralized system where no single party has unilateral control.

1.4 Terminology

Some terminology used throughout this document is defined in the Terminology section of the Controlled Identifiers v1.0 specification, the Terminology section of the Decentralized Identifiers (DIDs) v1.0 specification, and the Terminology section of the Verifiable Credential Data Integrity 1.0 specification. This section defines additional terms used throughout this specification.

cryptographic event log
A hashlinked chain of events that records the complete history of operations performed on a document with each event cryptographically tied to the preceding event.
hashlink
A mechanism of connecting data through cryptographic hashes such that an observer can cryptographically verify that the contents of the data that is pointed to has not been modified since the link was created.
self-certifying identifier
A type of identifier derived directly from the cryptographic hash of data. The approach creates an intrinsic binding between the identifier and its content without requiring external registration or validation.
witness
An independent entity that provides cryptographic attestation to data in a cryptographic event log by creating data integrity proofs, enabling distributed validation without needing to store or control the data being attested to. Multiple witnesses can attest to the same data, and the process of creating such attestations is called witnessing.

1.5 Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

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

2. did:cel Identifier Syntax

The format for the did:cel method conforms to the Decentralized Identifiers (DIDs) v1.0 specification and is simple. It consists of the did:cel prefix, followed by a Multibase base58-btc encoded value that is a concatenation of the Multihash identifier and the corresponding cryptographic digest for the initial cryptographic event log entry.

The ABNF for the key format is described below:

did-cel-format := did:cel:<mb-value>
mb-value       := z[a-km-zA-HJ-NP-Z1-9]+

Alternatively, the encoding rules can also be thought of as the application of a series of transformation functions on the raw public key bytes:

did-cel-identifier := did:cel:MULTIBASE(base58-btc, MULTICODEC(sha3-256, JCS(initial-event-log-entry)))

A simple example of a valid did:cel DID is:

Example 1: A valid did:cel identifier
did:cel:zW1jPC3ViLfgPJX6KaPMhymin3LpATUgYTS7N58FLHtQ4HE

3. Witness Services

Witness services are independent entities that provide cryptographic attestations for events in cryptographic event logs, serving as a cornerstone of the did:cel method's decentralized architecture. Unlike centralized timestamp authorities or blockchain validators, witnesses operate autonomously without controlling or storing the DIDs they attest to, creating data integrity proofs that confirm events existed at specific points in time. This witness-based approach enables distributed trust without requiring expensive consensus mechanisms, heavy-weight infrastructure, or dependency on any single service provider. DID controllers select which witnesses to use for attestations, and because witnesses are independent and interchangeable, the system remains resilient even if individual witnesses become unavailable, compromised, or act maliciously.

3.1 Role of Witnesses

Witnesses fulfill several critical roles in the did:cel ecosystem. They provide temporal anchoring by generating timestamped cryptographic proofs that establish when events occurred, creating verifiable evidence that a DID controller performed an operation at a specific point in time. They enable distributed validation by offering independent third-party attestation, preventing any single entity from having unilateral control over the validity of DID operations. Witnesses also increase resistance to tampering and fraud by creating multiple independent records of events that would need to be simultaneously compromised to forge a fraudulent history. Importantly, witnesses do not validate the semantic correctness of DID document changes or make authorization decisions—they simply attest that an event with specific cryptographic hash existed at the time of witnessing. This limited scope keeps witness operations simple, efficient, and resistant to coercion and censorship, as witnesses cannot be compelled to make subjective judgments about the legitimacy of DID operations.

3.2 Witness Selection

Selecting the appropriate number of witnesses involves balancing security requirements against operational complexity and cost. Using more witnesses increases security by requiring attackers to compromise a larger number of independent services, but also increases the time, storage cost, network overhead, and time cost of obtaining attestations for each operation. Using too few witnesses creates risk that a single compromised or unavailable witness can block operations or enable fraud. For most use cases, a minimum of three independent witnesses from different operators and jurisdictions provides reasonable security while maintaining operational efficiency. High-security applications might require more witnesses with geographic and organizational diversity, while low-stakes applications might accept a single witness to minimize overhead.

DID controllers are advised to select witnesses operated by independent entities with diverse operational characteristics, avoiding witnesses that share infrastructure, jurisdiction, or governance that could create correlated failures. Verifiers establish their own policies about minimum witness thresholds they will accept, potentially requiring attestations from a majority or super-majority of a controller's chosen witnesses before trusting operations.

While governance and guidance around what makes an acceptable witness is out of scope for this specification, it is expected that verifier communities will publish lists of witnesses that they find acceptable to help controller's determine which ones to use to maximize trust in their DIDs.

3.3 Oblivious Witnessing

Oblivious witnessing is an important privacy and efficiency feature where witnesses attest to the hash of an event, including the hashlink to the previous event, rather than the contents of the event. When a DID controller requests witnessing, they compute a cryptographic hash of the event. They send only this cryptographic hash to witness services, which create data integrity proofs over the hash without ever seeing the actual event data. The witness returns a proof attesting that it witnessed the cryptographic hash at a specific time, providing temporal evidence without requiring disclosure of potentially sensitive information in the DID document or operation.

This approach offers several benefits: it protects the privacy of controller DID operations by preventing witnesses from seeing DID document contents, reduces the bandwidth and processing requirements for witnessing by transmitting only hashes rather than full documents, enables witnesses to operate as simple, stateless services that don't need to understand DID semantics, and prevents witnesses from being coerced to make judgments about the legitimacy of DID operations since they have no visibility into what they are attesting. Verifiers can validate oblivious witness proofs by computing the same hash of the event and confirming that the witness proof covers that hash, establishing the temporal attestation without compromising the privacy benefits.

4. Operations

The following section outlines the DID operations for the did:cel method.

4.1 Create

The create operation establishes a new did:cel DID document with a self-certifying identifier derived from the document's cryptographic hash. This operation accepts a cryptographic key pair and an OPTIONAL initial DID document. It constructs a new did:cel event log containing the DID document updated with the public key bound to an assertion method, and a data integrity proof for the document. This approach ensures that the DID is intrinsically bound to the document's initial state, providing strong integrity guarantees without requiring external registration.

Once the DID document is created and signed, a cryptographic event log (CEL) is initialized to track the complete history of operations on this DID. The log's first recorded operation is a create event, that contains the DID document as its data payload along with a corresponding data integrity proof. This event entry serves as the cryptographic foundation for all subsequent updates, enabling verifiable audit trails and witness attestation. The combination of the self-certifying identifier, cryptographic proof, and event log establishes a decentralized identifier implementation that requires no centralized authority for creation, validation, or resolution.

The did:cel event log identifier is cryptographically bound to both the the public key and the genesis DID document, which includes that public key.

An example of a cryptographic event log containing the creation event for a did:cel DID is shown below.

Example 2: Cryptographic event log after did:cel creation
{
  "log": [
    {
      "event": {
        "operation": {
          "type": "create",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1bVJvfgEBnKmH8WNShqxSuvySxWysKhhxri9EVPauwLtW",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeTk5EbiBNnqo6LSWyUfu5XHx4hK6JKnjK3hq2BAysQuaG",
                "type": "Multikey",
                "controller": "did:cel:zW1bVJvfgEBnKmH8WNShqxSuvySxWysKhhxri9EVPauwLtW",
                "publicKeyMultibase": "zDnaeTk5EbiBNnqo6LSWyUfu5XHx4hK6JKnjK3hq2BAysQuaG"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaeb9RJK8uK6YgB3sPxdgzGPtxVS6dLa8avv1YLzARxgGmD",
                "type": "Multikey",
                "controller": "did:cel:zW1bVJvfgEBnKmH8WNShqxSuvySxWysKhhxri9EVPauwLtW",
                "publicKeyMultibase": "zDnaeb9RJK8uK6YgB3sPxdgzGPtxVS6dLa8avv1YLzARxgGmD"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z4jkJUsSJZYRMGBzdT5MSCTQ5bMoczW3Z9myrhHJ2pGot1j3RQz5XtSbyqV8pNTBeUor6fQwQp6vBJYjPUYZ1hn4g",
          "verificationMethod": "did:cel:zW1bVJvfgEBnKmH8WNShqxSuvySxWysKhhxri9EVPauwLtW#zDnaeTk5EbiBNnqo6LSWyUfu5XHx4hK6JKnjK3hq2BAysQuaG"
        }
      }
    }
  ]
}

4.1.1 Document Creation Algorithm

The following algorithm specifies how to create a new did:cel DID document with a new verification method and establish a cryptographic event log. The algorithm takes three parameters as input: a cryptographic keyPair, an optional map representing the initial didDocument, and options. The output is a map containing the completed did:cel didDocument, the generated verificationMethod, and the initial cryptographicEventLog, or an error. Whenever this algorithm encodes strings, it MUST use UTF-8 encoding.

The initial didDocument can contain previously defined relationships and services, or it can be an empty map.

The options parameter is an optional map structure that allows the definition of a verificationMethod identifier options.vmId and a boolean options.referenced flag, which defaults to false. This flag determines whether the verificationMethod is embedded directly in the assertionMethod or referenced through the DID document’s verificationMethod. If options.vmId is not set, a new identifier is generated automatically.

  1. Create verificationMethod map structure for the assertion:
    1. If the keyPair algorithm is not supported by the Multikey specification, then an UNSUPPORTED_KEY_TYPE error MUST be raised and processing MUST be aborted.
    2. Export the public key from keyPair as a Multikey value. Let publicKey be the result.
    3. Let verificationMethod be a new empty map.
    4. Set the type property of the verificationMethod to Multikey.
    5. If options.vmId exists, then set the id property of the verificationMethod to the concatenation of the # character and the vmId value.
    6. Otherwise, set the id property of verificationMethod to the concatenation of the # character and the publicKeyMultibase representation of the publicKey.
    7. Set the publicKeyMultibase property of the verificationMethod to publicKeyMultibase representation of publicKey.
  2. Verify that the didDocument map is a valid genesis DID document by taking the following steps:
    1. Confirm that the @context property value is a list starting with two strings: https://www.w3.org/ns/did/v1.1 and https://w3id.org/didcel/v1.
      1. If the didDocument does not contain the @context property then set its value accordingly.
      2. Otherwise, if the @context property value does not start with the mandatory contexts listed above, then an INVALID_CONTEXT error MUST be raised and processing MUST be aborted.
    2. Remove the id property from didDocument if it exists.
    3. Confirm that the heartbeatFrequency property value conforms to ISO 8601 duration format.
      1. If the didDocument does not contain the heartbeatFrequency property, then set its value to P3M.
      2. Otherwise, if the heartbeatFrequency property value does not conform to ISO 8601 duration format, then INVALID_HEARTBEAT_FREQUENCY error MUST be raised and processing MUST be aborted.
    4. Confirm that a verificationMethod is bound to the assertionMethod.
      1. If options.referenced is false, then add the verificationMethod to the didDocument.assertionMethod property.
      2. Otherwise, add the verificationMethod to the didDocument.verificationMethod property and add verificationMethod.id to the didDocument.assertionMethod property.
    5. Add an entry to the service property of the didDocument where the type is CelStorageService and the serviceEndpoint is a list of URLs that the controller will use to store the canonical version of the cryptographic event log.
  3. Generate the did:cel identifier (DID) by hashing the canonicalized DID document:
    1. Canonicalize didDocument using JSON Canonicalization Scheme (JCS) as specified in [RFC8785]. Let canonicalizedDidDocument be the result.
    2. Compute the SHA3-256 Multihash of the UTF-8 encoded canonicalized document. Let hash be the result.
    3. Encode hash using base58-btc encoding, prepending the Multibase (z) character to the encoding. Let encodedHash be the result.
    4. Set didDocument.id to the concatenated value of did:cel: and the encodedHash.
    5. Set the controller property of the verificationMethod to didDocument.id.
  4. Create the event by setting event to a map where the operation property is a map containing:
    1. A type property with the value create.
    2. A data property containing the didDocument.
  5. Generate a cryptographic proof for the event using a cryptosuite that is compatible with the generated keyPair, such as ecdsa-jcs-2019:
    1. Let proofOptions be an empty map.
    2. Set the proofPurpose property of proofOptions to assertionMethod.
    3. Set the verificationMethod property of proofOptions to verificationMethod.id.
    4. Generate proof by passing event (the document to sign), proofOptions, and keyPair as inputs to the signature suite sign method.
    5. Add the proof to the proof property of the event.
  6. Create the initial cryptographic event log:
    1. Let cryptographicEventLog be a new map.
    2. Let eventEntry be a new map with event property set to event.
    3. Set log property of the cryptographicEventLog to a new list containg the eventEntry.
  7. Return a map containing:
    1. didDocument: the completed DID document with the computed identifier
    2. verificationMethod: the generated verification method map
    3. cryptographicEventLog: the initial event log with the create event

4.2 Witness

The witness operation provides independent cryptographic attestation for events in a cryptographic event log, establishing temporal evidence and distributed validation of DID operations. After a DID document is modified, witness services—independent entities operating under their own authority—generate data integrity proofs over events in the log. Each witness returns a cryptographic proof that attests the event existed and was witnessed at a specific point in time.

The witnessing process does not modify the event itself; rather, it produces a collection of cryptographic proofs that are attached to the event structure for subsequent verification. These witness attestations serve multiple purposes: they provide temporal anchoring by demonstrating when an event was witnessed, enable auditability through independent third-party validation, and increase resistance to tampering by distributing trust across multiple independent witnesses. Unlike centralized timestamp authorities, the witness architecture allows DID controllers to select witness services, preventing single points of failure while maintaining cryptographic verifiability of the entire event history.

Example 3: Cryptographic event log after witnessing
{
  "log": [
    {
      "event": {
        "operation": {
          "type": "create",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1nSw7i9XbGpDgN2mRPG1ZX9HCrfDmKrjxm5cRjoavcRB2",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeb1ocikBdzmhq79i9bpsa4GteJBw7gYxr4K4uEupUchtr",
                "type": "Multikey",
                "controller": "did:cel:zW1nSw7i9XbGpDgN2mRPG1ZX9HCrfDmKrjxm5cRjoavcRB2",
                "publicKeyMultibase": "zDnaeb1ocikBdzmhq79i9bpsa4GteJBw7gYxr4K4uEupUchtr"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaenThrFERDRotcefC3pn9DBDNSpgNhqoGMh6Z1248pWGK9",
                "type": "Multikey",
                "controller": "did:cel:zW1nSw7i9XbGpDgN2mRPG1ZX9HCrfDmKrjxm5cRjoavcRB2",
                "publicKeyMultibase": "zDnaenThrFERDRotcefC3pn9DBDNSpgNhqoGMh6Z1248pWGK9"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z5NNZCDVDf4yTvXRhWM6Rcs7Yb8DSGgJKTd11eqDf41mHi92V8FLRVuPGjNXBwiSc6C8dkrhxstviW3LmmtCNdmx4",
          "verificationMethod": "did:cel:zW1nSw7i9XbGpDgN2mRPG1ZX9HCrfDmKrjxm5cRjoavcRB2#zDnaeb1ocikBdzmhq79i9bpsa4GteJBw7gYxr4K4uEupUchtr"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3psUVS8NmAgm2jJ6rdYPPU7JodzFsPnR4dvoBpvMbn6FLuDvUVhC1tKQKzy7DZsptkUWtMkhwKB5CTixaVKfb6FZ",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "ze4kZNqsZBtUT6p6snVT1U2U3BuwSgnQoZB9f3Tg76CrnUn3ot23zMCphNcuFhDYfseMumZoZtzouUn8ywgnSizW",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3xCoiQQzJrRRbmxwpCpxUEjKAYtyXtD5N8js8p37n6oiRmL8V6WGymz4htCjTgEpB9QvG8T9Lu8YnRY8AWTafCQE",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    }
  ]
}

4.2.1 Document Witnessing Algorithm

The following algorithm specifies how to generate witness attestations for the most recent event in a cryptographic event log. Witnesses are independent entities that cryptographically sign events to provide decentralized validation and auditability. The algorithm takes a map cel as input, which is the cryptographic event log containing one or more events. Output is an array of proof objects, one from each configured witness, or an error. Whenever this algorithm encodes strings, it MUST use UTF-8 encoding.

  1. Initialize an empty array proofs to collect witness attestations.
  2. Let event be the most recent event in cel.log. This is obtained by accessing the last event in the array.
  3. Let witnesses be an array of witness endpoint URLs that are trusted by the controller of the DID.
  4. For each witness endpoint in witnesses, perform the following steps:
    1. Canonicalize event using the JSON Canonicalization Scheme (JCS) as specified in [RFC8785]. Let canonicalizedEvent be the result.
    2. Compute the SHA3-256 Multihash of the UTF-8 encoded canonicalizedEvent. Let hash be the result.
    3. Encode hash using base58-btc encoding, prepending the Multibase (z) character to the encoding. Let encodedHash be the result.
    4. Send a witnessing request to the witness by performing an HTTP POST on the witness endpoint. The body of the POST is a JSON object containing a digestMultibase property with encodedHash as the associated value. Let proof be the result. If witnessing fails, an error MUST be raised and SHOULD convey an error type of WITNESSING_ERROR.
    5. Append proof to the proofs array.
  5. Set event.proof to the proofs array containing attestations from all witnesses. Each proof in the array represents an independent cryptographic commitment by a witness that the event is valid and has been witnessed at a specific point in time.
Note

The witness operation does not modify the cryptographic event log itself. The returned proofs are attached to the event in the log structure. Witnesses provide independent validation and temporal attestation, enabling auditability and resistance to single points of failure in the DID method infrastructure.

4.3 Read

Example 4: Cryptographic event log where a read is performed
{
  "log": [
    {
      "event": {
        "operation": {
          "type": "create",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaexiPSQFLopHAZaY7JWzwZqC1PwQ3NQ1C8c8X4GWDRuMVo",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaexiPSQFLopHAZaY7JWzwZqC1PwQ3NQ1C8c8X4GWDRuMVo"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zxwVk4ZqzzC92YysXSf7s53ngfuTprHWgRj4RbBArxuVfK4yHgBawTpeUnk6dJB28G1fM7WQFsrkNBBkvw7g8hjC",
          "verificationMethod": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zgAsicZ7sS8egXdHhddR86bdU4FYS7JHMkNMeTmiZEnCV7CwyjCVPhbFTEas23RrHai7vNn6oJPNRPk4r3H9i1Y1",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3H5fUs5orLAUKzhTZEuesmGX29tgek76zxvEqyu9T3RMfnW7HKLvAgJwDANTDUACYVqa8Pnc6u7ajY16zjmcrxpr",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3secaNHL2aVEGMEqjWVn2Tcwt1mtDH7e5NijVGK9WEKrfoCGPDZhoTkbVx3138V9XDHaMmJwN7tcW78sGjEBopqT",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    },
    {
      "event": {
        "previousEventHash": "zW1gau4yGksW2SdRVvrLcDv7NNPRc5KfMUG3G2i3GQS4vSJ",
        "operation": {
          "type": "update",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q"
              }
            ],
            "authentication": [
              {
                "id": "#zDnaeaLf1SVnSWENcayqfX37rYkutG8BjoiLRVWq8XR1Z8pof",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaeaLf1SVnSWENcayqfX37rYkutG8BjoiLRVWq8XR1Z8pof"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaexiPSQFLopHAZaY7JWzwZqC1PwQ3NQ1C8c8X4GWDRuMVo",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaexiPSQFLopHAZaY7JWzwZqC1PwQ3NQ1C8c8X4GWDRuMVo"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z4vUFeRUpqaFLiSwkzN2Qiugw1yeA2DgJC6MTpqiwwzBkSNdaNMSYXAgLWC8UsJFb8dymbDQiBaQySuWGjMxBhGiZ",
          "verificationMethod": "undefined#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z4TExM33QJDdfLJANtBBcDy5YeWWmwh7BYNdBmbx9iL2KnfwrZvNgRs6t5wjUETDpNauipv2nVcj9pJgVaaQ7Y24P",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zRYNbUWmCLR5LExjSEnKCxMRMt6amUYSTvm4SFgofHJstyYZE6FCUvLN6owYGHvhuqnHso6AZ4qyAyLMnhTwF5yH",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z2RdgJy2Amt7yJrU1o915Hda8ZsW1VajBdVMgRZmCAT9bEZvASUCr9s45UNBsqiZXb2U5ng2otxgEt6GRdtyG52wq",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    }
  ]
}

4.3.1 Compression

Cryptographic event logs can become sizeable after a few decades of usage. For example, a production-grade organizational DID document that requires key rotations every three months, with three witnesses per event, can grow to be roughly 5MB in size over those 30 years. However, the contents of the file (such as identifiers) are largely repetitive. Performing compression on the file can result in a 5MB log being reduced to roughly 600KB in size. These significant savings in both network bandwidth and storage make it such that all storage and read operations benefit from the usage of compression. Therefore, all cryptographic event logs MUST be transmitted using gzip compression.

4.3.2 Document Read Algorithm

4.4 Update

The update operation enables modifications to an existing did:cel DID document while maintaining a verifiable audit trail through the cryptographic event log. When changes are made to a DID document—such as adding or removing verification methods, updating service endpoints, or setting expiration dates—the update operation ensures these modifications are cryptographically signed and recorded in the event log. The operation proceeds in two phases: first, the modified DID document receives a fresh data integrity proof signed by an authorized assertion method key; second, a new update event is appended to the cryptographic event log with a hash link to the previous event, creating an immutable chain of document history.

The hashlinking mechanism is central to the update operation's security properties. Each update event includes a previousEventHash property containing the SHA3-256 hash of the prior event. This cryptographic chain ensures that any tampering with historical events would be immediately detectable, as it would break the hash links throughout the chain. The combination of cryptographic proofs on the DID document and hashlinked events in the log provides both authenticity guarantees (the document was signed by an authorized key) and integrity guarantees (the complete history of changes is verifiable and tamper-evident). After performing an update, implementations typically invoke the witness operation to obtain independent temporal attestations of the modification.

An example of an update operation serialized to a cryptographic event log is shown below:

Example 5: Cryptographic event log after did:cel update
{
  "log": [
    {
      "event": {
        "operation": {
          "type": "create",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaexiPSQFLopHAZaY7JWzwZqC1PwQ3NQ1C8c8X4GWDRuMVo",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaexiPSQFLopHAZaY7JWzwZqC1PwQ3NQ1C8c8X4GWDRuMVo"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zxwVk4ZqzzC92YysXSf7s53ngfuTprHWgRj4RbBArxuVfK4yHgBawTpeUnk6dJB28G1fM7WQFsrkNBBkvw7g8hjC",
          "verificationMethod": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zgAsicZ7sS8egXdHhddR86bdU4FYS7JHMkNMeTmiZEnCV7CwyjCVPhbFTEas23RrHai7vNn6oJPNRPk4r3H9i1Y1",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3H5fUs5orLAUKzhTZEuesmGX29tgek76zxvEqyu9T3RMfnW7HKLvAgJwDANTDUACYVqa8Pnc6u7ajY16zjmcrxpr",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3secaNHL2aVEGMEqjWVn2Tcwt1mtDH7e5NijVGK9WEKrfoCGPDZhoTkbVx3138V9XDHaMmJwN7tcW78sGjEBopqT",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    },
    {
      "event": {
        "previousEventHash": "zW1gau4yGksW2SdRVvrLcDv7NNPRc5KfMUG3G2i3GQS4vSJ",
        "operation": {
          "type": "update",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q"
              }
            ],
            "authentication": [
              {
                "id": "#zDnaeaLf1SVnSWENcayqfX37rYkutG8BjoiLRVWq8XR1Z8pof",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaeaLf1SVnSWENcayqfX37rYkutG8BjoiLRVWq8XR1Z8pof"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaexiPSQFLopHAZaY7JWzwZqC1PwQ3NQ1C8c8X4GWDRuMVo",
                "type": "Multikey",
                "controller": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1",
                "publicKeyMultibase": "zDnaexiPSQFLopHAZaY7JWzwZqC1PwQ3NQ1C8c8X4GWDRuMVo"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z4vUFeRUpqaFLiSwkzN2Qiugw1yeA2DgJC6MTpqiwwzBkSNdaNMSYXAgLWC8UsJFb8dymbDQiBaQySuWGjMxBhGiZ",
          "verificationMethod": "undefined#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z4TExM33QJDdfLJANtBBcDy5YeWWmwh7BYNdBmbx9iL2KnfwrZvNgRs6t5wjUETDpNauipv2nVcj9pJgVaaQ7Y24P",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zRYNbUWmCLR5LExjSEnKCxMRMt6amUYSTvm4SFgofHJstyYZE6FCUvLN6owYGHvhuqnHso6AZ4qyAyLMnhTwF5yH",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z2RdgJy2Amt7yJrU1o915Hda8ZsW1VajBdVMgRZmCAT9bEZvASUCr9s45UNBsqiZXb2U5ng2otxgEt6GRdtyG52wq",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    }
  ]
}

4.4.1 Document Update Algorithm

The following algorithm specifies how to update an existing did:cel DID document and record the change in the cryptographic event log. The update operation consists of two phases: regenerating the cryptographic proof on the modified DID document, and appending a hashlinked update event to the log. The algorithm takes a map didDocument (the modified DID document), a map assertionMethod (the key pair to use for signing), and a map cel (the existing cryptographic event log) as input. Output is the updated didDocument with a new proof and the updated cel with the new event appended, or an error. Whenever this algorithm encodes strings, it MUST use UTF-8 encoding.

Issue 1: How much forking protection is enough?

There is always a possibility that either an attacker, or a dishonest controller, will try to fork the history of the cryptographic event log. The specification is currently not specific on which protections are used for each attack. One approach could have the CEL storage services implement some rules as a part of the "registration" step, such as 1) ensure that the log history validates, 2) ensure that the log isn't being rolled back, and 3) if there is a conflict on logs between multiple CEL storage services, the longest log wins. Another approach could utilize a keep-alive approach where a specific offline key is committed to and used for updates within a certain time frame. The specification needs to detail the approach to provide adequate fork protection for a DID.

  1. Update the proof on the DID Document by performing the following steps:
    1. Let newDidDocument be a copy of didDocument.
    2. If newDidDocument contains a proof property, remove it. Any existing proof will be replaced with a new proof reflecting the current state of the document.
    3. Create a data integrity proof with the cryptosuite and a signer derived from assertionMethod. Let proof be the result of this step.
    4. Set newDidDocument.proof to proof.
    5. Set didDocument to newDidDocument.
  2. Append the update event to the cryptographic event log by performing the following steps:
    1. If cel.log does not contain any events, an error MUST be raised and SHOULD convey an error type of MALFORMED_CEL_ERROR.
    2. Perform the following steps to create a hash link to the previous event:
      1. Let lastEvent be the most recent event in cel.log, which will be the last entry in the array.
      2. Canonicalize lastEvent using JSON Canonicalization Scheme (JCS) as specified in [RFC8785]. Let canonicalizedEvent be the result.
      3. Compute the SHA3-256 Multihash of the UTF-8 encoded canonicalizedEvent. Let hash be the result.
      4. Encode hash using base58-btc encoding, prepending the Multibase (z) character to the encoding. Let encodedHash be the result.
    3. Create a new event object (map updateEvent) with the following structure:
      1. Set updateEvent.event to a new map.
      2. Set updateEvent.event.previousEventHash to encodedHash. This creates the hashlinked chain connecting this event to the previous event.
      3. Set updateEvent.event.operation to a new map.
      4. Set updateEvent.event.operation.type to the string update.
      5. Set updateEvent.event.operation.data to the updated didDocument (which now includes the new proof).
    4. Append updateEvent to cel.log.
  3. Return the updated didDocument and updated cel. The didDocument now has a fresh cryptographic proof, and the cel contains a new hashlinked event recording the update operation.
Note

The update operation maintains the integrity of the cryptographic event log through hashlinking. Each update event includes a previousEventHash property containing the hash of the prior event, creating a verifiable chain that prevents tampering and enables auditing of the DID document's complete history. After updating, implementations invoke the witness operation to obtain independent attestations of the update event.

4.5 Heartbeat

The heartbeat operation prevents an attacker, such as a compromised cryptographic event log storage service, from truncating a cryptographic log. If the attacker attacker attempts to truncate the cryptographic log beyond the heartbeat window for a specific DID, it will be interpreted as a deactivation by a verifier. DID documents created with the did:cel method can include a heartbeatFrequency property that specifies how frequently heartbeat events should be generated to prevent automatic deactivation. When the time elapsed since the last event in the cryptographic event log exceeds the heartbeatFrequency duration, the DID is considered deactivated by verifiers or cryptographic event log storage services. Any events, including heartbeat events, reset this timer, demonstrating that the DID controller remains in control and wishes to keep the DID active.

Unlike update operations that modify the DID document, heartbeat events contain only an operation structure with a type of heartbeat and no associated data payload. This minimal structure reduces the computational cost and storage requirements for maintaining DID liveness while still providing cryptographic proof that the DID controller possesses the private keys necessary to sign events. The heartbeat event is signed using an assertion method key and hashlinked to the previous event in the log, maintaining the integrity of the event chain. After creating a heartbeat event, implementations typically invoke the witness operation to obtain independent temporal attestations, which provide evidence that the heartbeat occurred at a specific point in time and can be used to verify compliance with the heartbeatFrequency policy.

Example 6: Cryptographic event log after a heartbeat event
{
  "log": [
    {
      "event": {
        "operation": {
          "type": "create",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1oEeMMxDEgBkt5fay1h9FGVvVk1rmS8uw1KZJ4rFAgu3T",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeQgqTA9zL2JPsN5Wd7Zdx8oTawHkvFo98tpUNBrb87RbV",
                "type": "Multikey",
                "controller": "did:cel:zW1oEeMMxDEgBkt5fay1h9FGVvVk1rmS8uw1KZJ4rFAgu3T",
                "publicKeyMultibase": "zDnaeQgqTA9zL2JPsN5Wd7Zdx8oTawHkvFo98tpUNBrb87RbV"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaex7wVcG2FaWwCz7fGiA72za5bhy83yqSp4g4ibpNY2xHA",
                "type": "Multikey",
                "controller": "did:cel:zW1oEeMMxDEgBkt5fay1h9FGVvVk1rmS8uw1KZJ4rFAgu3T",
                "publicKeyMultibase": "zDnaex7wVcG2FaWwCz7fGiA72za5bhy83yqSp4g4ibpNY2xHA"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z5vcALjQQXQo73ZCiT54azX7YYSH6gokbKxNjgaB1RKVJciA8smPBWo21UBdMR9CCKMtGesiAGZR2jifi2HAVvLFo",
          "verificationMethod": "did:cel:zW1oEeMMxDEgBkt5fay1h9FGVvVk1rmS8uw1KZJ4rFAgu3T#zDnaeQgqTA9zL2JPsN5Wd7Zdx8oTawHkvFo98tpUNBrb87RbV"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z2RyKqAnaYeZ9TfwxtyK1U9JNMuDmEQWe9QUCZHKehWaU3ficCKDiRgNvfeUYfAZ3bu3hWoN6QeGWFrsb1k3wb31g",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3ubBG8BevXpCUooPyqq4cSt51nKMEK797LsJdrtex1Y8LVhvVqr33FsKuUcZa2RLF3PqhDmrbsvudxUvGxhgfp1X",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3u8wAYedBwAFLHnFQUStCVYRUhMy7uQTdPZyUQ85jLhKsvZ9YdyfL4JG4HRxSjxhvWRQrM6sfxM9aPNr6AkiZTvc",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    },
    {
      "event": {
        "previousEventHash": "zW1i3iMU6mzLVh6vwGS9E9o3NyQKVg7spE1GuxkysMTmQgD",
        "operation": {
          "type": "heartbeat"
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z2AuEqJkuHLTXnFPzdCyb6bdZcizVURP4o1vUEkYc5mdD9oRFdwW7pDrQhm8ZxCrVgKkkuBm5476aDhP6FEh5JBix",
          "verificationMethod": "undefined#zDnaeQgqTA9zL2JPsN5Wd7Zdx8oTawHkvFo98tpUNBrb87RbV"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zAhpkdc1yK3RK7VpzWUAasGXoM8bmc8fgrNMHpDsNugjnGuGgsYqWXG41fQKyN8DESG8Cd9j5VgdU3ab1g6bB73F",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3ZCMSAGwTiL4mGQtRXxF9ZqdUk27TnKszwnDWMgyXdNk7DeqqEdfKesLxZMD582tp64buiqb3ZvGXBistjG94bur",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zTg9zqgQbrRAT84uE5nNRvMerNXp3S1tLBFL4rwDi9U1U1DnNx4D3zAWigBwhbDs3DgSUQrDf9KAyynuZhx51GaP",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    }
  ]
}

4.5.1 Document Heartbeat Algorithm

The following algorithm specifies how to create a heartbeat event and append it to the cryptographic event log. The heartbeat operation demonstrates continued control of the DID without modifying the DID document contents. The algorithm takes a map assertionMethod (the key pair to use for signing) and a map cel (the existing cryptographic event log) as input. Output is the updated cel with the heartbeat event appended, or an error. Whenever this algorithm encodes strings, it MUST use UTF-8 encoding.

  1. Create a hash link to the previous event:
    1. Let lastEvent be the most recent event in cel.log, which will be the last entry in the array.
    2. Canonicalize lastEvent using JSON Canonicalization Scheme (JCS) as specified in [RFC8785]. Let canonicalizedEvent be the result.
    3. Compute the SHA3-256 Multihash of the UTF-8 encoded canonicalizedEvent. Let hash be the result.
    4. Encode hash using base58-btc encoding, prepending the Multibase (z) character to the encoding. Let encodedHash be the result.
  2. Create the heartbeat event object:
    1. Create a new event object (map heartbeatEvent).
    2. Set heartbeatEvent.previousEventHash to encodedHash. This creates the hashlinked chain connecting this event to the previous event.
    3. Set heartbeatEvent.operation to a new map.
    4. Set heartbeatEvent.operation.type to the string heartbeat.
  3. Generate a cryptographic proof for heartbeatEvent:
    1. Create a data integrity proof using the cryptosuite compatible with assertionMethod (such as ecdsa-jcs-2019). Let proof be the result. The proofPurpose MUST be set to assertionMethod.
    2. Set heartbeatEvent.proof to proof.
  4. Append the heartbeat event to the cryptographic event log:
    1. Create a new log entry (map logEntry) with an event property set to heartbeatEvent.
    2. Append logEntry to cel.log.
  5. Return the updated cel. The cryptographic event log now contains a new hashlinked heartbeat event that demonstrates continued control without modifying the DID document.
Note

After creating a heartbeat event, implementations invoke the witness operation to obtain independent temporal attestations. The timestamps in witness proofs provide evidence of when the heartbeat occurred, which can be used to verify compliance with the heartbeatFrequency policy specified in the DID document. Verifiers might reject DIDs where the time elapsed since the last event exceeds the heartbeatFrequency duration, treating such DIDs as potentially deactivated.

4.6 Deactivate

The deactivate operation permanently disables a did:cel DID, signaling that the DID controller no longer wishes to use the identifier and that it is not to be trusted for any future operations. Once a deactivation event is added to the cryptographic event log and witnessed, the DID enters a terminal state where no further updates, heartbeats, or other operations can be performed. Deactivation is irreversible—the DID cannot be reactivated or modified after a deactivation event is recorded. This operation is typically used when a DID controller is retiring an identifier or is migrating to a new DID and wishes to explicitly deprecate the old identifier to prevent confusion or misuse.

Similar to heartbeat operations, deactivation events contain only an operation structure with a type of deactivate and no associated data payload. The deactivation event is signed using an assertion method key from the current DID document and hashlinked to the previous event in the log, proving that the DID controller authorized the deactivation. After creating a deactivation event, implementations invoke the witness operation to obtain independent attestations of the deactivation, which provides temporal evidence and distributed validation that the deactivation occurred. Verifiers that encounter a cryptographic event log containing a deactivation event reject any future operations that use the DID after it is deactivated, treating it as permanently invalid thereafter. The complete event log, including the deactivation event, remains accessible for historical auditing and verification purposes, but the DID itself is no longer usable for authentication, assertion, or any other cryptographic operations.

Example 7: Cryptographic event log after did:cel deactivation
{
  "log": [
    {
      "event": {
        "operation": {
          "type": "create",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1kZFWb8dNEggBF8hCi6Uw6MYPz9wHD47ugaCP4QtGyshD",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeWXHW1LVG4TS3jzPJ7QhKs27qTvLTgeLzdPjP7wUH7Rqk",
                "type": "Multikey",
                "controller": "did:cel:zW1kZFWb8dNEggBF8hCi6Uw6MYPz9wHD47ugaCP4QtGyshD",
                "publicKeyMultibase": "zDnaeWXHW1LVG4TS3jzPJ7QhKs27qTvLTgeLzdPjP7wUH7Rqk"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaefe4CS8ieyUs8fUZFfsjaWDCgNJszHyxgrAQvFkKXwsPM",
                "type": "Multikey",
                "controller": "did:cel:zW1kZFWb8dNEggBF8hCi6Uw6MYPz9wHD47ugaCP4QtGyshD",
                "publicKeyMultibase": "zDnaefe4CS8ieyUs8fUZFfsjaWDCgNJszHyxgrAQvFkKXwsPM"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z64ZmxkZg28hk5SdkcUvokiU61ePg8YEUhAkp1Tygrx2J46eHEJBefqymNDT2DxGgwP6UUuYuTCBVd7Jvyi856pCx",
          "verificationMethod": "did:cel:zW1kZFWb8dNEggBF8hCi6Uw6MYPz9wHD47ugaCP4QtGyshD#zDnaeWXHW1LVG4TS3jzPJ7QhKs27qTvLTgeLzdPjP7wUH7Rqk"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3r8iVLbmSrpVRPyQNbQWsTxXzxFnnuejyDL1PVUCduZnDZoTmjZ65BUn2WdLTKgVqYxJ79x9cQ4sdXodSvMyoMnH",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z4UXRi9JHVjx6gT8xhjXny1iMw7dqqPb8BTbt4HSjAaHcAqRRfp6ZAaQRZn3NoaQCpxGR2Q7UxJEXLE7tyGi7f23J",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z5MXtkiLY8koDcFrPSDqY6HRu3cnMzfB8nGeCvi6f871fZb1ZWLpAhB22Pvt8zkoF24sbUdHFfHftzLF6zRfL5o6",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    },
    {
      "event": {
        "previousEventHash": "zW1kHeFYDHQiP3rQo4tTpNnTjRkduVVCpTQeiBREiT1F3Uw",
        "operation": {
          "type": "update",
          "data": {
            "@context": [
              "https://www.w3.org/ns/did/v1.1",
              "https://w3id.org/didcel/v1"
            ],
            "id": "did:cel:zW1kZFWb8dNEggBF8hCi6Uw6MYPz9wHD47ugaCP4QtGyshD",
            "heartbeatFrequency": "P3M",
            "assertionMethod": [
              {
                "id": "#zDnaeWXHW1LVG4TS3jzPJ7QhKs27qTvLTgeLzdPjP7wUH7Rqk",
                "type": "Multikey",
                "controller": "did:cel:zW1kZFWb8dNEggBF8hCi6Uw6MYPz9wHD47ugaCP4QtGyshD",
                "publicKeyMultibase": "zDnaeWXHW1LVG4TS3jzPJ7QhKs27qTvLTgeLzdPjP7wUH7Rqk"
              }
            ],
            "authentication": [
              {
                "id": "#zDnaeuF97oWNu5PmeLKMWszLcvXugZvP9qABouF5AFhiGuLmW",
                "type": "Multikey",
                "controller": "did:cel:zW1kZFWb8dNEggBF8hCi6Uw6MYPz9wHD47ugaCP4QtGyshD",
                "publicKeyMultibase": "zDnaeuF97oWNu5PmeLKMWszLcvXugZvP9qABouF5AFhiGuLmW"
              }
            ],
            "recovery": [
              {
                "id": "#zDnaefe4CS8ieyUs8fUZFfsjaWDCgNJszHyxgrAQvFkKXwsPM",
                "type": "Multikey",
                "controller": "did:cel:zW1kZFWb8dNEggBF8hCi6Uw6MYPz9wHD47ugaCP4QtGyshD",
                "publicKeyMultibase": "zDnaefe4CS8ieyUs8fUZFfsjaWDCgNJszHyxgrAQvFkKXwsPM"
              }
            ],
            "service": {
              "type": "CelStorageService",
              "serviceEndpoint": [
                "https://storage.gamma.example/v1",
                "https://2001:db8:85a3::8a2e:370:7334/v1",
                "https://celstorageiu7vnjjbwkhpilnemxj7ase3mhbshg7kx5tfydaniltxjqhy.onion/"
              ]
            }
          }
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z3Zq18W57EsyCo6HyC8J7dTHKnF8rhdjcSAwPowZMWCC4YnRhSnFDoBWvzd1bf12ANAJuATYNJgHU9rw33KcjiXSR",
          "verificationMethod": "undefined#zDnaeWXHW1LVG4TS3jzPJ7QhKs27qTvLTgeLzdPjP7wUH7Rqk"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zGc92MpjUPcTsr6u9oTDJzavKrwyWJNZGX4SSJBug2XvDDt3dKQpta9XinffqJtXCzqJB4BEFbUsRJHwmwPod1zW",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zBEWYoTvZZJteb3GquzjomzLwsnvYksM99eGY1wz6oTXwJRKgD1v2WPsvq154xgK2qYrQziJSoCRtpKdVcWtK5LD",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zMZCrH9z26V3CnutDWf3P7DcfNNu48xZxPnJ1b5JucDy7fV8a9M3jxa18bqcMV8UMqg3JoBL24SNLk95tRpb6Xqq",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    },
    {
      "event": {
        "previousEventHash": "zW1pXxiAWqfXnnCbbna1ceAPPmdHWL511E5wU17n4HKBppM",
        "operation": {
          "type": "deactivate"
        },
        "proof": {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "zUiBRBMm1x3nzf3q8bcyMQ2HgarLqpy4vHdaBQqJzQgJ19QLHQNYVjHoc4BgYvLiDLW68dcs7vwGhmgikKQ1bWJS",
          "verificationMethod": "undefined#zDnaeWXHW1LVG4TS3jzPJ7QhKs27qTvLTgeLzdPjP7wUH7Rqk"
        }
      },
      "proof": [
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z35smbUdz4CRde7byCLC5m7PWND4jdzxqfkSDMMG2MahDgungexAq2TZgyoWpBkArtphFGEsxY4bsUb2Hv91dDYxD",
          "verificationMethod": "did:web:red-witness.example#vm-red-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z5pSfsevk1Ecbtw8oJdFvvDU4duZHfsMqycZDZqEPzFKgsWQMaLUmtK1yQUXfK99aFqEspd4qMef8U8TuJGXvTcip",
          "verificationMethod": "did:web:green-witness.example#vm-green-1"
        },
        {
          "type": "DataIntegrityProof",
          "cryptosuite": "ecdsa-jcs-2019",
          "created": "2025-12-06T22:09:08Z",
          "proofPurpose": "assertionMethod",
          "proofValue": "z5seGYhv3iT7oop2NUhrs1NrKCQ9iUjxryy2bCzbXtRtSPTUuCiydFLGs9XhHL26jFSLbedqknmFk4eXMySoRDSx6",
          "verificationMethod": "did:web:blue-witness.example#vm-blue-1"
        }
      ]
    }
  ]
}

4.6.1 Document Deactivation Algorithm

The following algorithm specifies how to create a deactivation event and append it to the cryptographic event log. The deactivation operation permanently disables the DID, preventing any further operations. The algorithm takes a map assertionMethod (the key pair to use for signing) and a map cel (the existing cryptographic event log) as input. Output is the updated cel with the deactivation event appended, or an error. Whenever this algorithm encodes strings, it MUST use UTF-8 encoding.

  1. Create a hash link to the previous event:
    1. Let lastEvent be the most recent event in cel.log, which will be the last entry in the array.
    2. Canonicalize lastEvent using JSON Canonicalization Scheme (JCS) as specified in [RFC8785]. Let canonicalizedEvent be the result.
    3. Compute the SHA3-256 Multihash of the UTF-8 encoded canonicalizedEvent. Let hash be the result.
    4. Encode hash using base58-btc encoding, prepending the Multibase (z) character to the encoding. Let encodedHash be the result.
  2. Create the deactivation event object:
    1. Create a new event object (map deactivateEvent).
    2. Set deactivateEvent.previousEventHash to encodedHash. This creates the hashlinked chain connecting this event to the previous event.
    3. Set deactivateEvent.operation to a new map.
    4. Set deactivateEvent.operation.type to the string deactivate.
  3. Generate a cryptographic proof for deactivateEvent:
    1. Create a data integrity proof using the cryptosuite compatible with assertionMethod (such as ecdsa-jcs-2019). Let proof be the result. The proofPurpose MUST be set to assertionMethod.
    2. Set deactivateEvent.proof to proof.
  4. Append the deactivation event to the cryptographic event log:
    1. Create a new log entry (map logEntry) with an event property set to deactivateEvent.
    2. Append logEntry to cel.log.
  5. Return the updated cel. The cryptographic event log now contains a deactivation event that permanently disables the DID. No further operations can be performed on this DID.
Note

Deactivation is a terminal operation that cannot be reversed. Once a deactivation event is added to the cryptographic event log and witnessed, the DID is permanently disabled. Verifiers that encounter a cryptographic event log containing a deactivation event reject any operations after the DID was deactivated. Implementations that allow deactivation might require additional authentication beyond the standard assertion method signature, such as multi-signature authorization or confirmation from recovery keys, to prevent accidental or malicious deactivation of active DIDs. The complete event log remains accessible for historical auditing, but the DID itself is no longer valid for any cryptographic operation beyond the deactivate timestamp.

5. Privacy Considerations

This section is non-normative.

This section contains a variety of privacy considerations that people using the did:cel Method are advised to consider before deploying this technology in a production setting. Readers are urged to read the Privacy Considerations section of the Controlled Identifiers v1.0 specification, as well as the Privacy Considerations section of the Decentralized Identifiers (DIDs) v1.0 specification, before reading this section.

5.1 Public Event Log Visibility

The cryptographic event log (cryptographic event log) for a DID is designed to be publicly verifiable, which means that the complete history of DID document operations, including creation, updates, additions, and removals of verification methods and services, is permanently recorded and accessible. This transparency enables auditability and trust but comes at the cost of revealing temporal patterns and the evolution of a DID's capabilities over time. Observers can analyze the log to determine when verification methods were added or expired, when services were introduced or removed, and how frequently the DID document has been modified.

To mitigate this privacy concern, implementers might carefully consider what information is included in DID documents and when updates are performed. Batch multiple related changes into a single update operation when possible to reduce the granularity of information exposed through temporal analysis. For use cases requiring higher privacy, consider using ephemeral DIDs that are rotated regularly, or employing DIDs with shorter active periods for their event logs. Organizations might also document their DID Document update policies to help users understand the privacy implications of using their DID-related services.

5.2 Correlation via Witness Selection

The cryptographic event log architecture relies on witness services to provide attestations for DID operations. The specific set of witnesses chosen to attest to an event can serve as a correlatable fingerprint, especially if the witness configuration is unique or rarely used. If a DID consistently uses the same set of witnesses across multiple operations, or if the witness selection pattern is distinctive, observers might be able to correlate different DIDs or activities as belonging to the same entity or organization. This correlation risk increases when custom witness services are deployed or when non-standard witness configurations are used.

To reduce correlation risk, implementers might use commonly deployed and widely adopted witness services when privacy is a concern. Using the same witness configuration as other entities in the ecosystem provides herd privacy by making it difficult to distinguish one DID controller from another based solely on witness selection. Standardizing witness selection policies across an ecosystem can also help establish common configurations that enhance privacy through ubiquity.

5.3 Temporal Metadata Leakage

Each event in the cryptographic event log includes temporal information, either explicitly through timestamps in witness proofs or implicitly through the sequence and timing of operations. This temporal metadata can reveal patterns about the DID controller's activities, operational hours, time zones, or response times to security incidents. For example, if verification methods are consistently updated during specific hours, this might reveal information about the organization's business hours or geographic location. Rapid succession of updates might indicate automated processes or security incidents, while long periods of inactivity followed by bursts of activity can reveal operational patterns.

Implementers can mitigate temporal metadata leakage by implementing delays or jitter in update operations to obscure the precise timing of changes. Automated systems might avoid predictable update schedules and instead use randomized timing within acceptable windows. For sensitive operations, consider batching updates and releasing them at randomized intervals to prevent timing correlation. Organizations might also be aware that even without explicit timestamps, the sequence of events and witness attestation timing can leak temporal information, so careful consideration of when to perform DID operations is important for privacy-sensitive use cases.

5.4 Hashlinked History Immutability

The hashlinking mechanism that chains events together in the cryptographic event log provides strong integrity guarantees but also creates an immutable, permanent record of all DID operations. Once an event is added to the log, witnessed, and stored, it cannot be removed or modified without breaking the cryptographic chain. This means that information about previous verification methods, services, or other metadata remains permanently visible in the log even after being removed from the current DID document. This immutability can be problematic for privacy if sensitive information was inadvertently included in earlier versions of the DID document, or if the history of changes itself reveals sensitive information about the DID controller's activities or relationships.

To address the immutability concern, implementers might exercise caution when including information in DID documents, as any data added will become part of the permanent record. Before performing operations, carefully review the information being added to ensure it does not contain sensitive data that needs to remain private. For cases where the historical record becomes problematic, DID controllers can deactivate the current DID and create a new one, though this breaks continuity and requires updating all systems that reference the old DID. Alternatively, implement clear documentation and guidelines for DID controllers about what information might and might not be included in DID documents to prevent privacy issues before they occur.

5.5 DID Identifier Persistence

A DID identifier in the did:cel method is derived from cryptographic material from the initial creation event, making it a persistent self-certifying identifier that is correlatable across all uses. Unlike some privacy-preserving identifier systems that allow for easy rotation or unlinkable presentations, a did:cel identifier remains constant and serves as a permanent correlation point. Any entity that observes the DID identifier in multiple contexts can definitively link those interactions as involving the same DID controller. This persistence is valuable for establishing long-term identity and trust but directly conflicts with privacy goals that require unlinkability between different interactions or contexts.

For scenarios requiring unlinkability, implementers might not reuse the same DID across different contexts or relationships. Instead, create separate DIDs for different purposes, relationships, or contexts where correlation might be prevented. Implement DID management practices that include regular rotation of DIDs when appropriate, and clearly document which DIDs are used for which purposes. Organizations might also provide tooling to help users manage multiple DIDs and understand the privacy implications of DID reuse. For use cases where both persistence and privacy are required, consider layering additional privacy-preserving mechanisms on top of the DID infrastructure, such as using verifiable credentials with unlinkable presentation features.

5.6 Verification Method Enumeration

DID documents contain verification methods that specify the cryptographic keys and their purposes (authentication, assertion, key agreement, etc.). The complete set of verification methods, their types, cryptographic algorithms, and relationship assignments can serve as a unique fingerprint for a DID, especially when non-standard cryptographic suites are used or when the combination of verification methods is unusual. Even when using common cryptographic suites, the specific number and configuration of verification methods for different purposes can reveal information about the DID controller's intended use cases, security posture, or organizational structure.

To reduce the identifiability of DIDs through verification method enumeration, implementers might favor standard, commonly used verification method configurations that are widely deployed in the ecosystem. Avoid creating unique or unusual combinations of verification methods unless specifically required. When possible, use the minimum number of verification methods necessary for the intended functionality to reduce the uniqueness of the configuration. For organizations deploying multiple DIDs, consider standardizing on common verification method templates that are used across many DIDs to prevent fingerprinting. Documentation might also guide users on recommended verification method configurations that balance functionality with privacy considerations.

5.7 Service Endpoint Disclosure

DID documents can include service endpoints that specify how to interact with services related to the DID controller. These service endpoints often contain URLs or other network identifiers that reveal information about the DID controller's infrastructure, service providers, or operational environment. Service endpoints might point to specific servers, domains, or third-party services, which can be used to correlate DIDs, identify the organizations or individuals behind them, or map out relationships between different entities. Even when service endpoints use common infrastructure, the specific combination or configuration of services can serve as an identifying characteristic.

Implementers might carefully consider whether service endpoints need to be included in the DID document itself, or whether they could be communicated through other channels that provide better privacy properties. When service endpoints might be included, use generic or shared infrastructure that does not reveal specific information about the DID controller. Consider using privacy-preserving relay services, proxy servers, or shared service infrastructure that is used by multiple entities to prevent correlation. Avoid including service endpoints that point to unique or rarely used domains. For higher privacy scenarios, service endpoint information might be exchanged out-of-band or through encrypted communication channels rather than being published in the public DID document.

5.8 Witness Service Metadata

When witness services attest to cryptographic event log events, they create proofs that include metadata such as their witness identifier, the cryptographic suite used, and timing information. While this metadata is necessary for verification, it can also reveal information about the DID controller's relationships with witness services, their witness selection strategy, and potentially their geographic location or operational preferences. If a DID consistently uses witnesses that are associated with specific geographic regions, industries, or organizations, this association can reveal information about the DID controller. Additionally, the specific combination of witness services chosen might reveal business relationships or trust relationships that the DID controller has established.

To mitigate privacy concerns related to witness metadata, implementers might select witness services that are widely used and geographically distributed to avoid revealing location information. When possible, use witness services that are operated by neutral, well-known entities rather than industry-specific or organization-specific witnesses that might reveal affiliations. Documentation might guide users on selecting witness services that align with their privacy requirements, and ecosystems might encourage the deployment of diverse, broadly available witness services that can be used interchangeably to enhance herd privacy.

5.9 Long-term Cryptographic Commitment

The cryptographic algorithms and key types chosen during DID creation and throughout the DID's lifecycle represent long-term commitments that are permanently recorded in the cryptographic event log. These cryptographic choices can reveal information about when the DID was created (based on algorithm popularity at that time), the security requirements or preferences of the DID controller, and potentially the systems or software used to create the DID. As cryptographic algorithms age and new algorithms are adopted, the continued use of older algorithms or the early adoption of newer ones can serve as identifying characteristics. Furthermore, the cryptographic choices reveal the DID controller's security posture and risk tolerance.

Implementers might provide clear guidance on recommended cryptographic algorithms that balance security requirements with privacy considerations. Using widely adopted, current best-practice cryptographic algorithms helps provide herd privacy by ensuring that many DIDs share similar cryptographic profiles. Organizations might plan for cryptographic agility by supporting algorithm migration paths that allow updating to newer algorithms without requiring DID replacement. When upgrading cryptographic algorithms, coordinate with broader ecosystem adoption to avoid standing out as an early or late adopter. Documentation might explain the privacy implications of different cryptographic choices and provide recommendations for standard configurations that are appropriate for different use cases.

5.10 Resolution Privacy

Resolving a DID to obtain its current DID document and verify the cryptographic event log requires accessing the log data, which is stored in various locations. The act of resolving a DID can reveal information about the resolver's interest in that particular DID to the entities operating the storage or retrieval infrastructure. This creates potential for surveillance, tracking of resolution patterns, or profiling of which DIDs are being resolved by which entities. Network-level metadata such as IP addresses, timing of resolution requests, and patterns of correlated resolutions can further compromise privacy by revealing resolver identity or activities.

To enhance resolution privacy, implementers might use privacy-preserving resolution mechanisms such as proxies, Oblivious HTTP, VPNs, or onion routing when resolving DIDs. Aggressive caching of DID documents and cryptographic event log data reduces the frequency of resolution requests and limits the metadata exposed to storage providers. Consider using decentralized resolution infrastructure that does not rely on single points that can monitor resolution patterns. Implement resolution protocols that minimize metadata leakage, such as fetching data through encrypted channels or using obfuscation techniques that prevent correlation of multiple resolution requests. For high-privacy scenarios, design systems that pre-fetch or batch resolve multiple DIDs to obscure which specific DIDs are of interest, and utilize privacy-preserving query protocols where available.

6. Security Considerations

This section is non-normative.

This section contains a variety of security considerations that people using the did:cel Method are advised to consider before deploying this technology in a production setting. Readers are urged to read the Security Considerations section of the Controlled Identifiers v1.0 specification, as well as the Security Considerations section of the Decentralized Identifiers (DIDs) v1.0 specification, before reading this section.

6.1 Witness Collusion and Compromise

The security of the cryptographic event log relies on witness services providing independent attestations to DID document operations. If a sufficient number of witnesses collude or are compromised by an attacker, they could deny witnessing calls from specific IP addresses or generate invalid proofs to deny a DID controller the ability to witness a particular event. The impact of such an attack depends on how many witnesses are required for an event to be considered valid and how many witnesses an attacker can control. If witnesses are operated by a single entity or share common infrastructure, the risk of coordinated compromise increases significantly.

To mitigate witness collusion risks, implementers are encouraged to select witnesses operated by independent entities with diverse operational and jurisdictional characteristics. Systems that verify DIDs can require attestations from a minimum number of witnesses before accepting an event as valid, and can maintain lists of trusted witnesses with known good security practices. DID controllers are encouraged to select geographically and organizationally distributed witnesses to minimize the risk of coordinated attacks. Monitoring witness behavior over time can help detect anomalies that might indicate compromise, such as witnesses consistently refusing to signing events that other witnesses sign. For critical applications, implementing witness rotation policies or requiring attestations from a larger pool of witnesses can provide additional security margins.

6.2 Key Rotation and Revocation

When a cryptographic key used in a DID document is compromised or needs to be rotated for operational reasons, the DID controller faces the challenge of updating the DID document while maintaining the integrity and verifiability of the cryptographic event log. The key rotation process itself requires signing operations using existing keys, but if those keys are compromised, an attacker might perform unauthorized rotations before the legitimate DID controller can act. Additionally, the immutable nature of the log means that compromised keys remain visible in the historical record, potentially allowing attackers to forge signatures on historical DID documents if proper expiration handling is not implemented.

Implementers are encouraged to implement key expiration mechanisms using the expires property on verification methods, which limits the time window during which a compromised key can be abused. When rotating keys, DID controllers are advised to follow a process of first adding new keys to the DID document, then expiring old keys, and only after confirming the new keys are functional should the old keys be removed. This overlapping approach ensures continuity of operations during rotation. For critical keys, maintaining offline backup keys with authority to perform emergency rotations can provide recovery paths when primary keys are compromised. Conforming systems that verify data integrity proofs check verification method expiration times and reject proofs created after a verification method has expired, limiting the damage from compromised keys. Regular key rotation schedules, even without evidence of compromise, can reduce the impact window of undetected key compromises.

6.3 Hash Collision Resistance

The did:cel method relies on SHA3-256 cryptographic hashing for multiple security-critical functions: generating DID identifiers from DID documents, creating hash links between events in the cryptographic event log, and ensuring the integrity of the event chain. If SHA3-256 were to become vulnerable to collision attacks where two different inputs produce the same hash output, attackers could create fraudulent DID documents that resolve to the same DID identifier, forge event chain links to hide modifications, or substitute malicious events while maintaining apparent chain integrity. The security of the current DID method depends on the continued collision resistance of SHA3-256, though upgrading to a newer cryptographic hashing algorithm is possible and supported.

While SHA3-256 is currently considered cryptographically secure with no known practical collision attacks, implementers are advised to monitor cryptographic research for any developments that might weaken SHA3-256. Systems can be designed with cryptographic agility in mind, allowing for future migration to stronger hash functions if SHA3-256 becomes compromised. When verifying DIDs, conforming implementation validate not just that hash links are correctly formed, but also that the entire chain of events maintains integrity from the creation event forward. For long-lived DIDs, DID controllers might consider planning for eventual migration to stronger cryptographic primitives before SHA3-256 reaches end of life, though the timeline for such migrations is measured in decades given current cryptographic knowledge.

6.4 Replay Attack Prevention

Events in the cryptographic event log contain data integrity proofs and witness attestations that are valid cryptographic signatures. Without proper safeguards, an attacker might capture a valid event from one DID's log and attempt to replay it in a different context, such as in another DID's log or at a different position in the same log. While the hashlinking mechanism provides some protection by binding events to specific positions in the chain, attackers might attempt to fork a log at an earlier point and replay captured events to create a fraudulent alternate history. The self-contained nature of events means that signatures remain mathematically valid even when presented out of their intended context.

The hashlinking of events through the previousEventHash property provides the primary defense against replay attacks by binding each event to a specific position in the event chain. Conforming implementations that verify cryptographic event logs validate that each event's previousEventHash hash correctly matches the hash of the preceding event, and that the chain is unbroken from the creation event to the most recent event. Systems that maintain state about known DIDs can track the highest event sequence number they have seen for each DID and reject events that appear to rewind the log.

6.5 Event Ordering and Forking

The cryptographic event log creates a linear chain of events through hashlinking, but without additional coordination mechanisms, a DID controller or an attacker with access to the DID controller's keys could create multiple divergent chains (forks) from the same parent event. This could result in different observers seeing different versions of the DID document depending on which fork they have accessed. A compromised or malicious DID controller might try to selectively present different forks to different verifiers], creating confusion about the authoritative state of the DID document.

Detecting forks requires verifiers to compare event logs from multiple cryptographic event log storage services listed in the DID Document history and identify cases where divergent chains exist for the same DID. The cryptographic event log storage services-based architecture provides fork detection that is independent of the witness services. Clear policies about how verifiers handle fork detection, such as "longest fork always wins", and whether cryptographic event log services alert each other or DID observers, can strengthen the overall security posture against forking attacks.

6.6 Proof Verification Requirements

Each event in a cryptographic event log contains data integrity proofs on the operation and one or more witness proofs attesting to the event. Verifying the complete log requires checking every proof in every event from the creation event forward, which involves cryptographic signature verification operations, hash computations, and canonicalization of JSON data structures. For DIDs with long histories containing many events and witness proofs, the computational cost of full verification can be significant, potentially leading to resource exhaustion or denial-of-service conditions when processing maliciously crafted logs with excessive events or operation data.

Implementations are encouraged to set reasonable limits on the resources they will expend when verifying cryptographic event logs, including maximum numbers of events to process, maximum verification time, and maximum memory usage. When possible, verification can be optimized by caching the results of verifying earlier portions of the log and only verifying new events since the last cached verification point. For applications that do not require complete historical verification, implementations might depend on the cryptographic event log storage services to verify the history since they are not supposed to accept cryptographic event logs with malformed histories. Rate limiting the acceptance of DID resolution requests can prevent attackers from overwhelming systems with verification requests for complex DID documents. Clear documentation about the expected verification costs and performance characteristics helps implementers make informed decisions about resource allocation for DID verification operations.

6.7 Witness Availability and Reliability

The witness-based architecture of did:cel creates an operational dependency on witness services being available and responsive when DID controllers need to update their DID documents. If witnesses become unavailable due to network outages, operational failures, or deliberate denial-of-service attacks, DID controllers might be unable to record new events in their cryptographic event logs, effectively preventing them from making necessary updates such as key rotations in response to security incidents. This availability dependency could be exploited by attackers who compromise a DID controller's keys and then launch denial-of-service attacks against witness services to prevent the legitimate controller from performing emergency key rotations.

DID controllers are encouraged to select multiple geographically and operationally distributed witnesses to reduce the risk of correlated failures. Systems can be designed to tolerate some witness unavailability by requiring only a subset of witnesses to attest to an event, though this reduces the security assurance provided by witness attestations. Implementing witness selection policies that automatically failover to alternative witnesses when primary witnesses are unavailable can maintain operational continuity during outages. For critical operations, DID controllers might pre-establish relationships with backup witness services that can be used if primary witnesses fail. Witness services are encouraged to implement high-availability architectures with redundancy and failover capabilities to minimize downtime. Clear service level agreements and monitoring of witness availability helps DID controllers make informed decisions about which witnesses to rely on for their security requirements.

6.8 Cryptographic Algorithm Aging

The did:cel method uses modern cryptographic signing and hashing algorithms. While these cryptographic algorithms are currently considered secure, all cryptographic algorithms have a finite lifetime and eventually become vulnerable to attacks as computational capabilities advance or new cryptographic breakthroughs occur. DIDs created today might need to remain valid and verifiable for many years or decades, potentially outliving the security guarantees of the cryptographic algorithms they employ. As algorithms age, signatures and hashes created using those algorithms provide diminishing security. The immutable nature of the cryptographic event log means that while historical events cannot be re-signed with stronger algorithms, the historical chain of events can be signed with stronger algorithms (such as post-quantum signatures) under certain conditions (such as the security of SHA3-256 remaining uncompromised even if ECDSA becomes compromised).

DID controllers planning for long-term use of their DIDs are encouraged to monitor cryptographic algorithm recommendations and plan for upgrading algorithms or eventually migrating to DIDs using stronger algorithms before current algorithms are compromised. Implementing cryptographic layering by including multiple verification methods using different cryptographic algorithms, such as pre-quantum and post-quantum cryptographic algorithms, can provide continued security even if one algorithm is compromised, following the guidance in the Verifiable Credential Data Integrity 1.0 specification. Systems that verify DIDs can maintain policies about which cryptographic algorithms are acceptable and reject DIDs using deprecated algorithms that no longer provide adequate security. For historical preservation, the witness attestations in the log provide evidence that events were considered valid at the time they were created, even if the underlying cryptographic algorithms later become compromised. Clear documentation about the expected lifetime of cryptographic algorithms helps DID controllers plan appropriate migration timelines.

6.9 Timestamp Manipulation

Witness data integrity proofs include timestamp information indicating when the witness attested to an event. While timestamps can be useful for understanding the temporal sequence of events and detecting anomalies, they also introduce potential for manipulation if witnesses collude or if their clocks are inaccurate or maliciously adjusted. An attacker who compromises multiple witnesses might create backdated attestations to make fraudulent events appear to have occurred earlier than they actually did, or forward-date attestations to hide the timing of malicious activities. Relying on timestamps for security-critical decisions can be problematic given the difficulty of ensuring accurate, tamper-proof time sources across distributed witness services.

Implementations are encouraged to use timestamps as informational indicators rather than security-critical values, and to corroborate timing information from multiple independent sources, such as the cryptographic event log storage services, before relying on it. When witnesses include timestamps in their proofs, using multiple witnesses with independent time sources can help detect significant clock discrepancies or manipulation attempts. Systems that detect large discrepancies in witness timestamps for the same event can flag those events for additional scrutiny. The hashlinked structure of the event log provides a partial ordering guarantee—events must have occurred in the order they appear in the chain—which are more reliable than timestamp values for determining relative event ordering. Clear documentation about the limitations of timestamp information helps prevent over-reliance on timing data that might be manipulated.

6.10 Storage and Retrieval Security

Cryptographic event logs are stored by storage services listed in the DID Document and made available during DID resolution, but the specification does not mandate a particular storage mechanism. Depending on the chosen storage approach—whether distributed ledgers, decentralized storage systems, centralized repositories, or peer-to-peer networks—different security considerations apply. If log storage is compromised, attackers might delete events to hide malicious modifications, modify historical events to change the DID document history, or deny access to legitimate log data preventing DID resolution. The integrity and availability of the storage system directly impacts the security and usability of the DID.

DID controllers are encouraged to store their cryptographic event logs with multiple independent storage services to protect against data loss and ensure availability even if one storage location fails or is compromised. The hashlinked structure and witness proofs in the log provide integrity protection, meaning that modifications to stored log data can be detected during verification, but this does not prevent deletion or denial of access. Using storage systems with built-in redundancy, access controls, and audit logging can help protect log data from unauthorized modification or deletion. For public DIDs, publishing logs to multiple publicly accessible storage services increases resilience and makes censorship more difficult. Implementations that retrieve logs are encouraged to verify the complete integrity of the log using the hashlinking and proofs, rather than trusting that stored data is authentic. Backup strategies that maintain copies of logs in geographically and operationally diverse locations can ensure long-term preservation and availability.

6.11 Proof Validation

Each operation in the cryptographic event log contains a data integrity proof that cryptographically binds the operation to the DID document through a signature created with a verification method contained in the document. Witnesses proofs are also attached to each event in the cryptographic event log. Proper validation of these proofs is critical for security—if implementations skip proof verification or perform it incorrectly, they might accept fraudulent DID documents that were not actually created by the legitimate DID controller. The process of data integrity proof verification, which involves JSON processing, canonicalization, and signature verification, creates opportunities for implementation errors that could compromise security.

Implementations are strongly encouraged to use well-tested, standardized libraries for data integrity proof verification rather than implementing verification logic from scratch, as cryptographic implementations are prone to subtle errors that can completely compromise security. Following the verification algorithms specified in the Verifiable Credential Data Integrity 1.0 specification precisely, without shortcuts or optimizations that might skip critical validation steps, is important for maintaining security. Verification processes are encouraged to validate all aspects of the proof including the signature value, the proof purpose, the verification method reference, and any additional proof metadata. Regular testing with both valid and intentionally malformed proofs can help ensure that implementations correctly reject invalid proofs. Implementers are advised to review the security considerations in the Verifiable Credential Data Integrity 1.0 specification for additional guidance on proof verification.

6.12 Previous Event Hash Verification

The integrity of the cryptographic event log depends on each event containing a correct hash of the previous event in the previousEventHash property, creating an unbroken chain from the creation event to the most recent event. If implementations fail to properly verify that each previousEventHash hash matches the actual hash of the preceding event, or if they skip hash verification entirely, attackers could insert fraudulent events, remove events from the middle of the chain, or create alternate histories without detection. This hashlinking is fundamental to the security model—without rigorous verification, the log provides no integrity guarantees.

Implementations that verify cryptographic event logs are advised to compute the hash of each event using the same canonicalization and hashing algorithms specified in the creation and update algorithms, and verify that the computed hash matches the previousEventHash value in the following event. Verification processes are encouraged to validate the complete chain from the creation event forward without skipping any events, as gaps in verification could hide inserted or modified events. The creation event, which has no previous event, represents a trust anchor and its authenticity can be verified through witness attestations and the data integrity proof on the operation. For performance reasons, implementations might cache verification results for earlier portions of the chain, but care is needed to ensure cached results are not reused when the log has been modified. Clear error handling and reporting when hash verification fails helps diagnose attacks or data corruption issues.

6.13 Witness Proof Threshold Requirements

The did:cel specification includes witness attestations for events but does not mandate how many witness proofs are required for an event to be considered valid or trustworthy. Different applications and trust models might require different numbers of witnesses—some might accept events with a single witness attestation, while others might require multiple witnesses. If the threshold is set too low, attackers who compromise a small number of witnesses might be able to gain a denial-of-service advantage. If set too high, legitimate operations might be blocked by witness unavailability or disagreement, creating denial-of-service conditions.

Implementations are encouraged to establish clear policies about witness proof requirements that balance security needs against operational flexibility. For high-security applications, requiring attestations from a majority or supermajority of a defined witness set provides protection against individual witness compromises. Lower-security applications might accept events with fewer attestations but implement monitoring to detect suspicious patterns. Policies can be adaptive, such as requiring more witnesses for security-critical operations like key rotations while accepting fewer witnesses for routine updates. When witnesses seem to be acting in a way that would lead to a denial of service, implementations are encouraged to investigate the discrepancy. Clear documentation about witness requirements helps DID controllers understand what level of witness attestation they need to achieve for their operations to be accepted by verifiers. Witness selection strategies that include witnesses with diverse operational and governance models can provide more robust validation than witnesses operated by related entities.

6.14 Unauthorized DID Modifications

The security of DID document modifications relies on the DID controller maintaining exclusive control over the private keys corresponding to verification methods in the DID document. If an attacker gains access to these private keys through theft, social engineering, malware, or cryptographic compromise, they can create fraudulent updates to the DID document that appear legitimate because they carry valid data integrity proofs. Such unauthorized modifications might add attacker-controlled verification methods, remove legitimate verification methods, change service endpoints, or modify other DID document properties, all while appearing to be authorized changes in the cryptographic event log.

DID controllers are strongly encouraged to implement rigorous key management practices including secure generation, storage, and access control for private keys. Using hardware security modules, secure enclaves, or other tamper-resistant storage for keys that control critical DIDs can significantly reduce the risk of key theft. Regular security audits, monitoring for unexpected DID document changes, and maintaining offline backups of key material can help detect and recover from compromises. Implementing the principle of least privilege by using different verification methods for different purposes, with only minimal keys having authority to modify the DID document, can limit the impact of key compromises. When unauthorized modifications are detected, rapid key rotation following the guidance in the key rotation section can help regain control and prevent further unauthorized changes.

6.15 Cryptosuite Downgrade Attacks

As cryptographic algorithms age and newer, stronger algorithms become available, DID documents might contain verification methods using different cryptographic suites with varying security strengths. An attacker might attempt to force systems to use weaker cryptographic algorithms by by exploiting verification implementations that default to weaker algorithms when multiple options are available. If successful, such downgrade attacks reduce the effective security to that of the weakest algorithm, potentially enabling signature forgeries or other cryptographic breaks that would not be possible against stronger algorithms.

Implementations are encouraged to maintain policies about which cryptographic algorithms are acceptable and to reject cryptographic event logs or proofs using algorithms that no longer provide adequate security. When DID documents contain multiple verification methods using different algorithms, verification processes are advised to require proofs using the strongest available algorithm rather than accepting weaker proofs. DID controllers are encouraged to remove deprecated verification methods using obsolete algorithms from their DID documents once stronger methods are in place, rather than maintaining weak methods for backward compatibility. Clear documentation about supported cryptographic algorithms and their expected security lifetimes helps both DID controllers and verifiers make informed decisions about algorithm selection. Following the cryptographic agility guidance in the Verifiable Credential Data Integrity 1.0 specification enables smooth transitions to newer algorithms without compromising security during migration periods.

A. Acknowledgements

This section is non-normative.

The Working Group would like to thank the following individuals for reviewing and providing feedback on the specification (in alphabetical order):

TBD...

B. Usage in Protocols

This section is non-normative.

This section provides some examples of how did:cel is used in various other protocols and data formats.

B.1 DID Authentication

This section is non-normative.

The example below demonstrates a Verifiable Presentation Request query requesting that the holder verify control of a did:cel DID:

Example 8: A DID Authentication request
{
  "query": [{
    "type": "DIDAuthentication",
    "acceptedMethods": [{"method": "cel"}]
  }],
  "challenge": "99612b24-63d9-11ea-b99f-4f66f3e4f81a",
  "domain": "domain.example"
}

When using did:cel, the holder responds with the following DID Authentication response:

Example 9: A DID Authentication response
{
  "@context": ["https://www.w3.org/ns/credentials/v2"],
  "type": "VerifiablePresentation",
  "holder": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1?storage=https%3A%2F%2Fstorage.example%2Fdids%2F",
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "ecdsa-rdfc-2019",
    "verificationMethod": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1?storage=https%3A%2F%2Fstorage.example%2Fdids%2F#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q",
    "challenge": "99612b24-63d9-11ea-b99f-4f66f3e4f81a",
    "domain": "domain.example",
    "created": "2025-12-07T14:58:42Z",
    "proofPurpose": "authentication",
    "proofValue": "z4vUFeRUpqaFLiSwkzN2Qiugw1yeA2DgJC6MTpqiwwzBkSNdaNMSYXAgLWC8UsJFb8dymbDQiBaQySuWGjMxBhGiZ"
  }
}

The DID Authentication response above instructs the verifier that the did:cel cryptographic event log for the provided DID can be found by fetching the following URL: https://storage.example/dids/did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1.cel.gz.

B.2 Verifiable Credentials

This section is non-normative.

The example below demonstrates the use of a did:cel DID within a verifiable credential:

Example 10: A verifiable credential using did:cel DIDs
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "type": [
    "VerifiableCredential",
    "ExampleDegreeCredential"
  ],
  "issuer": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1?storage=https%3A%2F%2Funiversity.example%2Fdids%2F",
  "validFrom": "2010-01-01T00:00:00Z",
  "credentialSubject": {
    "id": "did:cel:zW1aH98tbKKqFeohTz1poyeoHMrkJWDaT1WftFBG8WKa6fC?storage=https%3A%2F%2Fstorage.example%2Fdids%2F",
    "degree": {
      "type": "ExampleBachelorDegree",
      "name": "Bachelor of Science and Arts"
    }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "created": "2025-12-07T19:47:10Z",
    "verificationMethod": "did:cel:zW1poyeoHaT1WftFBG8WKa6fCaH98tbKKMrkJWDqFeohTz1?storage=https%3A%2F%2Funiversity.example%2Fdids%2F#zDnaeU8aVJn9pZjH7f249geMiz9UTRjfXUcc5pN4QsxVte57q",
    "cryptosuite": "ecdsa-rdfc-2019",
    "proofPurpose": "assertionMethod",
    "proofValue": "z3oB59kTTajyXKx3FYJGk9Xvb158rLG2Pq6FQSNaGL6J9ieA3ipXGot5zWME4TXisz1vpfTo8DFjLpBwe4afL1r27"
  }
}

C. References

C.1 Normative references

[CID]
Controlled Identifiers v1.0. Michael Jones; Manu Sporny. W3C. 15 May 2025. W3C Recommendation. URL: https://www.w3.org/TR/cid-1.0/
[DID]
Decentralized Identifiers (DIDs) v1.0. Manu Sporny; Amy Guy; Markus Sabadello; Drummond Reed. W3C. 19 July 2022. W3C Recommendation. URL: https://www.w3.org/TR/did-core/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8785]
JSON Canonicalization Scheme (JCS). A. Rundgren; B. Jordan; S. Erdtman. IETF. June 2020. Informational. URL: https://www.rfc-editor.org/rfc/rfc8785
[VC-DI-ECDSA]
Data Integrity ECDSA Cryptosuites v1.0. Manu Sporny; Dave Longley; Greg Bernstein. W3C. 15 May 2025. W3C Recommendation. URL: https://www.w3.org/TR/vc-di-ecdsa/

C.2 Informative references

[CEL]
Cryptographic Event Log v0.1. Manu Sporny; Dave Longley; Christine Lemmer-Webber. W3C Credentials Community Group. CG-DRAFT. URL: https://w3c-ccg.github.io/cel-spec/
[VC-DATA-INTEGRITY]
Verifiable Credential Data Integrity 1.0. Ivan Herman; Manu Sporny; Ted Thibodeau Jr; Dave Longley; Greg Bernstein. W3C. 15 May 2025. W3C Recommendation. URL: https://www.w3.org/TR/vc-data-integrity/