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.
- Node.js (v18 or higher recommended)
- npm (comes with Node.js)
npm installThe 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/secretsTo start the interactive REPL:
./didcelYou will be prompted for an encryption password used to protect secret keys on
disk. Pass -p <password> to supply it non-interactively.
Pass one or more -c flags to execute commands before entering the interactive
loop:
./didcel -c "create" -c "witness" -c "save" -c "quit"Once in the REPL, you'll see a did:cel> prompt. The following commands are available:
Displays help information about available commands.
Usage:
did:cel> help
Description: Shows a list of all available commands with brief descriptions.
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)
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 purposesassertionMethod- For making assertionscapabilityDelegation- For delegating capabilitiescapabilityInvocation- For invoking capabilitieskeyAgreement- For key agreement protocolsservice- 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 curvebbs- 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.
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"
}
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.
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.
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.
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
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
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
Loads and validates a DID from a cryptographic event log file.
Usage:
did:cel> load <filename>
Parameters:
<filename>: Path to the.cel.gzfile 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.
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
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.
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> quitIf 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> quitThe 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
didcel- Main executable script and REPL implementationlib/config.js- Configuration loader (readsconfig.yaml, resolves~/paths)
- 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.
BSD-3-Clause
This is an experimental implementation of the did:cel DID method. Contributions and feedback are welcome.
- DID CEL Specification - Technical specification for the
did:celmethod - W3C Decentralized Identifiers (DIDs) v1.0 - Core DID specification
- Verifiable Credential Data Integrity - Data Integrity Proofs specification