Unofficial Draft
Copyright and licensing terms are to be confirmed by the editors.
This specification defines a processing model for maintaining and verifying the history of an evolving data object using a Cryptographic Event Log. Every history has a self-certifying identifier derived from genesis. The model describes event continuity, authorization, state transitions, pre-rotation, and witnessing, with application-specific behavior defined by profiles.
This document is a draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organization.
This is version 0.1 of an exploratory editor's draft. It is a proposal for discussion, not an adopted DIF or W3C specification. The draft is maintained in the VHCEL repository and published on GitHub Pages. Editors, standards publication venue, and licensing are to be confirmed.
The draft specifies a history processing model. A concrete CEL binding and application profile are still required for interoperable implementations. Examples are conceptual; abbreviated digests and empty proof arrays are not test vectors. Editorial issues identify choices that remain open.
This specification defines Verifiable History (VH), a mechanism for maintaining and verifying the history of an evolving data object using a Cryptographic Event Log (CEL).
A Verifiable History consists of an ordered sequence of cryptographically linked events. Each event describes an operation against an application-defined state. Each non-genesis event is cryptographically bound to its predecessor.
Verifiers can independently establish that:
the history begins with the expected genesis event, when an expected identity is supplied;
the supplied events satisfy their cryptographic commitments and predecessor links;
each state transition was authorized according to the applicable authorization policy; and
the current state can be deterministically derived from the history.
Verification alone does not establish that the supplied history is the latest available history or the only valid branch. See 6.3 History Truncation and 4.6 Forks.
This specification defines the processing model necessary to construct and verify a Verifiable History while delegating application-specific state semantics to application specifications.
Verifiable History is independent of any particular identifier system, transport, storage system, or application data model.
DID methods, digital assets, social objects, configuration systems, registries, and other applications MAY define application specifications based on this specification.
VHCEL builds on the history mechanisms of [DID-WEBVH] and the separation of events, operations, and external references in [CEL]. This draft proposes an alignment; it does not establish wire compatibility with either specification.
Many systems publish data whose value changes over time.
Examples include:
DID Documents;
public keys and authorization policies;
digital assets;
social objects;
configuration documents;
registries; and
other persistent digital objects.
Publishing only the latest representation of such an object does not provide cryptographic evidence of how the object reached that state.
A Verifiable History provides that evidence.
Conceptually:
Genesis Event
|
v
Event 1
|
v
Event 2
|
v
Event 3
|
v
Current State
Each non-genesis event cryptographically commits to its predecessor. Application-defined authorization rules determine whether an operation represented by an event is permitted.
The resulting history can be verified independently of the system from which the history was retrieved.
This distinction is fundamental:
Discovery determines where a history can be found. Verifiable History determines whether that history is authentic.
A Verifiable History therefore does not require a blockchain, distributed ledger, trusted database, or particular network protocol.
This section is non-normative.
This specification has the following design goals.
A Verifiable History MUST NOT depend upon a particular transport or storage system for its integrity.
A conforming history MAY be distributed using HTTPS, local files, content addressed storage, peer-to-peer networks, databases, or other mechanisms.
The core history format MUST NOT depend upon the semantics of the object whose history is being represented.
Applications define how operations modify application state.
A verifier possessing a history and the required cryptographic material MUST be able to verify that history without trusting the system from which the history was retrieved.
Two conforming processors given the same valid history and application specification MUST derive the same current state.
The format SHOULD permit cryptographic algorithms to evolve without requiring a new history data model.
An ordered sequence of cryptographically linked events describing the evolution of an object.
The representation containing the events that comprise a Verifiable History.
A record carrying an operation. Each non-genesis event also carries a reference to the cryptographic digest of its immediate predecessor.
The first event in a Verifiable History.
A cryptographic digest identifying an event.
The event immediately preceding another event.
Application-defined information describing a proposed state transition.
The application-defined representation resulting from processing zero or more operations.
An entity authorized according to an application's authorization policy to create an event.
An entity that produces cryptographic evidence acknowledging an event.
The required Self-Certifying History Identifier (SCID), derived from genesis and stable for the lifetime of a Verifiable History.
A specification defining how a particular application interprets and processes events.
For a concise prototype checklist, see the separate Short Implementation Guide.
Verifiable History separates four concerns:
+--------------------------------+ | Application State | +--------------------------------+ | Application Operations | +--------------------------------+ | Verifiable History | +--------------------------------+ | Cryptographic Event Log | +--------------------------------+
The Cryptographic Event Log establishes event integrity and ordering.
Verifiable History establishes continuity and history verification.
Application specifications establish authorization and state transition semantics.
Transport and discovery are outside the scope of this specification.
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 MAY, MUST, MUST NOT, OPTIONAL, REQUIRED, SHOULD, and SHOULD NOT 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.
A conforming history MUST have a genesis-derived SCID and every non-genesis
event MUST reference its immediate predecessor through previousEvent.
SCIDs are a core requirement, not an optional application capability.
Conformance is relative to a named binding and application profile. This draft alone does not define a complete interoperable wire protocol.
A conforming Verifiable History processor:
MUST implement the history verification algorithm defined by this specification;
MUST implement at least one compatible Cryptographic Event Log representation;
MUST reject histories that fail required cryptographic or application verification;
MUST NOT silently resolve forks unless permitted by the applicable application specification; and
MUST expose sufficient verification results for callers to distinguish a successfully verified history from an unverified representation.
A conforming application specification MUST satisfy the requirements in 5. Application Specifications.
For the design choices carried forward from related log formats, see 8.1 From did:webvh and 8.2 From CEL.
The data model describes the events, operations, and policies that comprise a verifiable history. Concrete property names and encodings are selected by a CEL binding.
A history contains one or more events. The following table summarizes the abstract event properties.
| Property | Description |
|---|---|
operation | REQUIRED. Describes the application-defined state transition. See 2.3 Operations and State. |
previousEvent | REQUIRED for non-genesis events; absent at genesis. References the cryptographic digest of the immediately preceding event. See 4.2 Event Chaining. |
scid | REQUIRED in genesis. Identifies the entire history and is immutable. Subsequent events are bound to it through the chain. See 2.4 Self-Certifying History Identifiers. |
time | OPTIONAL. An asserted event timestamp. Its interpretation is defined by the application. |
| Authorization proofs | Required when the application policy requires authorization. Placement and proof coverage are defined by the CEL binding. |
| External references | OPTIONAL. Cryptographic commitments to data held outside the event. See 2.2 External References. |
| Application properties | OPTIONAL. Additional information defined by the application specification. |
{
"previousEvent": "<previous-event-digest>",
"time": "2026-09-12T07:00:00Z",
"operation": {
"type": "update",
"data": {}
},
"proof": []
}
The event's identifier is computed from its protected content; it need not
be stored in the event. The previousEvent value is part of that
content. The history's SCID is established by genesis and is not repeated in
this update sketch. Exact placement and encoding MUST be specified by the
VHCEL binding; the examples illustrate the selected model, not a finalized
wire format.
Select a concrete CEL version and define
its mapping to this model, including event envelopes, controller proofs,
witness proofs, mandatory SCIDs, predecessor references, and chunk boundaries.
[CEL] is the alignment target; this model retains its explicit
previousEvent linkage, but compatibility has not yet been demonstrated.
An event MAY cryptographically commit to data that is not embedded directly in the event.
Conceptually:
{
"previousEvent": "<previous-event-digest>",
"operation": {
"type": "update",
"dataReference": {
"digestMultibase": "uEi..."
}
}
}
The referenced data MAY be available from one or more locations.
The integrity of externally referenced data MUST be established from its cryptographic digest and MUST NOT depend solely upon the location from which it was retrieved.
This permits:
+--> HTTPS
|
Event -> Hash +--> IPFS
|
+--> P2P
|
+--> local storage
without changing the cryptographic identity of the referenced data.
If external data is required to validate or apply an operation, a processor MUST retrieve and verify it before accepting the resulting state. If it is unavailable, the processor MUST report incomplete verification or failure; it MUST NOT report the dependent state as verified. Optional data MAY remain unretrieved only when the application profile permits this, and the result MUST identify that data as unverified.
An operation describes an application-defined state transition.
Common operation types MAY include:
create update deactivate
Applications MAY define additional operation types.
The core Verifiable History processor MUST NOT assign semantics to application operations beyond those required by this specification.
An application specification MUST define:
valid operation types;
operation syntax;
the initial state construction algorithm;
the state transition algorithm; and
conditions under which an operation MUST be rejected.
Given:
S(n) = application state after event n O(n) = operation contained in event n
state processing is conceptually:
S(0) = CREATE(O(0)) S(n) = APPLY(S(n-1), O(n))
Every Verifiable History MUST have a Self-Certifying History Identifier (SCID) derived from its genesis commitment. Genesis MUST carry this value. The SCID identifies the history as a whole; an event identifier identifies a particular event within that history.
The SCID MUST remain unchanged throughout the history, including when its storage or discovery location changes. A successor MUST NOT establish a different SCID for the same history. The chain binds subsequent events to the genesis SCID; it does not require every event to repeat the value.
SCID derivation and event chaining are separate procedures. The SCID commits
to genesis. Each successor's previousEvent commits to the digest of
the completed preceding event. A stored current-event identifier and an
identifier-substitution procedure are not required.
SCID = DERIVE_SCID(genesisTemplate) E[0].scid = SCID E[1].previousEvent = EVENT_DIGEST(E[0]) E[2].previousEvent = EVENT_DIGEST(E[1])
The stable SCID and the digest of the completed genesis event serve different roles and are not assumed to be equal. The functions above describe the processing relationship, not concrete cryptographic algorithms.
{
"scid": "<self-certifying-history-id>",
"operation": {
"type": "create",
"data": { "name": "Example object" }
},
"proof": [{ "proofValue": "<controller-proof>" }]
}
A processor verifying from genesis MUST recompute the SCID and compare it with the value carried by genesis. It MUST reject a missing or mismatched SCID. If the caller supplies an expected SCID, the processor MUST also compare against that value. Internal consistency alone does not establish that a supplied history is the history the caller intended. See 6.15 Genesis and Whole-History Substitution for concrete attacks this expected-identity check addresses and its limits.
SCIDs are mandatory. Finalize the common genesis
commitment procedure, including coverage of initial state, authorization
material, and bootstrap policies; domain separation; canonicalization; encoding;
and deterministic treatment of the SCID field and
any embedded SCID references to avoid circular hash input. Placeholder processing
is one candidate for genesis derivation; it does not require replacing CEL's
previousEvent linkage. The exact derivation algorithm remains to be
specified by the binding.
SCID | +--> HTTPS location A | +--> HTTPS location B | +--> content-addressed network | +--> local archive
The same SCID can be verified regardless of where the history is retrieved.
Specify the exact committed key bytes, commitment lifecycle, activation policy, and recovery behavior. Decide when prior commitments authorize a revealing key to sign the transition.
A Verifiable History MAY support pre-rotation.
Pre-rotation allows a controller to commit to future authorization keys before those keys become active.
For example:
Event N
Active:
Key A
Commitment:
HASH(Key B)
|
v
Event N+1
Reveal:
Key B
A processor implementing pre-rotation MUST verify that newly activated cryptographic material satisfies a commitment established by an earlier valid event.
An application specification using pre-rotation MUST define:
the commitment algorithm;
when commitments are established;
when committed keys may be revealed;
whether multiple future keys may be committed;
how unused commitments are handled; and
how authorization recovery interacts with pre-rotation.
Pre-rotation enables compromise of an active authorization key to be distinguished from possession of previously committed future key material.
An event MAY be acknowledged by one or more witnesses.
A witness produces cryptographic evidence committing to an event identifier.
Conceptually:
+--> Witness A
|
Event ------ +--> Witness B
|
+--> Witness C
Witness proofs MUST NOT modify the identifier of the event they witness.
This permits witnesses to independently acknowledge the same immutable event.
Applications MAY define witness policies.
A witness policy MAY specify:
authorized witnesses;
threshold requirements;
witness rotation;
witness proof mechanisms;
timing requirements; and
whether witnessing is required or advisory.
For example:
Witnesses: A B C Threshold: 2
In this example, an event is considered sufficiently witnessed when valid proofs from at least two distinct authorized witnesses are present.
Witness policy changes MUST themselves occur through valid history operations.
The application specification MUST define which witness policy applies to a policy-changing event, including any requirement for the old set, the new set, or both. A processor MUST count distinct authorized witnesses, not the number of signatures, when checking a threshold. Witness evidence MUST NOT substitute for required controller authorization or operation validation.
Define a common witness profile: policy activation, rotation handover, receipt representation, threshold counting, and the meaning of a witness acknowledgment remain to be standardized.
Select the required exchange format, media type, version negotiation, and any log chunking rules. Listing possible formats below does not establish support or cross-format hash equivalence.
A Verifiable History MAY be serialized using any representation defined by a compatible Cryptographic Event Log specification.
Possible serializations include:
JSON;
JSON Lines;
CBOR; or
application-defined binary representations.
Serialization MUST NOT alter the cryptographic meaning of an event.
Applications requiring interoperable exchange MUST identify the serialization formats they support.
The following processing rules define event identification, history continuity, and verification. A selected CEL binding supplies the cryptographic procedures referenced by these algorithms.
Every event MUST have a deterministic cryptographic identifier calculated from its protected content. This identifier is the event's digest; it need not be stored as a property of the event.
EVENT_DIGEST(event) = ENCODE(HASH(CANONICALIZE(PROTECTED(event))))
The binding MUST define protected fields, canonicalization, byte encoding,
digest algorithms, and identifier encoding. The protected content MUST include
the SCID carried by genesis and the previousEvent reference carried
by each successor. Witness receipts MUST remain outside the event identity
calculation.
CEL-style predecessor references are the selected model. Finalize the event-digest procedure, controller-proof inclusion and coverage, unknown-property handling, and algorithm transitions. The conceptual formula is not yet an implementable hashing algorithm.
A verifier MUST reconstruct the hash input and calculate the identifier of every event, including the final supplied event. It MUST check successor references, required proofs, and any trusted event commitments against the protected content or calculated identifiers as specified by the binding. Calculating a digest alone does not authenticate an event.
Changing cryptographically protected content, including a predecessor reference, MUST change the calculated identifier except with negligible cryptographic probability.
Every non-genesis event MUST carry a previousEvent reference to
the cryptographic digest of its immediate predecessor.
E[2] --> E[1] --> E[0] (genesis carries the SCID)
previousEvent references
REQUIRE E[1].previousEvent == EVENT_DIGEST(E[0]) REQUIRE E[2].previousEvent == EVENT_DIGEST(E[1])
A verifier compares each previousEvent with the calculated digest
of the immediately preceding verified event. A missing reference or a mismatch
MUST cause verification to fail.
This detects a broken link within the supplied sequence. An attacker may still serve a valid prefix or an alternative authorized branch. The mandatory SCID binds the history to genesis; it does not by itself establish freshness or uniqueness of succession.
The first event in a Verifiable History is the genesis event. It MUST establish the history's SCID and sufficient information to initialize application state, and MUST satisfy the application's genesis requirements.
Genesis has no preceding event and MUST NOT carry a previousEvent
property. Its SCID MUST be verified according to the binding. The digest of the
completed genesis event is calculated for use by its successor and any applicable
proofs or trusted commitments.
A conforming processor MUST perform the following steps, or an equivalent
algorithm producing the same result. Inputs are an ordered sequence
E[0..n], the selected binding and application specification, and
any independently obtained expected SCID or trusted event commitment.
E[0]. Reconstruct the genesis commitment,
calculate the SCID, and compare it with the supplied value. Reject a mismatch.
If the caller supplies an expected SCID, also require it to match.E[0] satisfies the application's genesis rules.
Reject a previousEvent property at genesis. Calculate the digest
of the completed genesis event using the binding's event-digest procedure.S[0].E[i], where i > 0:
E[i].previousEvent to match the calculated digest
of the verified E[i-1]. Reject a missing reference or a mismatch.E[i], including its
previousEvent reference, under the binding and algorithm-transition
rules permitted by the previously verified state.S[i-1] permits a successor, including any
deactivation restrictions.S[i-1].
Verify applicable pre-rotation reveals against previously verified commitments.S[i] only after all required checks succeed.If any required check fails, the processor MUST reject the history as a successfully verified result. It MAY return diagnostics or a verified prefix, but MUST identify the failure and MUST NOT present that prefix as verification of the entire supplied history.
The returned state and metadata describe the scope of verification. They do not prescribe a programming-language API or a serialized result format. A boolean can answer a precisely scoped validation question, but does not by itself communicate the verified state or whether verification began at genesis or a trusted checkpoint.
A successful result describes the supplied sequence. A processor MUST NOT claim global uniqueness, absence of undisclosed forks, or freshness without additional evidence defined by the application.
Applications MAY permit verification from a trusted checkpoint rather than from genesis.
An authenticated checkpoint MUST bind:
the verified event identifier at which verification begins;
sufficient application state to continue processing subsequent events, including authorization policy, active commitments, witness policy, and deactivation status; and
the mandatory SCID and the applicable binding and application profile.
Checkpoint verification starts with the authenticated checkpoint state and continues with the successor checks in 4.4 History Verification. It does not rerun genesis processing on the first supplied successor. The checkpoint supplies the authenticated SCID and event identifier used to resume verification. Any expected SCID MUST match the checkpoint SCID; accepting a checkpoint does not independently verify the genesis derivation.
A processor MUST NOT represent a history verified only from a checkpoint as having been independently verified from genesis.
Two valid events MAY reference the same previous event:
+--> Event B
|
Event A -----+
|
+--> Event C
This condition constitutes a fork.
The core Verifiable History specification does not define a universal mechanism for choosing between competing branches.
An application specification MUST define its fork policy if forks are possible.
A fork policy MAY:
reject all forks;
select a branch according to application-defined consensus;
require witness evidence;
use external consensus;
preserve multiple branches.
Processors MUST NOT silently select a branch unless the applicable application specification defines how that selection is made.
An application MAY define an operation that permanently or temporarily prevents further state transitions.
A deactivation operation MUST be authorized according to the state immediately preceding the deactivation event.
An application specification MUST define whether events following deactivation are permitted.
An application specification conforming to this specification MUST define:
the application state model;
valid operations;
genesis processing consistent with the mandatory SCID derivation and event-identifier rules;
state transition processing;
authorization requirements, if applicable;
witness requirements, if applicable;
pre-rotation requirements, if applicable;
fork handling;
deactivation semantics, if applicable;
supported CEL serialization and cryptographic mechanisms; and
discovery mechanisms, if required.
Application specifications SHOULD reuse standardized profiles rather than defining equivalent mechanisms independently.
Discovery is explicitly separate from verification.
An application specification MAY define mechanisms for discovering a Verifiable History.
For example:
identifier
|
+--> HTTPS
+--> DNS
+--> DHT
+--> content-addressed network
+--> peer-to-peer protocol
A discovery mechanism MUST NOT be considered authoritative merely because it returned a history.
The returned history MUST still satisfy Verifiable History verification.
This section is non-normative.
A DID method MAY use Verifiable History to represent changes to a DID Document.
Such a profile could map:
| Verifiable History | DID profile |
|---|---|
| History | DID history |
| Genesis | DID creation |
| State | DID Document |
| Update operation | DID update |
| Authorization | DID controller authority |
| Deactivation | DID deactivation |
| SCID | DID self-certifying identifier |
The DID profile SHOULD NOT redefine event chaining, hashing, witnessing, or other mechanisms already defined by this specification or CEL profiles.
This section is non-normative.
This is a proposed decomposition of [DID-WEBVH]. Existing
did:webvh logs retain their original hashing and proof semantics.
Renaming fields or wrapping an entry in CEL does not preserve its signatures.
A future did:webvh profile could be expressed as a Verifiable History application combining:
Verifiable History
|
+-- CEL event representation
|
+-- Self-Certifying History Identifier
|
+-- Authorization
|
+-- Pre-Rotation
|
+-- Witness Policy
|
+-- DID state machine
|
+-- Web discovery
The did:webvh specification remains responsible for:
DID syntax;
DID-to-HTTPS transformation;
DID Document semantics;
web-based discovery;
DID portability;
DID URL behavior; and
DID-specific processing.
Generic history mechanics SHOULD be defined by this specification rather than independently by the DID method.
The integrity of a Verifiable History depends upon the collision and second-preimage resistance of the selected hash function.
Applications MUST define acceptable cryptographic algorithms.
Applications SHOULD provide a migration mechanism for histories that use algorithms that later become unsuitable.
Hash chaining detects modification of known history but does not inherently prove that a verifier has received the latest event.
Applications requiring freshness guarantees MUST define an additional mechanism.
Such mechanisms MAY include:
witness receipts;
trusted checkpoints;
independently published event identifiers;
transparency services;
periodic anchors;
application-defined heartbeat events; or
comparison with multiple independent sources.
A verifier MUST NOT infer that a valid terminal event is the most recent event solely because the supplied history is internally consistent.
An attacker controlling a discovery or storage mechanism may suppress valid events while continuing to serve an older valid prefix of the history.
Cryptographic event chaining alone does not detect this condition.
Applications concerned with suppression SHOULD permit verifiers to obtain history information from independent sources or require freshness evidence from witnesses or other external mechanisms.
A controller possessing valid authorization material may produce multiple events referencing the same predecessor.
Each branch may be individually cryptographically valid.
Hash chaining therefore provides tamper evidence but does not, by itself, provide consensus or uniqueness of succession.
Applications in which forks are security-significant MUST define a deterministic fork policy or an external mechanism capable of identifying the accepted branch.
Witnessing MAY reduce the ability to present inconsistent branches to different verifiers, but witness behavior and threshold assumptions MUST be considered part of the application's trust model.
A controller, witness, or publication service may present different valid histories to different parties.
Applications requiring detection of equivocation SHOULD support exchange or publication of event identifiers, witness receipts, checkpoints, or other cryptographic commitments between independent observers.
A witness system does not prevent equivocation unless the witness protocol or policy requires witnesses to detect or refuse conflicting histories.
Witnesses are not inherently trusted authorities.
A compromised witness may sign an event it should not have acknowledged.
A set of colluding witnesses may acknowledge conflicting or unreviewed events and satisfy a numerical threshold. This does not make a history that fails authorization, integrity, or state transition checks valid.
Applications MUST select witness thresholds and witness independence assumptions consistent with their threat model.
Where practical, witness sets SHOULD be chosen so that compromise of a single administrative, infrastructure, or cryptographic domain does not satisfy the required threshold.
A cryptographically valid event copied from one context into another may remain cryptographically valid unless the signed or hashed event data binds the event to the intended history and application context.
Applications MUST ensure that authorization proofs cannot be replayed across different histories or incompatible application contexts.
This binding SHOULD include sufficient context such as:
the History Identifier;
the previous event identifier;
the operation;
the applicable application or protocol identifier; and
any domain separation required by the cryptographic proof mechanism.
Cryptographic material used with multiple protocols may create ambiguity about what was authorized by a signature or proof.
Applications SHOULD use cryptographic domain separation and SHOULD avoid signing representations that could be interpreted as valid events under a different protocol.
Proof verification MUST include any purpose, domain, challenge, context, or equivalent fields required by the selected proof mechanism.
Event identifiers depend upon deterministic canonicalization.
Differences in parsing, Unicode handling, number representation, property ordering, omitted values, duplicate properties, or other serialization details can cause processors to calculate different event identifiers.
The applicable CEL serialization MUST define a single deterministic procedure for producing cryptographically protected bytes.
Processors MUST reject inputs that cannot be represented unambiguously by that procedure.
A processor MUST NOT select cryptographic algorithms solely from untrusted event content without validating that those algorithms are permitted by the applicable application specification or profile.
Algorithm identifiers MUST be interpreted unambiguously.
Processors MUST reject unsupported or prohibited algorithms rather than silently substituting another algorithm.
An attacker may attempt to transition a history from a strong cryptographic algorithm to a weaker permitted algorithm.
Applications supporting cryptographic agility MUST define who may authorize algorithm changes and which transitions are permitted.
A cryptographic algorithm transition SHOULD be authorized under the security requirements applicable before the transition takes effect.
The security of pre-rotation depends on the hiding and binding properties required by the selected commitment construction.
A commitment scheme MUST make it computationally infeasible to substitute different future authorization material for the material originally committed.
Applications SHOULD consider whether exposing a hash of predictable public key material permits unwanted correlation or precomputation.
Where this is a concern, the commitment construction MAY incorporate an application-defined nonce or other binding material.
Pre-rotation protects against some forms of compromise of an active key, but it may introduce security dependencies on future key material that must be protected before activation.
If committed future private key material is compromised before it becomes active, an attacker may be able to assume control when that material is later revealed.
Applications using pre-rotation SHOULD provide a mechanism to supersede unused commitments when the current authorization policy remains uncompromised.
An attacker controlling a host or discovery service can replace an entire history with a different, internally consistent history. The replacement can contain valid hash links and valid signatures made with the attacker's own keys. Those checks alone do not establish that it is the history the caller intended.
A securely obtained expected SCID binds the requested history to its genesis. The verifier reconstructs the genesis commitment, recomputes the SCID, and compares it with that expected value. This applies the genesis-binding principle used by [DID-WEBVH]; the following scenarios describe its application to VHCEL.
| Attack | Attempt | Why verification rejects it |
|---|---|---|
| Whole-history replacement | A compromised server publishes a fresh genesis with attacker-controlled keys and a newly signed history at the same URL. | The replacement genesis derives a different SCID. Copying the expected SCID into the replacement does not make its recomputed commitment match. |
| Genesis key or policy substitution | An attacker changes initial authorization keys, initial state, or bootstrap witness policy and recomputes the subsequent chain. | Changing content protected by the SCID commitment changes the derived identifier. This protection applies only to fields included in that commitment. |
| Substitution during discovery or relocation | A redirect, mirror, or new storage location returns another object's valid history under the expected name or locator. | The returned history fails the independently retained SCID check, even if its own proofs and chain are valid. |
These are forms of the same substitution attack. For example, a client that
has retained SCID A rejects a replacement whose genesis derives
B, whether that replacement advertises A or B.
The protection depends on the commitment's resistance to substitution, unambiguous
encoding, permitted algorithms, and correct verification. The binding must
specify which genesis fields are protected before these guarantees can be
claimed for an implementation.
Applications MUST define how a verifier obtains or establishes the expected identity of a history when identity matters. The expected SCID must come from a source the caller already trusts, such as an authenticated reference or a previously verified and retained identifier. Taking both the history and the expected SCID from the same untrusted response does not prevent replacement. Remembering a SCID on first use can detect later replacement but does not authenticate that first encounter.
A SCID does not establish the real-world identity or trustworthiness of its controller. It also does not detect an older valid prefix, select between valid forks sharing the same genesis, prevent misuse of a compromised active key, or ensure data availability. Those require the separate mechanisms discussed in 6.3 History Truncation, 6.5 Fork Attacks, 6.2 Authorization Key Compromise, and 6.17 External Data Availability.
An authenticated genesis digest or trusted checkpoint can also provide a cryptographic commitment for detecting replacement, subject to its verification rules and scope. VHCEL's SCID requirement makes a stable genesis identity common to all profiles; it does not introduce a protection that a CEL application could not provide.
Verification beginning from a checkpoint does not independently establish the validity of events preceding that checkpoint.
The security of partial-history verification therefore depends upon the authenticity and integrity of the checkpoint and the state associated with it.
Applications using checkpoints MUST define how checkpoints are authenticated.
Processors SHOULD expose whether verification began at genesis or from a checkpoint so that relying parties can distinguish the resulting assurance.
A cryptographic digest can establish the integrity of external data but cannot guarantee its availability.
An event may remain cryptographically valid even when referenced data can no longer be retrieved.
Applications requiring long-term availability SHOULD define replication, archival, or persistence requirements separately from cryptographic integrity.
Processors MUST verify externally retrieved data against the digest committed by the event before using that data.
A location, URL, filename, media type, or transport security property MUST NOT be treated as a substitute for digest verification when a cryptographic commitment is present.
A Verifiable History provides integrity and authenticity properties but does not provide confidentiality.
Event contents, cryptographic identifiers, witness information, timestamps, authorization keys, and external data references may reveal information even when application data is encrypted or stored externally.
Applications handling sensitive information SHOULD minimize information exposed in the log and SHOULD consider the correlation properties of stable identifiers and hashes.
Persistent identifiers, timestamps, update frequency, witness identities, authorization changes, and external data references may enable correlation across services or contexts.
Applications SHOULD consider whether every piece of metadata needs to be cryptographically committed or publicly distributed.
Transport privacy does not eliminate correlation that arises from the history itself.
Unless an application defines a trusted timestamping mechanism, an event timestamp represents an asserted time rather than independently proven time.
Cryptographic event ordering establishes causal succession within a history but does not, by itself, establish the real-world time at which an event occurred.
Applications MUST NOT use untrusted event timestamps as security-critical time evidence unless additional validation is defined.
A malicious or malformed history may contain a very large number of events, large operations, deeply nested data, expensive proof suites, excessive witness proofs, or external references intended to consume processor resources.
Implementations SHOULD impose appropriate limits on:
history size;
individual event size;
nesting depth;
number of proofs;
number of witnesses;
cryptographic work;
external retrievals; and
processing time.
A processor SHOULD fail safely when implementation limits are exceeded.
Implementations MUST treat serialized histories as untrusted input.
Parsers MUST reject duplicate object member names in JSON input used for cryptographic processing, before a parser can silently discard duplicate values.
Implementations SHOULD avoid parser differentials between the representation used for validation and the representation used for hashing or proof verification.
Cryptographic verification MUST operate on the exact semantic representation defined by the applicable CEL specification.
Permanent deactivation may prevent recovery after accidental or malicious deactivation.
Applications defining irreversible deactivation SHOULD make that property explicit and SHOULD consider whether stronger authorization, delay, witnessing, or other safeguards are appropriate.
Recovery mechanisms, when supported, MUST NOT permit an unauthorized party to bypass previously established authorization or pre-rotation requirements.
HTTPS, DNS, distributed storage, peer-to-peer systems, registries, and other discovery mechanisms may provide useful availability or origin information but are not substitutes for history verification.
A compromised discovery mechanism may redirect a verifier to an invalid, truncated, or unrelated history.
Processors MUST apply the same cryptographic verification regardless of the source from which a history was obtained.
The security guarantees of Verifiable History depend on correct implementation of canonicalization, hashing, proof verification, state transition processing, authorization, and application-specific policy.
Implementations SHOULD include test vectors covering:
valid histories;
modified events;
deleted events;
inserted events;
reordered events;
invalid predecessor references;
unauthorized transitions;
invalid pre-rotation reveals;
insufficient witness thresholds;
forks;
malformed canonical representations; and
cryptographic algorithm transitions.
Interoperability testing SHOULD include histories produced by independent implementations.
Verifiable Histories are often append-only and may be widely replicated.
Information written to a history may therefore be difficult or impossible to remove from all copies.
Applications SHOULD avoid including personal or confidential data directly in events unless permanent disclosure is acceptable.
Where practical, applications SHOULD commit to externally stored data rather than embedding sensitive data in the history itself.
The use of cryptographic hashes does not necessarily make personal data anonymous. Hashes of predictable or low-entropy data may permit dictionary attacks or correlation.
Applications SHOULD consider data minimization, selective disclosure, encrypted external storage, and appropriate commitment constructions when processing sensitive information.
This section is non-normative.
VHCEL combines the history-verification requirements of did:webvh
with CEL's application-independent event model. The following sections explain
which ideas the current draft carries forward and which it changes or leaves
outside the core. They describe design choices, not wire compatibility.
[DID-WEBVH] supplies the starting point for stable history identity and verification across changes in control.
A mandatory genesis-derived SCID. Every history has a stable identity that can be checked against its genesis, even when its storage location changes.
Authorization through history. Each successor is checked against previously established authorization, including commitments that can authorize newly revealed keys.
Pre-rotation and witnessing. The model carries forward commitments to future keys and witness-policy checks, with their concrete rules defined by profiles.
Verification of state transitions. Processing checks the history and its control changes before accepting the resulting state.
A DID-specific core. DID Documents, DID syntax, method parameters, and DID-to-HTTPS discovery belong in an application profile. The core can describe other evolving objects.
A complete DID Document in every entry. Events carry operations; the application decides how those operations produce state, including whether to use snapshots or incremental changes.
Stored current IDs and predecessor substitution. VHCEL
uses CEL's explicit previousEvent reference. It computes event
digests without requiring versionId or replacing a current-ID field
when hashing. Mandatory SCIDs do not require that construction.
[CEL] supplies the starting point for representing events independently of the application whose history they describe.
Explicit predecessor references. Each non-genesis event
uses previousEvent to reference the digest of the preceding event.
Operations and application profiles. The core describes history processing; applications define control and the meaning of state changes.
Embedded or externally referenced data. An operation can carry data directly or commit to data retrieved elsewhere.
Separate witness evidence. Witness receipts remain separate from controller authorization and outside the event-digest calculation.
Common history identity. VHCEL requires every application profile to use a genesis-derived SCID. CEL's DID example derives an identifier, but CEL does not make that a universal core requirement. An independently established SCID enables detection of the replacement attacks described in 6.15 Genesis and Whole-History Substitution.
Common history-processing requirements. VHCEL specifies how genesis, predecessor linkage, authorization, required data, and state transitions are checked together. CEL already requires application specifications to define control, state construction, and witness validity; VHCEL makes the shared verification sequence explicit while retaining those application semantics.
These additions describe a shared history-processing layer over the CEL model. They do not by themselves require a different event envelope. The result metadata in 4.4 History Verification describes what a verifier reports, rather than a difference in the log format.
Taking a design idea does not select every detail of its source format. VHCEL has not yet adopted an exact CEL envelope, serialization, digest encoding, or proof suite. SCID derivation and concrete policy bindings also remain open; these choices are deferred, not rejected. In particular, genesis may still need placeholder processing for embedded SCID references even though event chaining does not use current-ID substitution.
These sections describe the current processing model. A binding and test vectors are still needed to establish interoperability. Existing histories cannot be converted by renaming fields while assuming their original identifiers and proofs remain valid.
This specification has no IANA actions at this time.
This section is non-normative.
Future specifications or profiles may define:
the exact derivation and encoding of the required Self-Certifying History Identifier;
standardized authorization policies;
standardized pre-rotation commitments;
threshold witness profiles;
transparency and freshness mechanisms;
checkpoint formats;
compact binary representations;
selective disclosure mechanisms; and
application-specific profiles including DIDs and digital assets.
This section is non-normative.
Before claiming compatibility, map a real
did:webvh history into the selected CEL representation and perform
the reverse exercise. Compare protected bytes, identifiers, proof coverage,
SCID derivation, key transitions, and witness policy activation. Record which
properties are preserved and which would require a newly signed history.
The first interoperability milestone is a named binding, a minimal application profile, and independently verified test vectors covering genesis, update, rotation, witnessing, deactivation, forks, and malformed inputs.