Skip to content

digitalbazaar/did-cel-tools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DID CEL Tools

A command-line tool for creating and managing Decentralized Identifiers (DIDs) using the Cryptographic Event Log (CEL) method. This tool provides an interactive REPL (Read-Eval-Print Loop) for working with did:cel identifiers, which use a witness-based architecture to maintain a cryptographically verifiable history of DID document operations.

The did:cel method is a fully decentralized DID method that doesn't depend on blockchains, centralized registries, or any single point of control. Instead, it uses cryptographic event logs with independent witness attestations to create tamper-evident audit trails for DID operations.

Installation

Prerequisites

  • Node.js (v18 or higher recommended)
  • npm (comes with Node.js)

Install Dependencies

npm install

Configuration

The tool reads a YAML configuration file. By default it looks for ~/.config/didcel/config.yaml. Pass -g <path> to use a different file.

# URL(s) of witness services to contact during the witness command
witnesses:
  - https://red-witness.example/witnesses/v1/witness
  - https://green-witness.example/witnesses/v1/witness
  - https://blue-witness.example/witnesses/v1/witness

# directory where .cel.gz event log files are written by the save command
logs: ~/.config/didcel/logs

# directory where encrypted secret key files are written by the save command
secrets: ~/.config/didcel/secrets

Usage

Starting the REPL

To start the interactive REPL:

./didcel

You will be prompted for an encryption password used to protect secret keys on disk. Pass -p <password> to supply it non-interactively.

Non-Interactive (Batch) Mode

Pass one or more -c flags to execute commands before entering the interactive loop:

./didcel -c "create" -c "witness" -c "save" -c "quit"

REPL Interactive Mode

Once in the REPL, you'll see a did:cel> prompt. The following commands are available:

help

Displays help information about available commands.

Usage:

did:cel> help

Description: Shows a list of all available commands with brief descriptions.


create

Creates a new DID document with a heartbeat commitment.

Usage:

did:cel> create

Description: Generates a new did:cel DID document with a self-certifying identifier derived from the document's cryptographic hash, and initializes a Cryptographic Event Log (CEL) to track the DID's history. The DID identifier is generated by computing did:cel: + base58btc(SHA3-256(JCS(initial-DID-document-without-id))). No verification methods are added at creation time — use the add command afterwards to add keys for authentication, assertionMethod, and other relationships.

Output: Displays the created DID identifier (e.g., create successful: did:cel:zW1jPC3ViLfgPJX6KaPMhymin3LpATUgYTS7N58FLHtQ4HE)


add <property> <type>

Adds a new verification method or service to the current DID document.

Usage:

did:cel> add <property> <type>

Parameters:

  • <property>: The verification relationship to add to. Choices:

    • authentication - For authentication purposes
    • assertionMethod - For making assertions
    • capabilityDelegation - For delegating capabilities
    • capabilityInvocation - For invoking capabilities
    • keyAgreement - For key agreement protocols
    • service - For service endpoints
  • <type>: The type of verification method or service. Choices:

    • eddsa - EdDSA signature scheme (not yet implemented)
    • ecdsa - ECDSA signature scheme with P-256 curve
    • bbs - BBS+ signatures (not yet implemented)
    • FileService - File service endpoint (not yet implemented)

Description: Generates a new cryptographic key pair and adds it to the specified verification relationship in the DID document. Currently, only ECDSA verification methods are supported. The DID document is modified in-place but changes are not committed to the Cryptographic Event Log until you run the update command.

Example:

did:cel> add authentication ecdsa

Output: Confirmation message indicating the verification method was added.


ls [suffix]

Lists the contents of the DID document.

Usage:

did:cel> ls [suffix]

Parameters:

  • [suffix] (optional): The last several characters of an identifier to display details for.

Description:

  • Without arguments: Displays a summary of the DID document, showing the DID identifier and abbreviated listings of all verification methods and services.
  • With a suffix: Shows detailed JSON representation of the specific object whose identifier ends with the provided suffix.

Examples:

