Implementing a did:webvh
Resolver¶
This article summarizes the process that a did:webvh
resolver might use in processing a did:webvh
DID. The process covers both the DID Log File processing, as well as the processing of the DID Witness Proofs file (if applicable). This article is not a specification, and there is no requirement for a did:webvh
to follow this approach. It is provided to help those beginning a registrar/resolver implementation to navigate the specification (links into the specification are embedded in the algorithm) using the experience of those that have gone before. Updates to the algorithm are welcome (via Issues or PRs) from implementers wanting to make life easier for those who will follow.
This approach draws heavily from the did:webvh
Python implementation at DIF.
The verification passes below may be interleaved. In particular, the did:webvh
Python implementation collects log entry proofs and verifies them in a thread pool in the background while doing the primary verification. Witness log retrieval could be performed when the first witness
rule is seen in the DID Log.
Primary verification¶
- Fetch
did.jsonl
(Spec Ref). If not found, abort (error=notFound
). - For each entry in the history log:
- Perform preliminary checks:
- Check the entry is a valid JSON object with only the required properties. (Spec Ref)
- If it is the first entry, check the SCID derivation. (Spec Ref)
- Check the derivation of the entry hash and the sequencing of the version number. (Spec Ref)
- Verify the DIDDoc ID contains the SCID.
- Verify the type, value, and validity (allowed or not) of the parameters in the Log Entry. (Spec Ref)
- If preliminary checks fail:
- Set
INVALID=true
. - Move to the next verification phase.
- Set
- If a specific
versionId
is specified:- If the requested
versionId
equals the current entry'sversionId
: - If a specific
versionTime
is requested and is less than the entry'sversionTime
, abort (error=notFound
) - cannot reconcileversionId
andversionTime
. - Set
FOUND
to the current entry.
- If the requested
- If a specific
versionTime
is requested and a specificversionId
is not requested:- If the current entry's
versionTime
<=versionTime
: - Set
FOUND
to the current entry.
- If the current entry's
- If the current entry updates the parameters (Spec Ref)
updateKeys
,nextKeyHashes
, orwitness
:- Add the entry to
AUTH_ENTRIES
.
- Add the entry to
- If the
witness
parameter is non-null and thethreshold
is non-zero (Spec Ref):- Add
(versionNumber, witness)
toWITNESS_CHECKS
.
- Add
- If the previous value of
witness
was non-null and different fromwitness
:- Add
(versionNumber, prevWitness)
toWITNESS_CHECKS
.
- Add
- Add the current entry's
versionId
toCHECKED
. - Set
LATEST
to the current entry.
Proof verification¶
- If
LATEST
is not set, abort (error=invalidDid
) - no entries. - If
FOUND
is not set: - If
INVALID
, abort (error=invalidDid
) - latest version is needed, but verification short-circuited. - If a specific
versionId
orversionTime
is requested, abort (error=notFound
). - Set
FOUND=LATEST
. - Add
FOUND
toAUTH_ENTRIES
. - For each entry in
AUTH_ENTRIES
: - Check the associated entry proof(s). There must be at least one valid proof from an active update key. (Define active keys) (Spec Ref)
- If no valid proof is found, abort (
error=invalidDid
).
Witness verification¶
- If
WITNESS_CHECKS
is not set, then skip to next verification phase. - Fetch
did-witness.json
. If not found, abort (error=invalidDid
). (Spec Ref) - For each proof in the log:
- Check the
versionId
is set and is inCHECKED
, otherwise skip. - Check the validity of the proof, otherwise skip.
- Extract the version number from the
versionId
. - Add
(versionNumber, witnessId)
toWITNESS_VALID
. - For each
(versionNumber, rule)
inWITNESS_CHECKS
: - Check the witness rule against
WITNESS_VALID
. Each entry with a laterversionNumber
and one of the requested witness IDs may add to the weight. (Don't count multiple proofs from the same witness ID.) - If the threshold of a rule is met, remove it from
WITNESS_CHECKS
. (Spec Ref) - If any values remain in
WITNESS_CHECKS
, abort(error=invalidDid)
.
Final checks¶
- For the resolved entry
FOUND
, check that the ID of the document matches the resolution target. - If not, abort (
error=notFound
). - Add implicit services (
#files
/#whois
) to the DID document as needed. (Spec Ref Files), (Spec Ref Whois) - Perform dereferencing if necessary.
- If
INVALID
is set, add (TBD) to the resolution metadata. Adjust the internal TTL to the standard 'verification failure' TTL.
TODO: define caching behavior