w3c / did-core

W3C Decentralized Identifier Specification v1.0
https://www.w3.org/TR/did-core/
Other
395 stars 93 forks source link

Fix assertion narrative clearly define the authoritative claims made when DID Key Controllers are not the DID Controller of the Document #831

Open vitorpamplona opened 1 year ago

vitorpamplona commented 1 year ago

The assertion section refers to "claims made by the DID Subject". Since the DID Document can have keys from multiple DID Controllers, the liability of the claim should be linked to the DID Controller of each key. If the DID Controller of the key is the same as the DID Document Controller, then it is an assertion of the DID Subject. If not, then it is an assertion of the DID Subject linked by the DID Controller of the key.

This is just semantics, but it's blocking some institutional use of the spec. A note to release DID Subject of the liability of claims made by different DID controllers listed in a single DID Document would be very, very helpful.

talltree commented 1 year ago

Vitor, you raise a good point. A number of considerations about the relationship of the DID controller (controller of the keys for updating the DID document) to the DID subject (the entity identified by the DID) are discussed generally in Appendix B of the DID spec.

We make it clear there that there are cases where DID controller may be entirely separate from the DID subject. However this separation often cannot be "seen" by an external party. Thus for any particular DID—or set of DIDs—it is up to the DID controller to specify the policies that it will follow with regard to key management and liability.

At the Trust Over IP (ToIP) Foundation, such policies are declared in a governance framework. So it would be the governance framework followed by a particular digital trust ecosystem where the policies for key management and liability should be declared.

vitorpamplona commented 1 year ago

I agree. It's just that it would conflict with the current narrative of the assertion, which forces it to be a DID Subject claim.

jandrieu commented 1 year ago

The language in the spec is in error.

This property is useful, for example, during the processing of a verifiable credential by a verifier. During verification, a verifier checks to see if a verifiable credential contains a proof created by the DID subject by checking that the verification method used to assert the proof is associated with the assertionMethod property in the corresponding DID document.

What I think is meant is that during validation the Verifiable Presentation (VP) proof creator can be checked against the subject identifier of one or more claims to establish that the current holder (and presenter) has access to the same private material as the subject (assuming the issuer performed a DID Auth before issuing to that subject DID).

To wit: verification only checks the tamper-evident signature and the statusCheck property. The business rule that requires evaluating whether or not the presenter/holder is the subject is a part of validation not verification.

Perhaps more important, a VC never has a proof by the subject. Only VPs would have that, if and only if, the holder is the subject.

jmandel commented 1 year ago

(Thanks @vitorpamplona for pointing me to this thread -- very relevant to our discussion on verifiable credentials for clinical data!)

I'd like to introduce a concrete example (even if it's a silly one), because I'm not sure if everyone is talking about the same thing.

Let's look at a DID Document involving four distinct entities:

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ],
  "id": "did:example:all-the-kings-men",
  "controller": "did:example:the-king-of-town",
  "assertionMethod": [{
    "id": "did:example:all-the-kings-men#key-for-the-hornblower",
    "type": "JsonWebKey2020", 
    "controller": "did:example:the-hornblower",
    "publicKeyJwk": {/*omited for brevity*/}
  }, {
    "id": "did:example:all-the-kings-men#key-for-the-knight",
    "type": "JsonWebKey2020", 
    "controller": "did:example:the-knight",
    "publicKeyJwk": {/*omited for brevity*/}
  }]
}

With this configuration, reading the DID Core v1.0 spec:

The assertionMethod verification relationship is used to specify how the DID subject is expected to express claims, such as for the purposes of issuing a Verifiable Credential.

I would conclude that did:example:the-king-of-town intends these two specific JWKs (controlled by did:example:the-hornblower and did:example:the-knight) to express claims (e.g. issue Verifiable Credentials) as did:example:all-the-kings-men. Am I over-reading or mis-reading the DID Core 1.0 semantics as written?

Thus for any particular DID—or set of DIDs—it is up to the DID controller to specify the policies that it will follow with regard to key management and liability.

This makes perfect sense @talltree, in terms of policies about when and how to populate the assertionMethods. But I wouldn't think that the controller's policies could change the meaning of the assertionMethod relationship.

⟹ In my example, I'd think something was broken if The King of Town tried to say "When I write assertionMethod in this particular DID document, I only mean that these keys belong to members of my band. I don't mean to suggest that The Hornblower and The Knight can express claims as or on behalf of All The King's Men."

If we allowed The King to say this, it would seem to limit the usefulness of a standardized assertionMethod relationship, because it falls back to meaning ... whatever The King (or any other DID Controller) says it means in any given context, rather than having standardized semantics.

jandrieu commented 1 year ago

@jmandel presents an example, above.