did:cel> ls
did:cel:zW1jPC3ViLfgPJX6KaPMhymin3LpATUgYTS7N58FLHtQ4HE
  assertionMethod: Multikey#zDn...T9UV
  authentication: MultikeyDid:...8j4K

did:cel> ls T9UV
{
  "id": "#zDnaei5odivPwAt8q8QFF1cKCtz6gMkVpb9PBacKBzUNcT9UV",
  "type": "Multikey",
  "controller": "did:cel:zW1jPC3ViLfgPJX6KaPMhymin3LpATUgYTS7N58FLHtQ4HE",
  "publicKeyMultibase": "zDnaei5odivPwAt8q8QFF1cKCtz6gMkVpb9PBacKBzUNcT9UV"
}

expire <suffix>

Sets an expiration timestamp on a verification method.

Usage:

did:cel> expire <suffix>

Parameters:

  • <suffix>: The last several characters of the verification method identifier to expire.

Description: Adds an expires property to the specified verification method with the current timestamp in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ). This marks the verification method as expired, though it remains in the DID document. Changes take effect immediately in the local DID document but are not committed to the Cryptographic Event Log until you run the update command.

Example:

did:cel> expire T9UV

Output: Confirmation message with the expiration timestamp.


remove <suffix>

Removes a verification method or service from the DID document.

Usage:

did:cel> remove <suffix>

Parameters:

  • <suffix>: The last several characters of the identifier to remove.

Description: Searches through all arrays in the DID document (verification relationships and services) and removes the object whose identifier ends with the specified suffix. The object is immediately removed from the local DID document, but the change is not committed to the Cryptographic Event Log until you run the update and witness commands.

Example:

did:cel> remove T9UV

Output: Confirmation message showing the removed object's full identifier.


update

Updates the cryptographic event log with the latest DID document changes.

Usage:

did:cel> update

Description: Creates a new signed update event containing the current DID document and appends it to the Cryptographic Event Log. The event includes a previousEventHash field — a base58btc-encoded SHA3-256 hash of the previous event — that hash-links it to the preceding entry, making the chain tamper-evident.

After running update, you should run the witness command to obtain independent attestations from witness services.

Note: This command does not display output but prepares the event log for witnessing.


heartbeat

Appends a heartbeat event to the cryptographic event log.

Usage:

did:cel> heartbeat

Description: Creates a signed heartbeat event and appends it to the Cryptographic Event Log. A heartbeat carries no DID document data — it simply proves the DID is still active. DIDs with a heartbeatFrequency field are considered automatically deactivated if no witnessed heartbeat (or other event) is recorded within the specified ISO 8601 duration (e.g., P3M = 3 months).

After running heartbeat, run the witness command to obtain witness attestations.

Output: heartbeat: generated


deactivate

Permanently deactivates the DID.

Usage:

did:cel> deactivate

Description: Creates a signed deactivate event and appends it to the Cryptographic Event Log. Deactivation is a terminal operation — no further events (create, update, heartbeat) may be appended after it. After running deactivate, run the witness command and then save to persist the final state.

Output: deactivation: complete


witness

Obtains cryptographic attestations from witness services for the latest event.

Usage:

did:cel> witness

Description: Sends a SHA3-256 digest of the most recent event in the Cryptographic Event Log to each configured witness service. Witnesses are blind — they never see the DID document, only the hash — and each returns a DataIntegrityProof (ecdsa-jcs-2019) that is attached to the log entry.

These witness attestations provide:

  • Temporal anchoring: Proof of when the event was witnessed
  • Independent validation: Third-party attestation of the event hash
  • Distributed trust: No single witness can compromise the system

The witness proofs are attached to the log entry in the Cryptographic Event Log, creating a fully attested and verifiable history of DID operations.

Output: witness: proofs complete


load <filename>

Loads and validates a DID from a cryptographic event log file.

Usage:

did:cel> load <filename>

Parameters:

  • <filename>: Path to the .cel.gz file to load.

