didwebvh
didwebvh copied to clipboard
Inconsistency in how versionId is generated
At the start of the spec it states:
The value of versionId MUST be a string consisting of the DID version number (starting at 1 and incrementing by one per DID version), a literal dash -, and the entryHash, a hash calculated across the log entry content. The input to the hash is chosen so as to link each entry to its predecessor in a ledger-like chain. The input to the hash is specified in the Entry Hash Generation and Verification section of this specification.
However, the example provided https://identity.foundation/didwebvh/v1.0/#entry-hash-generation-and-verification
{"versionId": "QmdmPkUdYzbr9txmx8gM2rsHPgr5L6m3gHjJGAf4vUFoGE", "versionTime": "2025-04-01T17:39:50Z", "parameters": {"witness": {"threshold": 2, "witnesses": [{"id": "did:key:z6Mkkc51mg2vpQzKWAbWQZupeGYhowaBjYkmvcKMTqteqHB4", "weight": 1}, {"id": "did:key:z6MkuDdJdKLCgwZuQuEi9xG6LVgJJ9Tebr74CXPYPSumqgJs", "weight": 1}, {"id": "did:key:z6MkoSWmQyp4fTk4ZQy4KUsss9dFX51XfEUzKKKj1J1JUsrF", "weight": 1}]}, "updateKeys": ["z6MkgzBDcBFV3sk4ypPE5YXMZHmS213A3HpYY2LmcVKV15jr"], "nextKeyHashes": ["QmZreDcjvWEpyRFznQeExWNCsvMLk5i59AcRJJuQC8UodJ"], "method": "did:webvh:0.5", "scid": "QmdmPkUdYzbr9txmx8gM2rsHPgr5L6m3gHjJGAf4vUFoGE"}, "state": {"@context": ["https://www.w3.org/ns/did/v1"], "id": "did:webvh:QmdmPkUdYzbr9txmx8gM2rsHPgr5L6m3gHjJGAf4vUFoGE:domain.example"}}
Shows versionId without a versionNumber prefix. And states
The following is an example of a preliminary log entry that is processed to produce an entry hash. As this is a first entry in a DID Log, the input versionId is the SCID of the DID.
Thanks for the note. The spec and the example are correct. What the example is showing is the input to the algorithm to calculate the entryhash for the DID Log Entry. Once the entryhash is calculated, the versionId is updated to the final form in the that is published in the DID Log entry -- <versionNumber>-<entryhash>. What the example is trying to show is that in the input to the algorithm for the first DID log entry, the value of versionId is the SCID, whereas for the rest of the DID log entries, the value is the versionId from the previous log entry. The calculation of the entryhash using the data from the prior entry (or SCID) is the "chain of blocks" concept that prevents an attacker from inserting DID log entries into the file without detection.
I'll take a look at that to see if the wording can be improved. Suggestions are welcome!!
Made a couple of edits to my previous note to clarify further -- that the spec and example are correct, and the "final form" means the form published as the DID Log Entry.
Ah okay, I see thanks. That makes sense. You are using that initial log entry to calculate the entryHash that then gets combined with the 1- to make the actual versionId
Yes. The wording "initial log entry" isn't quite right, and that's where it needs to be clear. The data for a DID Log Entry is successively revised through the following steps:
- input from the controller -- at least the DIDDoc, but could also include parameters and versionTime. A deployment would likely hide the parameters and versionTime from the business logic.
- input to the SCID calculation (first DID Log only) -- all of the fields in a DID Log Entry, with locations where the SCID will go holding the literal string
{SCID}. After generation, the data is updated to replace the literal string{SCID}with the calculated value. - input to the entryHash calculation, where
versionIdcontains data from the prior record -- either the SCID (first entry) or the version ID from the previous log entry. After generation, theversionIdis updated to the value for that DID Log Entry. - input to the Data Integrity proof generation. After generation, the DI proof is attached.
- That output is the final DID log Entry for publication.
Once you get it, I don't think it is that complicated, but its not easy to explain. I'll work on improving that.
We've got a Tutorial coming Real Soon Now that will make this clear.