In that example, the literal controller of the DID, with the capability to modify the DID Document, has created two assertionMethod verification relationships which allow did:example:the-hornblower and did:example:the-knight to sign assertions on behalf of did:example:all-the-kings-men

From a pragmatic perspective, it will be obvious which of those two keys are used when signing a VC issued under the authority of did:example:all-the-kings-men, however, that assertion carries with it the authority of 'did:example:all-the-kings-men' and NOT just the authority of the respective parties did:example:the-hornblower and did:example:the-knight. It does not have the authority of did:example:the-king-of-town

As such, I think you got it exactly right, @jmandel:

If we allowed The King to say this, it would seem to limit the usefulness of a standardized assertionMethod relationship, because it falls back to meaning ... whatever The King (or any other DID Controller) says it means in any given context, rather than having standardized semantics.

The DID Document MUST mean that signing with a verification method associated with an assertionMethod relationship is on behalf of the DID Controller for the presumed DID Subject. If the King merely wants to express that some of his staff use specific keys, he can issue a VC to that effect, although interpreting that VC will require understanding the semantics of the VC, because neither VCs nor DIDs are designed to directly express this notion using semantics from the core specifications. You can, of course, use a VC to say anything, so you can make these statements, provably as the King; you just need a vocabulary that disambiguates that statement clearly and which is known to ultimate recipients of the VC..

I also should point out that the following construct in the DID Document probably doesn't mean what you think it means.

  "id": "did:example:all-the-kings-men",
  "controller": "did:example:the-king-of-town",

This does NOT establish that the literal controller of the DID is did:example:the-king-of-town. Unfortunately, that's not a requirement for the controller property. Different DID methods may use the controller property that way, but some DID methods do not.

What it means is that any verification relationships in the DID document resolved from did:example:the-king-of-town should be considered as authoritative for did:example:all-the-kings-men. It means: go check that other DID document and also use the verification relationships specified there, as if they were in this document.

So, it is worth nothing that the example DOES NOT give did:example:the-hornblower and did:example:the-knight the ability to issue VCs on behalf of the King (did:example:the-king-of-town). It only gives them the authority to issue VCs on behalf of did:example:all-the-kings-men.

vitorpamplona commented 1 year ago

Ok, so is the spec wrong or not? I am confused. @jandrieu you seem to have described what the current text is saying. That it doesn't matter if the DID Controller of each key is different than the DID Document's controller, in the end, the king gave permission to issue credentials on behalf of the band and the band is fully liable for anything each member says. Am I understanding this right?

jmandel commented 1 year ago

the king gave permission to issue credentials on behalf of the band and the band is fully liable for anything each member says

To keep discussion focused I might say "The King has expressed that The Hornblower and The Knight, using the two specified keys, are allowed to issue statements on behalf of the band". Liability seems like another level of the governance stack, and it's not important or even explicit in the band's DID Document that these two entities are members of the band.

vitorpamplona commented 1 year ago

Makes sense.

In this example, both The Hornblower and The Knight can issue VCs as band authorities (for lack of a better word) OR themselves. If The Knight signs the VC with did:example:all-the-kings-men#key-for-the-knight, it means he is signing on behalf of the band. If The Knight signs the VC with did:example:the-knight#key-for-the-knight, then The Knight is signing as himself. Does that make sense? The Key is exactly the same, but the DID path to the key is different.

vitorpamplona commented 1 year ago

Is the issue in the spec simply the "created by the DID subject" language as opposed to "on behalf of the DID subject"? The DID Subject doesn't seem to be something that "creates a proof". The controllers are the ones "creating" proofs, right? For this discussion, is there any difference between the terms: "created by", "on behalf of", "provided by"?

jmandel commented 1 year ago

If The Knight signs the VC with did:example:all-the-kings-men#key-for-the-knight, it means he is signing on behalf of the band.

I think so. When you say "signs the VC with," I'm reading this as "Creates a VC where the 'issuer' property is did:example:all-the-kings-men, and where the signing key is one listed in that issuer's DID Document", though I'm not sure how many of these details are precisely established.

vitorpamplona commented 1 year ago

If The Knight signs the VC with did:example:all-the-kings-men#key-for-the-knight, it means he is signing on behalf of the band.

I think so. When you say "signs the VC with," I'm reading this as "Creates a VC where the 'issuer' property is did:example:all-the-kings-men, and where the signing key is one listed in that issuer's DID Document", though I'm not sure how many of these details are precisely established.

Correct. The verificationMethod of the VC could be either:

As a Band Authority:

{
  /*omited for brevity*/
  "credentialSubject": { /*omited for brevity*/ },
  "proof": {
    "type": "Ed25519Signature2020",
    "verificationMethod": "did:example:all-the-kings-men#key-for-the-knight",
    "proofPurpose": "assertionMethod",
    "proofValue": "..."
  }
}

