w3c / vc-bitstring-status-list

A privacy-preserving mechanism to publish status information for Verifiable Credentials.
https://w3c.github.io/vc-bitstring-status-list/
Other
22 stars 19 forks source link

Define priority for a single credential with multiple statuses #37

Closed OR13 closed 10 months ago

OR13 commented 1 year ago

In what order should multiple status be processed?

How should an issuer set the order in which a verifier processes these?

In the case of suspension and revocation which takes priority?

Does the verifier have to process all the statues? or does it short circuit?

Sakurann commented 1 year ago

why a single credential would have multiple statuses? what's an example use-case?

OR13 commented 1 year ago

why a single credential would have multiple statuses? what's an example use-case?

A drivers license that can be "revoked" and "suspended"... where one status might be permanent, and the other might be temporary.

dlongley commented 1 year ago

One option is to make it so that verification software doesn't need to care what the order is, it just needs to report the status of all things -- and validation (business rules) will be used to apply some order of precedence, etc.

OR13 commented 1 year ago

Yes, we can define every status... similar to:

The status should condense to a boolean (true or false), regardless of how many "named bits" exist...

dlongley commented 1 year ago

We should make it clear that the order that status entries appear in a credential is not significant.

andresuribe87 commented 1 year ago

How would a single credential with multiple statuses look like? Something like the following? Wouldn't this be invalid JSON?

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/vc/status-list/2021/v1"
  ],
  "id": "https://example.com/credentials/23894672394",
  "type": ["VerifiableCredential"],
  "issuer": "did:example:12345",
  "issued": "2021-04-05T14:27:42Z",
  "credentialStatus": {
    "id": "https://example.com/credentials/status/3#94567"
    "type": "StatusList2021Entry",
    "statusPurpose": "revocation",
    "statusListIndex": "94567",
    "statusListCredential": "https://example.com/credentials/status/3"
  },
  "credentialStatus": {
    "id": "https://example.com/credentials/status/4#12345"
    "type": "StatusList2021Entry",
    "statusPurpose": "suspension",
    "statusListIndex": "12345",
    "statusListCredential": "https://example.com/credentials/status/4"
  },
  "credentialSubject": {
    "id": "did:example:6789",
    "type": "Person"
  },
  "proof": { ... }
}
iherman commented 1 year ago

The issue was discussed in a meeting on 2023-01-24

View the transcript #### 1.3. Define priority for a single credential with multiple statuses (issue vc-status-list-2021#37) _See github issue [vc-status-list-2021#37](https://github.com/w3c/vc-status-list-2021/issues/37)._ **Kristina Yasuda:** Next issue #37. **Orie Steele:** in earlier versions, it was only possible to have one status. just true/false. … it's now possible to have multiple statuses, e.g., a DL that is revoked, suspended, or both. … So what is the order that the verifier should process statuses?. … I'll update the issue to clarify that. **Manu Sporny:** The order of priority is revocation trumps suspension. … The spec todays just defines suspension and revocation, but the field is designed to be openworld. … people can put whatever status they want. > *Kristina Yasuda:* why is it legal to be both revoked and suspended at the same time?. **Manu Sporny:** because of that, I don't think we'll be able to have an order of priority for everything. … just for the things we define.. … If someone creates a new type, its up to them to define how it fits with the existing status terms. … I think its a bit of a corner case. … I don't expect people to create all kinds of crazy forms of status. … We should speak to revocation over suspension.. … The other spec authors can explain how their new types fit it. > *Dave Longley:* I don't think verification software needs to know this and could just report the status of all things ... leaving it to validation (business rules) to determine what to do from there. **Kristina Yasuda:** why would a credential be both revoked and suspended?. … We could say its undefined or if there are multiple states at the same time that's invalid. **Orie Steele:** I want to echo part of what manu said. > *Brent Zundel:* could we make clear that there are possible invalid states?. **Orie Steele:** This is defined for open world application. … While we defined those. Others might add a bunch of additional flags/terms. … I think the issuer should be able to specify the intention and verifiers should be able to execute that order in a computationally efficient way. … Revocation and Suspension are just two of many. … We should not overfit to these two. **Kristina Yasuda:** We could say, the software returns the data and its up to the issuer to indicate the order.. … is that good?. **Manu Sporny:** why would a credential have two statuses?. … Remember these things are issued, they are neither suspended or revoked. In the future, you might need to check both.. … Orie raised a question. Yes this is open world, we can only specify what these two mean and their priority. He also said other things to be done and its up to the issuer to define order of importance.. … we could do that by the ordering in the array.. … The problem is that is currently an unordered set in the VCDM. … So do we add a priority field?. … Or is it just up to the verifier to figure it out. … So we report both pieces of data, and its up to the verifier to decide how to process. … Were you intending there to be an explicit order set by the issuer?. **Orie Steele:** I would like for the issuer to be aware of what they are doing. … If they are assigning over a set, then they need to understand order doesn't matter. … I'm not sure which model we need, but the issuer needs to be clear about it. … The point about the set is really important.. … We have to be clear about our design decisions or they will just treat it as JSON, where order matters.. … So we need to be clear. > *Ted Thibodeau Jr.:* issuer might need to publish info about their statuses (ontology? priority? other?) that verifier can check along with the statuslist. **Kristina Yasuda:** I added the discuss label to the issue. **Manu Sporny:** We're almost to PR, I think. > *Orie Steele:* If order is unimportant, we should say so :). **Manu Sporny:** I'm going to suggest the order is unimportant. … because implementers are going to likely get that wrong. … and its up to the verifier to set the order of importance. … but the spec will clearly say that revocation is more important. … then verifiers can add their own rules after. > *Ted Thibodeau Jr.:* now we're defining business rules?. **Manu Sporny:** so revocation first, then suspension, then any additional rules. … We are defining the validation rules Orie says is imporant. **Ted Thibodeau Jr.:** I get that some people is desiring that. I don't think we should be dictating it in this way.. … I'm ok with someone deciding revoked in their ecosystem trumps everything. … but there are use cases where that isn't true. > *Manu Sporny:* hrm, them perhaps: "status is reported back and the verifier makes the decision on order of importance, with suggestion that revocation is more important than suspension.". **Kristina Yasuda:** I sense more confusion than clarity. I don't think we are ready for PR.
msporny commented 1 year ago