Description: Reads a gzip-compressed CEL file, fully validates the event chain (DID self-certification, hash chain, operation proofs, and trusted witness proofs if configured), and restores the current DID document and session state. Also loads the corresponding encrypted secret keys from config.secrets so subsequent commands can sign new events.

Output: load: valid CEL with N event(s): did:cel:z... or one or more error: lines describing validation failures.


save [filename]

Saves the Cryptographic Event Log to a file.

Usage:

did:cel> save [filename]

Parameters:

  • [filename] (optional): An additional path to write the event log to.

Description: Writes the complete Cryptographic Event Log (CEL) to a gzip-compressed JSON file (<did-identifier>.cel.gz) in the logs directory from config. Also encrypts all secret keys with AES-256-GCM (key derived via scrypt) and saves them to the secrets directory. If filename is supplied, the CEL is also written to that path. The CEL file contains the entire history of DID operations and can later be loaded with the load command.

Example:

did:cel> save my-did.cel.gz
Wrote to /home/user/.config/didcel/logs/z1abc...xyz.cel.gz
Wrote secrets to /home/user/.config/didcel/secrets/z1abc...xyz.yaml

quit

Exits the REPL without saving.

Usage:

did:cel> quit

Description: Terminates the interactive session immediately. Any unsaved changes to the DID document or Cryptographic Event Log will be lost. Make sure to run the save command before quitting if you want to persist your work.

Typical Workflow

Here's a common workflow for creating and managing a DID:

# 1. Start the REPL
./didcel

# 2. Create a new DID
did:cel> create

# 3. Witness the create event
did:cel> witness

# 4. Add additional verification methods
did:cel> add authentication ecdsa

# 5. Record the changes as an update event
did:cel> update

# 6. Get witness attestations for the update
did:cel> witness

# 7. Save the complete event log and encrypted keys
did:cel> save

# 8. Exit
did:cel> quit

Periodic heartbeat

If your DID document has a heartbeatFrequency, you must record witnessed heartbeats within that interval to keep the DID active:

did:cel> load z1abc...xyz.cel.gz
did:cel> heartbeat
did:cel> witness
did:cel> save
did:cel> quit

Architecture

The DID CEL tools implement the did:cel DID method, which consists of:

  • Self-certifying identifiers: DID identifiers derived from did:cel: + base58btc(SHA3-256(JCS(initial-DID-document-without-id)))
  • Cryptographic Event Log (CEL): A hash-linked chain of events recording all DID operations, stored as gzip-compressed JSON
  • Blind witness attestations: Witness services receive only a SHA3-256 digest of each event and return DataIntegrityProofs, providing temporal anchoring and distributed trust without ever seeing DID document contents
  • Data Integrity Proofs: ecdsa-jcs-2019 cryptographic signatures on events (operation proofs) and on witness attestations (witness proofs)
  • Heartbeat keys: Each DID document stores SHA3-256 hashes of heartbeat did:key: URIs derived from a master secret via HKDF-SHA256; each signed event rotates the hash to the next derived key, preventing key reuse

File Structure

  • didcel - Main executable script and REPL implementation
  • lib/config.js - Configuration loader (reads config.yaml, resolves ~/ paths)

Security Considerations

  • Secret Keys: Secret keys are stored in memory during the session and encrypted to disk when you run save. Keys use AES-256-GCM with scrypt key derivation.
  • Blind Witnesses: Witness services never see the DID document — they only sign a SHA3-256 hash of the event. This prevents witnesses from learning private information about DID controllers.
  • File Storage: CEL files (.cel.gz) contain only public information (DID documents and proofs), not secret keys. Secret keys are stored separately in encrypted YAML files.
  • Heartbeat Keys: Heartbeat key hashes are stored in the DID document. Each signed event must include the next heartbeat key's hash, rotating the commitment forward and preventing key reuse or replay attacks.

License

BSD-3-Clause

Contributing

This is an experimental implementation of the did:cel DID method. Contributions and feedback are welcome.

Related Specifications

About

Tools for did:cel DID Method

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors