Did-core: Discoverability of `version-id`

Created on 28 Sep 2020  路  8Comments  路  Source: w3c/did-core

In section 3.2.1 DID Parameters the version-id query param is defined. This is a great way to refer to a specific version of a DID document, especially in content addressed systems (e.g. based on IPFS). However, right now it's impossible for someone that resolves a document to determine what the current version-id is.

This becomes a problem if I want to encrypt a message (e.g. using JWE) to a recipient and I want them to know which key it was encrypted to (if they have rotated the key previously). If I'm able to specify the version-id they wouldn't need to try to decrypt the JWE with all of their previous keys until they find the correct one.

Most helpful comment

I agree with @OR13 's example (version-id should be in the DID document metadata, not DID document).

Except the example should say dereference(...) instead of resolve() since an entire DID URL (not just a DID) is passed.

All 8 comments

@oed We have some additional considerations about versioning in the DID Resolution spec (section 10.3 Versioning). Keep in mind that this is method-specific.

I don't really understand your message encryption use case, but the idea that a DID document could contain its current version ID has certainly been discussed before!

I think such a property would be part of the DID document metadata, rather than the DID document itself.

Since this can raise a lot of additional questions (and we announced a feature freeze for the DID Core spec several weeks ago), I would propose to not add this feature to DID Core at this point, but we can specify it elsewhere (e.g. in DID Resolution) and then add it as an extension to the DID Spec Registries, what do you think?

Thanks @peacekeeper

A DID document MAY contain a version identifier that changes with each Update operation that is performed on a DID.

From 10.3 as you linked. If this is the case that this should be all good. Not sure I get exactly how the DID Resolution spec relates to the DID-core spec though.

I don't really understand your message encryption use case, but the idea that a DID document could contain its current version ID has certainly been discussed before!

  1. You have keyAgreement key A in your document
  2. I encrypt message m to you using A
  3. You update your document and now only have keyAgreement key B
  4. You receive m, now do you decrypt using A or B?

You have to test with both unless I'm able to specify version-id along with m.

I don't know what the best path is here. I mainly just need a way to determine version-id in a non-custom way. Adding it as a property to the DID Doc seems like a simple solution, but idk what additional questions that could raise?

@oed your example lacks key identifiers.

lets say A has id = did:example:123#sha-256(JWK(A))
lets say B has id = did:example:123#sha-256(JWK(B))

JWE has kid === verificationMethod.id

No need for version-id.

Now lets say you decided to id your keys (poorly).

lets say A has id = did:example:123#primary
lets say B has id = did:example:123#primary

now you need version-id.... but only because you choose to reuse an identifier... and IMO, you should not have.

you can still get back to scenario one by doing the following:

lets say A produced JWE with kid = did:example:123?version-id=0#primary
lets say B produced JWE with kid = did:example:123?version-id=1#primary

but, imo its less ideal, more complicated and more error prone... key identifiers should be deterministic functions of key material...if they are not, kid identifiers should use version-id....

You may also want to review: https://w3c.github.io/did-core/#dfn-verificationmethod

In the case where a verification method is a public key, the value of the id property MAY be structured as a compound key. This is especially useful for integrating with existing key management systems and key formats such as JWK [RFC7517]. It is RECOMMENDED that JWK kid values are set to the public key fingerprint [RFC7638]. It is RECOMMENDED that verification methods that use JWKs to represent their public keys utilize the value of kid as their fragment identifier. See the first key in example of various public keys for an example of a public key with a compound key identifier.

If you don't like using compound keys like did:example:123#fingerprint you can construct JSON that looks like this instead.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    {
      "@base": "did:key:z6LSsNuQtFrFgNwWLuG2r443zNyGh5PBfpKuGvZXXFkK2gre"
    }
  ],
  "id": "did:key:z6LSsNuQtFrFgNwWLuG2r443zNyGh5PBfpKuGvZXXFkK2gre",
  "verificationMethod": [
    {
      "id": "#z6LSsNuQtFrFgNwWLuG2r443zNyGh5PBfpKuGvZXXFkK2gre",
      "type": "JsonWebKey2020",
      "controller": "did:key:z6LSsNuQtFrFgNwWLuG2r443zNyGh5PBfpKuGvZXXFkK2gre",
      "publicKeyJwk": {
        "kty": "OKP",
        "crv": "X25519",
        "x": "6U5OR5CP8f7PNorgLz1xylKKxsoPKPA9MbSMSJt-72M"
      }
    }
  ],
  "keyAgreement": [
    "#z6LSsNuQtFrFgNwWLuG2r443zNyGh5PBfpKuGvZXXFkK2gre"
  ]
}

Yep, kid will need to use version-id when key identifiers are not based on a hash as they could be in some cases, but not all. Hence the need to have a way to get the version-id from the DID document. It's also unclear if any given key has a deterministic id or not.

@oed well, some did methods don't let users pick id values... those methods are IMO more secure.

imo version-id does not belong in the did document, it belongs in metadata that is returned.... the did document is about the did subject... the version is about the "did document"... see https://en.wikipedia.org/wiki/HTTPRange-14

The WG has not done a great job of sorting this issue out, but it appears that there are no properties of the did document that are "about the did document".... they are all properties of the "did subject"... which is why i suggest version should be returned in resolver metadata.

So to answer your question as concretly as I can:

resolve ('did:example:123?version-id=0#primary', { accept: 'application/did+json'}  ) =>

didDocument (as it was at version 0, didDocument.id === 'did:example:123' (query strings are not reflected) )
didDocumentMetaData (version: 0)
didResolutionMetaData (..)

At least thats my interpretation of how did resolution is supposed to work today.

@OR13 yeah seems something like that could work! I also like the method you're suggesting above with did:key, where the id is the multicodec key itself. Might adopt that for 3ID but using multiple multicodec keys.

I think I also got things a little confused, because with JWS the version-id will definitely need to be specified in the kid in order to know if the signature was authored by before the key got revoked (removed from the did doc). That's however besides the point since the signing party is very likely to know it's version-id.

I agree with @OR13 's example (version-id should be in the DID document metadata, not DID document).

Except the example should say dereference(...) instead of resolve() since an entire DID URL (not just a DID) is passed.

Closing this as I'm satisfied with the given answers.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

selfissued picture selfissued  路  3Comments

awoie picture awoie  路  8Comments

dmitrizagidulin picture dmitrizagidulin  路  8Comments

shigeya picture shigeya  路  6Comments

dmitrizagidulin picture dmitrizagidulin  路  6Comments