We also need an example in the spec for a VC w/ multiple statuses.

dlongley commented 1 year ago

Applying a change to the comment above, a multiple status VC would actually look more like this (main emphasis on the credentialStatus field here):

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/vc/status-list/2021/v1"
  ],
  "id": "https://example.com/credentials/23894672394",
  "type": ["VerifiableCredential"],
  "issuer": "did:example:12345",
  "issuanceDate": "2021-04-05T14:27:42Z",
  // note the use of an array to represent the set of
  // status entries
  "credentialStatus": [{
    "id": "https://example.com/credentials/status/3#94567"
    "type": "StatusList2021Entry",
    "statusPurpose": "revocation",
    "statusListIndex": "94567",
    "statusListCredential": "https://example.com/credentials/status/3"
  }, {
    "id": "https://example.com/credentials/status/4#12345"
    "type": "StatusList2021Entry",
    "statusPurpose": "suspension",
    "statusListIndex": "12345",
    "statusListCredential": "https://example.com/credentials/status/4"
  }],
  "credentialSubject": {
    "id": "did:example:6789"
    ...
  }
}
OR13 commented 1 year ago

"type": "Person"

Not defined in the context above.

"proof": { ... }

Question was regarding a "credential" but answer is "verifiable credential".

"issued": "2021-04-05T14:27:42Z",

^ is this supposed to be validFrom now?

dlongley commented 1 year ago

@OR13, I made some edits above -- the main point of the example was to show that a set is used for credentialStatus. That was the only important part to highlight right away, IMO, given the number of issues now asking about it. A more robust example should be provided later that is proper in all of the other usual ways.

echenknox commented 1 year ago

I would agree with Kristina Yasuda. The status should not be just a true/false bit result. It also should not be multiple statuses; it would be very confusing. Plus, with @OR13 's question, how to define the priority of each status?

Instead, the status should be just a list of enums. A VC can have one status at a time. For example, suspended, revoked, paused, etc. Then, let the issuer decide how the status transitions from one to the other.

But this will also mean the bit string used in the spec will not work with the enum strategy.

echenknox commented 1 year ago

Applying a change to the comment above, a multiple status VC would actually look more like this (main emphasis on the credentialStatus field here):

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/vc/status-list/2021/v1"
  ],
  "id": "https://example.com/credentials/23894672394",
  "type": ["VerifiableCredential"],
  "issuer": "did:example:12345",
  "issuanceDate": "2021-04-05T14:27:42Z",
  // note the use of an array to represent the set of
  // status entries
  "credentialStatus": [{
    "id": "https://example.com/credentials/status/3#94567"
    "type": "StatusList2021Entry",
    "statusPurpose": "revocation",
    "statusListIndex": "94567",
    "statusListCredential": "https://example.com/credentials/status/3"
  }, {
    "id": "https://example.com/credentials/status/4#12345"
    "type": "StatusList2021Entry",
    "statusPurpose": "suspension",
    "statusListIndex": "12345",
    "statusListCredential": "https://example.com/credentials/status/4"
  }],
  "credentialSubject": {
    "id": "did:example:6789"
    ...
  }
}

Based on the current definition, above json-ld is invalid.