As a Person:

{
  /*omited for brevity*/
  "credentialSubject": { /*omited for brevity*/ },
  "proof": {
    "type": "Ed25519Signature2020",
    "verificationMethod": "did:example:the-knight#key-for-the-knight",
    "proofPurpose": "assertionMethod",
    "proofValue": "..."
  }
}
jmandel commented 1 year ago

In these examples I'm particularly interested in

  1. How is the issuer populated?
  2. Is there a distraction in meaning if verificationMethod points to one place where the key is published, versus another place? Assuming the key itself is in fact is discoverable from the issuers DID Document?

(I understand that there may not be one single answer or even established practice at this stage... and that additional implementation guides or downstream specs may be required to nail down this level of detail -- but from the periphery it can be hard for me to tell what's settled and what's wide open.)

vitorpamplona commented 1 year ago

The issuer field is somewhat irrelevant since there is no way to prove it's true. The Knight can say he is The Kight (if he is feeling lawful-good), the King, the Band, and even The Hornblower. There's nothing blocking The Knight from claiming to be somebody else in his credential issuance policy. And the verifier has no way to prove if is true unless that information also comes from the verificationMethod's DID Document whose DID Controller is a trusted third-party (The King).

IMHO, because of the link established between the assertion and the DID Subject of each DID Document, the verificationMethod reveals which DID Subject The Knight is signing on behalf of: (i) himself, in his own DID Document, (ii) the band, in the King's DID Document.

If The Knight signs as himself, the verifier can still verify if The Knight is part of the Band by comparing keys. So, there would be a third-party saying that The Knight is reliable (otherwise it would just be a random joe) without the knight having to make credentials on behalf of the band (although he could).

vitorpamplona commented 1 year ago

What it means is that any verification relationships in the DID document resolved from did:example:the-king-of-town should be considered as authoritative for did:example:all-the-kings-men

I just realized that you just implied that any verification relationship (including new ones) will have to be authoritative. We cannot create a moderatorsOfTheBand relationship because moderators are not issuing credentials on behalf of the band. But they would issue other credentials to help moderate the work of the Band. Is that how it is supposed to be?

dlongley commented 1 year ago

@jandrieu,

The language in the spec is in error.

This property is useful, for example, during the processing of a verifiable credential by a verifier. During verification, a verifier checks to see if a verifiable credential contains a proof created by the DID subject by checking that the verification method used to assert the proof is associated with the assertionMethod property in the corresponding DID document.

What I think is meant is that during validation the Verifiable Presentation (VP) proof creator can be checked against the subject identifier of one or more claims to establish that the current holder (and presenter) has access to the same private material as the subject (assuming the issuer performed a DID Auth before issuing to that subject DID).

To wit: verification only checks the tamper-evident signature and the statusCheck property. The business rule that requires evaluating whether or not the presenter/holder is the subject is a part of validation not verification.

Perhaps more important, a VC never has a proof by the subject. Only VPs would have that, if and only if, the holder is the subject.

I think the spec is talking about the DID subject as the issuer of the VC. It is not talking about the credential subject. Holders, presenters, VPs, etc. are not involved at all.

jmandel commented 1 year ago

The issuer field is somewhat irrelevant since there is no way to prove it's true.

I would have expected issuer to convey the semantics of who is making an assertion (e.g., to disambiguate between The Knight speaking for himself vs on behalf of All The King's Men, for this example). Anyone can decide whether to trust this property the same way they'd evaluate other aspects of a VC (e.g., by looking at the signing key and deciding whether they trust it for assertions with the specified issuer, claims, issuance time, etc). For example, the recipient of a VC could start by examining the issuer, deciding whether they're interested in things this issuer has to say; if so they could proceed to resolve the issuer's DID Document, determine the set of assertionMethod keys, and check if the VC has been signed with one of these. This approach would put more emphasis on the issuer and less on the verificationMethod. Other approaches, as you've suggested, might reverse this emphasis.

My expectation based on DID Core v1.0 would be that when an assertionMethod is listed in the DID Document for did:x, any VCs issued based on this assertionMethod would have an issuer of did:x. But that's a loosely held expectation, and I suspect there's room for various implementation choices. https://w3c-ccg.github.io/vc-lifecycle/#delegation-by-the-issuer describes some relevant patterns but leaves a lot to be defined by implementations -- and I'm not sure this analysis of delegation applies to what's happening when The Knight issues a VC as (i.e., speaking for) All The King's Men.

kdenhartog commented 1 year ago

The simple answer of how most code behaves is this although I've seen many different methods misuse these terms:

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ],
  "id": "did:example:all-the-kings-men", // the subject of the DID
  "controller": "did:example:the-king-of-town", // the did that can update the DID Document (although it's never been standardized which verification method is checked from did:example:the-king-of-town to update this did document)
  "assertionMethod": [{
    "id": "did:example:all-the-kings-men#key-for-the-hornblower",
    "type": "JsonWebKey2020", 
    "controller": "did:example:the-hornblower", // the controller of this key with the ability to sign VCs on behalf of did:example:all-the-kings-men. Note this isn't authenticated and is normally assumed to be a copy of the key from the did:example:the-hornblower did document, but it can fall out of sync if did:example:the-hornblower did doc is updated, but this did document isn't updated. Additionally, did:example:the-king-of-town could have created the key and randomly assigned it to be controlled by did:example:the-hornblower even if it's not actually. There's no code that's actually checking this key is actually controlled by who it says it is controlled by.
    "publicKeyJwk": {/*omited for brevity*/}
  }, {
    "id": "did:example:all-the-kings-men#key-for-the-knight",
    "type": "JsonWebKey2020", 
    "controller": "did:example:the-knight",
    "publicKeyJwk": {/*omited for brevity*/}
  }]
}

