How did:webplus works
If you know did:web, you already know half of this: the DID-to-URL mapping, the hosting model, and the deployment story carry over. What’s new is that history becomes a first-class, verifiable object.
1. The microledger
A did:webplus DID corresponds to an ordered sequence of DID documents called its microledger. Each document is self-hashed, and each non-root document names its predecessor’s hash in a prevDIDDocumentSelfHash field. The chain terminates at the root document, and the DID itself embeds the root document’s selfHash as its final path component:
did:webplus:example.com:uHiBKHZUE3HHlYcyVIF-vPm0Xg71vqJla2L1OGXHMSK4NEA
Because the identifier commits to the root document, and every update commits to its predecessor, altering any part of the history is computationally infeasible. The DID string never changes across updates; the history grows behind it.
2. Update rules
Every DID document carries an updateRules field defining exactly which signatures authorize the next update. Rules compose: a single key; a hashed key, which commits to a recovery or pre-rotation key without revealing it; any and all combinators; and weighted thresholds via atLeast / of.
Rules are enforced by every verifier when validating the chain, not just by the server that hosts it. Setting updateRules to {} permanently deactivates the DID: a tombstone that no future key can reopen.
{
"updateRules": {
"atLeast": 2,
"of": [
{ "key": "u7QFCWKaWNQ5FsNShO8BlZwjHa5xkGleeETKwu-vjf1SZXg" },
{ "key": "u7QFNzTwiEH-gYlFQ_jb01lEFnWnyZPzq-rcehFEbF-rPFg" },
{ "weight": 2,
"hashedKey": "uHiCMmFumKCTx6yxWPtoRM_VZj4DvdcHs2KEBK941pr8SXQ" }
]
}
}
A 2-of-3 policy: any two device keys, or one offline recovery key (weight 2) whose public key stays hidden until used.
3. Resolution
The DID-to-URL mapping is nearly identical to did:web: drop the prefix, turn colons into slashes, percent-decode, and append /did-documents.jsonl. The result is the resolution URL, fetched over plain HTTPS:
did:webplus:example.com:uHiBKHZUE3HHlYcyVIF-vPm0Xg71vqJla2L1OGXHMSK4NEA -> https://example.com/uHiBKHZUE3HHlYcyVIF-vPm0Xg71vqJla2L1OGXHMSK4NEA/did-documents.jsonl
did-documents.jsonl is the whole microledger: one canonicalized (JCS) DID document per line. Three properties follow from this choice. Resolvers fetch increments, since a resolver that has versions 0 through 6 issues an HTTP range request and receives only the bytes after them. Static hosting works, since no query-string handling is needed, so a personal site or GitHub Pages can be a fully functioning Verifiable Data Registry. And history is addressable: ?versionId=3 or ?selfHash=uHiC... resolves any historical document, which is what makes verification of old signatures possible.
4. Three architectures, one method
did:webplus specifies three deployment levels that share one data model.
Basic: a DID controller, a VDR (any web host), and Full resolvers. Each Full resolver fetches, verifies, and archives every microledger it touches, and can resolve offline from its archive. Right-sized for one-to-one relationships and self-hosters.
Intermediate: adds a Verifiable Data Gateway. The VDG is a Full resolver run as a shared service: it witnesses, archives, and serves verified histories for many parties, and enables Thin resolvers that are as simple as did:web’s single HTTP GET. VDRs can push updates to the VDG so resolution runs in constant time.
Advanced: VDG clusters behind CDNs for hyper-scaled deployments. Verified DID documents are immutable and cache beautifully at the edge, which also absorbs denial-of-service pressure.
Start at Basic on a static site; move up only when your trust and scale requirements demand it.
5. Attacks & countermeasures
| Attack | What it looks like | What catches it |
|---|---|---|
| DID fork | A malicious controller, colluding with its VDR, serves two valid but different histories to two different verifying parties, for later signature repudiation. | Forked histories share a root but diverge in selfHash chains. Any two parties comparing notes detect it immediately; a shared VDG makes that comparison automatic and continuous. A detected fork MUST be treated as fraud and the DID considered invalid. |
| Deletion or alteration | Controller and VDR erase or rewrite part of a DID’s history to repudiate an old signature. | Full resolvers and VDGs hold independent, verified archives from the time of signing. The altered history fails hash-chain validation against any archived copy. |
| Registry compromise | The web host serving DID documents is breached. | The VDR is the origin, never the authority. Every document is validated against the data model and its predecessor’s update rules by every consumer; a compromised host cannot forge a valid update without the controller’s keys. |
The common thread: in did:web, the server is trusted. In did:webplus, the server is merely the distribution channel, and verification is everyone’s job, done automatically.
6. Signatures that pin history
When a did:webplus controller signs an artifact, the signature’s key identifier is fully qualified: it names the DID, the exact DID document version current at signing (selfHash and versionId), and the specific key:
did:webplus:example.com:uHiBKHZUE3HHlYcyVIF-vPm0Xg71vqJla2L1OGXHMSK4NEA?selfHash=uHiDjConlZgv4fMol7F_LNmw73KIXfTzcBG2kOHsWm8WTBg&versionId=1#0
This does two jobs at once. It is a limited form of witnessing: the signer commits to a particular DID history inside an artifact held by outside parties. And it makes verification fast: a verifier with the referenced document in its archive resolves it entirely offline. Years later, an auditor reconstructing a chain of custody resolves exactly the document that was current at signing time, with cryptographic certainty.