{
  "@context": {
    "@version": 1.1,
    "@protected": true,

    "VerifiableCredential": {
      "@id": "https://www.w3.org/2018/credentials#VerifiableCredential",
      "@context": {
        "@version": 1.1,
        "@protected": true,
        // ... omitted ...
        "credentialStatus": {"@id": "cred:credentialStatus", "@type": "@id"},
        // ... omitted ...

credentialStatus is an @id. It has to be changed to array.

OR13 commented 1 year ago

credentialStatus is an @id It has to be changed to array.

Is this true? I thought JSON-LD will handle object with id or array of object with id consistently...

Is using a single bitstring for multiple statuses a privacy / security risk?

"credentialStatus": [{
    "id": "https://example.com/credentials/status/3#111111111" // same list different index
    "type": "StatusList2021Entry",
    "statusPurpose": "revocation",
    "statusListIndex": "111111111",
    "statusListCredential": "https://example.com/credentials/status/3"
  }, {
    "id": "https://example.com/credentials/status/3#2222222" // same list different index
    "type": "StatusList2021Entry",
    "statusPurpose": "suspension",
    "statusListIndex": "2222222",
    "statusListCredential": "https://example.com/credentials/status/4"
  }],

^ Should this be allowed or forbidden?

dlongley commented 1 year ago

@OR13, @echenknox,

credentialStatus is an @id. It has to be changed to array.

Is this true? I thought JSON-LD will handle object with id or array of object with id consistently...

It's not true; both of the cases you said will work just fine.

Is using a single bitstring for multiple statuses a privacy / security risk?

It would change the herd privacy characteristic. Meaning, at the very least, a larger bitstring would be needed to achieve the same herd privacy as before, since multiple bits would be allocated to the same VC.

Should this be allowed or forbidden?

Debatable -- we should speak to it either way though, given that it changes the privacy characteristics. I would expect it to be more complex to implement vs. having simple composable lists of a single status.

But, if two (or more) separate lists are used, there is something else for us to consider and eventually write about in the privacy section:

OR13 commented 1 year ago

2 lists implies 2 credentials and possibly 2 different keys... so you might see this:

credential signed by issuer key 1 revocation status credential signed by issuer key 2 suspension status credential signed by issuer key 3

On the pros side, using a key for only 1 purpose is a best practice... on the cons side... synchronization costs and higher KMS burden / costs.

dlongley commented 1 year ago

2 lists implies 2 credentials and possibly 2 different keys...

I think using multiple keys here would be unlikely except perhaps in the case that a rotation (without revocation) had occurred over time.

The purpose is still always the same here for the key: signing VCs. In fact, it would create yet another privacy problem if the issuer, for example, used a different key for every VC they signed. I can't recall if we mentioned that in the original VC 1.0 spec privacy section, but it did come up as something important to avoid as it defeats any number of revocation / status privacy mechanisms. At the very least, an issuer should endeavor to sign all VCs of the same type with the same key or they should consider creating sufficient herd privacy.

Here, I'd expect N-many status lists used with the same set of VCs to be coupled / bound / assigned to all work together, just like I have that expectation today with a single status list and the VCs it tracks. But, we should also recommend this in the spec so that's a shared expectation. It makes implementations much easier -- and doing something else could make some implementations impossible, e.g., if the cryptosuites used changed between / amongst the VCs and the status list(s). An implementation would have to support all possible options to be able to properly verify. So, it should be the same across the VCs and the status list(s) to keep it simple and highly interoperable.

OR13 commented 1 year ago

An implementation would have to support all possible options to be able to properly verify.

Yes, potentially: RSA, ECDSA, EdDSA... all to verify 1 credential.

At the very least, an issuer should endeavor to sign all VCs of the same type with the same key or they should consider creating sufficient herd privacy.

A subtle warning is embedded in here, the key used to issue the revocation list could be dynamically changed on each "dereference"... is that allowed?... I've implemented something similar to NFT / NT-NFT VCs before... as a joke, not sure if there is a real use case there.

dlongley commented 1 year ago

A subtle warning is embedded in here, the key used to issue the revocation list could be dynamically changed on each "dereference"... is that allowed?

The advice to reuse the same key across the VCs and the status list(s) would not be followed by doing this. However, since the status list is shared across many VCs, I don't think this changes any privacy characteristics. It doesn't seem to add new correlation factors where we are concerned about it; it's like a new correlating ID for the verifier that retrieved the status list VC, but they are already directly doing the dereference. As long as the cryptosuite is the same, I don't think it would be very harmful to interop either, unless, for example, the verification method is changing such that it requires a different URL resolution protocol. Note: We ought to mention this is another advantage of keeping the key the same.

All that being said, I don't know what the use case for doing it would be; it just sounds like unnecessary complexity. But I don't think we need to explicitly prevent it, unless there's some threat we can clearly outline that stems from doing it.

OR13 commented 1 year ago

Note: We ought to mention this is another advantage of keeping the key the same.

Is there some impact to colluding verifiers if the key is different every time?

What about to the holder?

dlongley commented 1 year ago

Is there some impact to colluding verifiers if the key is different every time?

Verifiers that are colluding to do what (and with whom)? Collusion between verifiers and the issuer is not a privacy threat mitigated by this status tracking mechanism. Verifiers that are colluding with one another can already see the same VCs.

What about to the holder?

Off the top of my head, I don't see an advantage nor a disadvantage, from a privacy perspective, on using a new key to reissue the status list VC each time it's dereferenced. If it's new every time, that should be the same as it always being the same in terms of information leakage. Collusion in sharing retrieved status list VCs would just reveal how many resolutions occurred. If it's some mix of new sometimes / reused other times, then some information could be learned around when the status list VC was retrieved, but that kind of information is likely already available via validFrom or validUntil on probably similar time frames.

OR13 commented 1 year ago

I think this is vendor / business logic validation, and there should be no defined priority, and we can close