More importantly though, this thread is a pretty big red flag to me because these terms are determining authorization systems most commonly for VCs which are confusing enough that we are going to see authorization bypass vulnerabilities in VC verifiers because of this. This language needs to be simplified quite a bit and concrete code path examples of how this gets used needs to be defined or the semantic drift between different methods are going to cause vulnerabilities.

vitorpamplona commented 1 year ago

Let's go back to the first principles.

Is it possible to have a non-authoritative verification relationship where keys are known by the controller/subject but are not authorized to make claims on behalf of the Subject?

As an example: The Hornblower and The Knight can make claims on behalf of the band, but not The Singer.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ],
  "id": "did:example:all-the-kings-men",
  "controller": "did:example:the-king-of-town",
  "assertionMethod": [{
    "id": "did:example:all-the-kings-men#key-for-the-hornblower",
    "type": "JsonWebKey2020", 
    "controller": "did:example:the-hornblower",
    "publicKeyJwk": {/*omited for brevity*/}
  }, {
    "id": "did:example:all-the-kings-men#key-for-the-knight",
    "type": "JsonWebKey2020", 
    "controller": "did:example:the-knight",
    "publicKeyJwk": {/*omited for brevity*/}
  }], 
  "nonAuthoritativeMethod": [{
    "id": "did:example:all-the-kings-men#key-for-the-singer",
    "type": "JsonWebKey2020", 
    "controller": "did:example:the-singer",
    "publicKeyJwk": {/*omited for brevity*/}
  }]
}
jmandel commented 1 year ago

Is it possible to have a non-authoritative verification relationship

Sure -- on my reading, the following text:

A DID document MAY include any of these, or other properties, to express a specific verification relationship.

... makes it clear that you can define new relationships as you see fit. You'd have to conceive of can be used to verify assertions made by someone who belongs to the Organization that is the DID Subject as a kind of "relationship between the DID subject and the verification method", to go down this path. I guess you'd call it something like assertionMethodForKnownGroupMember... but this to me feels quite awkward, and I think @jandrieu's suggestion is clearer and more idiomatic:

If the King merely wants to express that some of his staff use specific keys, he can issue a VC to that effect,

... notably, either of these approaches requires defining some new predicates (whether it's a assertionMethodForKnownGroupMember relationship for the DID doc, or a isKnownMemberOfGroup claim in a VC).

vitorpamplona commented 1 year ago

I guess we can also keep non-authoritative keys in the verificationMethod without any verification relationship defined.

But that means that the DID Document is also, at the core, a credential. All verification relationships could have been separate VCs to define the authorization for authoritative and non-authoritative claims.

But they are not. I am trying to understand why. Or what's the line that should take an implementer to express their relationship as a VC instead of just creating a new verification relationship in the DID Documents themselves.

kdenhartog commented 1 year ago

Is it possible to have a non-authoritative verification relationship where keys are known by the controller/subject but are not authorized to make claims on behalf of the Subject?

Yes, this is the purpose of the verificationMethod verification relationship. If you add a key to this VM without referencing it in another VM that grants it further capabilities then it's effectively just a declaration of a key.

This however assumes that the proofPurpose used is never going to be verificationMethod like we see in the VC Data Model. However, it's never been explicitly stated that it won't ever be used in that way so there's no guarantees of it working this way. The only thing making this true at the moment is the implementations themselves, but as you can see it's possible for the proof purpose to be overwritten by that API such that verificationMethod is passed in there and at that point then this is no longer true.

Also, it's worth noting this is all built on the assumption that JSON-LD signatures is in use. If non JSON-LD Signatures are being used then this is even less clear to me and I'm not certain anyone is actually doing this.