Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: create design doc for adding W3C VC format support #2674

Merged

Conversation

tra371
Copy link
Contributor

@tra371 tra371 commented Dec 13, 2023

This PR contains one main document:

  • AnoncredsW3CCompatibility.md - the design document for implementing w3c vc/vp format support

@tra371
Copy link
Contributor Author

tra371 commented Dec 13, 2023

@swcurran @TimoGlastra @dbluhm this is the new repo with DCO checks passed.


## Caveats

For now, we will only target compatibility with [VCDM (Verifiable Credential Data Model) 1.1](https://www.w3.org/TR/vc-data-model/) because the Rust framework we are deriving from is also working with that target. This means we would support the features being implemented in the RUST frameworks, which include:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that ACA-Py "cares" about which version is used -- I think the features will all be the same. From what I understand, the impacts are minimal from the AnonCreds W3C VC/VP formats -- different @context files, and the name of the issuanceDate field. I think everything else is the same.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There may be some tweaks required to get v1 and v2 of the VC data model working correctly. Some checks are done on the issuanceDate fields I believe, as well as on the exact values of the @context (MUST contain the v1 context url).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that ACA-Py wants to treat versions of VCDM as minor variations rather than radically different things, I think the preferred answer to this question which @swcurran raises below is probably his first proposal -- a flag passed as input -- instead of a different endpoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! We're gonna settle for flag parameters for now.. thank you for the insights and suggestions!


- If and how the W3C VC Format attachments for the Issue Credential V2.0 and Present Proof V2 Aries DIDComm Protocols should be used when using AnonCreds W3C VC Format credentials.
- How AnonCreds W3C VC Format verifiable credentials are stored by the holder such that they will be discoverable when needed for creating verifiable presentations.
- How and when multiple signatures can/should be added to a W3C VC Format credential, enabling both AnonCreds and non-AnonCreds signatures on a single credential and their use in presentations.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I think we need to discuss/document how this should, I think it this is out of scope of this effort. I think the controller will do the operations necessary to enable this, and that ACA-Py need not orchestrate the work. At most a demo flow and documentation of any missing features is needed.


### What is the roadmap for delivery? What will we build first, then second?

1. Python wrappers around Rust
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the Python wrapper are already completed and available in the anoncreds-rs library. Is that not the case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, the wrappers are already completed. It was supposed to say that we are gonna make use of the wrapper. I'll rephrase or remove that.


After thoroughly reviewing upcoming changes from [anoncreds-rs PR273](https://github.com/hyperledger/anoncreds-rs/pull/273), the classes or `AnoncredsObject` that we deemed necessary to be exported are:<br>

[W3CCredentialOffer](https://github.com/hyperledger/anoncreds-rs/pull/273/files#diff-6f8cbd34bbd373240b6af81f159177023c05b074b63c7757fc6b3796a66ee240R106)<br>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor point -- per the last meeting -- the "W3C-specific" versions of these calls have been dropped as they are identical to the existing calls.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"calls" meaning CredentialOffer and CredentialRequest.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I've checked that W3cCredentialOffer and W3cCredentialRequest are removed. will remove them as well.


There are two scenarios to consider when we want to add w3c format support to ACA-PY.

- Creating a W3C VC credential from credential definition, and issuing and presenting it as is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the places that we need to focus -- how is the ACA-py Admin API affected to enable creating an AnonCreds VC and what happens after that. I think we have to make the technique backwards compatible, so that existing Controllers (business logic) continue to work with legacy AnonCreds.

The options that I see are to add an optional flag "W3cFormat" (or whatever 😄 ) that is set true when an issuer wants to issue in W3C format. Alternatively, we can implement different endpoints.

For receiving a credential issued in W3C format, or a presentation presented in W3C format, we'd like that to "just work". Detect the format and process the data in either format. The tricky thing there is going to be the (still to be determined) attachment format of an AnonCreds credential/presentation. That topic is still being discussed.

Copy link

@dhh1128 dhh1128 Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like Stephen's idea and suggest using an input parameter with a name something like VCDM11 and another like VCVDM20, since this reduces the differences between them to a trivial constant, and sets up ACA-Py for future adaptations if the VCDM evolves more. This would mean it's not quite a boolean, but rather a number (which, if 0, means "legacy", maybe).

However, if ACA-Py is only ever going to support creating data in one version of the VCDM at a time (even if it can receive the data in multiple versions), then we can simplify back to the boolean flag.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent some time poking around the admin interface and studying test code, and I'm thinking that @swcurran is a genius. My vision wasn't good enough. Stephen said that he prefers to have ACA-Py just do the right thing when it is receiving a credential. I was thinking that on the issuance side, we'd have to add a flag to create_credential (e.g., here), and so I was looking at higher-level interfaces to try to figure out how a caller could provide input in a way that would tell us how to set that flag. But now I'm thinking that it is also possible to extend the "just do the right thing, based on the data" strategy to issuance as well. This would eliminate the need to change the admin interface at all, because the data format would be signaled by the credential request. We'd still modify create_credential, maybe, but only to accept a flag and do a credential conversion at the very end; otherwise everything would stay the same.

The magic is enabled by using the data payload of the propose-credential message in the Issue Credential protocol. If the preview is a w3c format, the everything switches to issuing in that format. If not, it remains legacy. This means that ACA-Py just always, naturally and perfectly, does the right thing, serving up whatever data type the remote parties want.

Maybe there are some gotchas to this approach that I haven't realized, but it seems ideal if we can make it work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i like this approach - is the old Perl spirit, and simpler semantics


- W3C Credential Offer

**NOTE: In the W3C VCDM, there is no concept of a credential offer, and most implementations of W3C VCs have no step where a credential is offered before it is issued. This is because, unlike AnonCreds, W3C VCs require no cryptographic commitment from the holder. So an alternative approach to credential offers is to simply not provide them in the W3C case. However, we think that it is simpler to expose the step as part of our support, thus giving the option for the future and making the correspondence between W3C and AnonCreds features more regular.**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An AnonCreds credential, whether in legacy or W3C VC Format must have an Offer and Request, so absolutely must be supported. It is necessary for the AnonCreds cryptography. This will (by definition) limit the holders that can use "flexcred" credentials to those that can support AnonCreds, but it is our required starting point.

A constraint of what we are doing is that every AnonCreds credential can be issued in W3C VC Format, but not every W3C VC can be issued in AnonCreds format. Notable limitation are complex JSON structures (although in theory, some could be flattened to work in AnonCreds) and JSON arrays or arbitrary length objects. The latter cannot be supported in AnonCreds, since the CredDef in AnonCreds defines exactly how many items are in the issued credentials.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duly noted!


### How a W3C credential is stored in the wallet.

Storing a credential in the wallet is somewhat dependent on the kinds of metadata that are relevent. The metadata mapping between the W3C credential and an anoncreds credential is not fully clear yet.
Copy link
Contributor

@swcurran swcurran Dec 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requirement is that a stored AnonCreds W3C VC format credential must be accessible in the same way as a legacy AnonCreds VC format -- searchable in the same way. In storing credentials, encrypted tags are generated to enable querying for a credential (using WQL) to find ones in a holder's storage that satisfy a presentation request. I'm not sure of the implication of that. Does an AnonCreds VC in W3C VC Format need to be converted to legacy format before storage?

I'll see what I can find out about that.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about changes that Askar might have made, but I'm pretty sure that in the original wallet impls, the cred itself was just an opaque blob, so it wouldn't need a format conversion before storing. What we would need, however, is a comparable extraction of metadata (cred def, schema, issuer, date, etc).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree — I’ll see what I can find out about where/how that happens.

}
```

**Question: Would it also be possible to generate the credentials on the fly to eliminate the need for storage?**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, I don't think this is a viable approach -- particularly for a holder. In storing a credential, a big need is the ability to query for it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Querying is done against metadata, I think, not by peering inside actual credential content. So it might be possible to generate and index metadata without storing the content. But perhaps this is a distinction without a real difference, and maybe it's not worth entertaining. Storing both formats of a credential isn't hard.

One wrinkle is that, if a credential is indexed in two formats with essentially the same metadata, many wallets may suddenly find themselves having to prompt the user to select a format, when before they only got one hit from a query. If you know that the only credential that satisfies a query is your driver's license, and you get used to that credential being selected automatically, it may be a little jarring to suddenly have to decide which format of your credential you want to use. So I think one important to-do item might be to detect which format the proof request wants, and use that to filter. Proof requests that say, "I'll take either format" need to declare a preference for one over the other, or else agents need to have one format that they prefer over the other by default.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aries Agents are designed to store the credential as a blob, and to add tags to enable querying. I did some checking with @andrewwhitehead about how that worked in ACA-Py/Askar/AnonCreds, and he let me know that it is ACA-Py's responsibility to extract/define the tags that point to an object (e.g., the credential), and to pass them to Askar for storage, along with the object itself. So, extracting the code, and adding a tag for the format(s) of a credential should be doable. No need to have two sets of tags for the same object just because it can be used in different types of presentations.


Only one of the signature types (CL) is allowed in the AnonCreds format, so if a W3C VC is created by `to_legacy()`, all signature types that can't be turned into a CL signature will be dropped. This would make the conversion lossy. Similarly, an AnonCreds credential carries only the CL signature, limiting output from `to_w3c()` signature types that can be derived from the source CL signature. A possible future enhancement would be to add an extra field to the AnonCreds data structure, in which additional signatures could be stored, even if they are not used. This could eliminate the lossiness, but it adds extra complexity and may not be worth doing.

### Compatibility with AFJ: how can we make sure that we are compatible?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is crucial -- especially in the design phase, so both groups are in sync, and with tests.


### Where should the new issuance code go?

So the [vc](https://github.com/hyperledger/aries-cloudagent-python/tree/main/aries_cloudagent/vc) directory contains code to verify vc's, is this a logical place to add the code for issuance?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this -- start from the Admin API for Issuing Credentials V2 and Presenting Proof V2 and follow the handlers. That will define where the code will go. As noted, existing functionality should not be impacted -- the implementation should be added. Triggers for calling the new code should be receiving data in the W3C VC Format, or via a configuration setting/Admin API setting that triggers emitting an AnonCreds W3C VC/VP format document.


So the [vc](https://github.com/hyperledger/aries-cloudagent-python/tree/main/aries_cloudagent/vc) directory contains code to verify vc's, is this a logical place to add the code for issuance?

### What do we call the new things? Flexcreds? or just W3C_xxx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think AnonCreds in W3C VC (and/or VP) Format. Long, ugly, but accurate. AWVCF?

FlexCreds is not really the right term, since it refers specifically to a VC with multiple attached signatures.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I put on my political hat, the naming strategy I'd be tempted to follow is to put the VC part first: W3C VC+Anon. You could also do something a bit like movies that use phrases like "The Matrix Reloaded" and do "VC Anonymized".

There are two reasons to put the VC part first. One is to make it impossible to refer to the technology without the VC brand (something that critics of Anoncreds have long urged people to do). The other is to make it clear that Anoncreds bring a new value to the VC ecosystem, by creating a minimal pair that highlights the anonymity. The thinking you want to encourage in a casual encounter is: "Do you want just plain VC, or do you want VC+Anon, which clearly has more features?"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this makes sense to me - @swcurran if you agree we could try to make it compatible between the workstreams, @TimoGlastra if you agree?

@swcurran
Copy link
Contributor

Thanks for the document and dealing with the DCO issue -- a pain, but now you know it is always needed :-).

I've added comments -- I hope they help. As noted, the biggest issue I see for the design is tracing from the Admin API and deciding how to enable emitting an AnonCreds W3C VC/VP format. As well, how a received AnonCreds VC/VP is automatically handled -- triggering the right processing steps.

The TBDs are important -- especially the Attachment format to use for the Issue Credential V2 and Present Proof V2 protocols in alignment with AFJ. We all need to work on that.


We don't need to input any parameters to it as it in turn calls `Credential.from_w3c()` method under the hood

### Format Handler for Issue_credential V2_0 Protocol
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@swcurran @dhh1128 @gvelez17 i just added this and i would like your reviews on it. like is this a correct approach to add the w3c format support on the same level as anoncreds?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the correct approach (adding a new formathandler)

@TimoGlastra
Copy link
Contributor

RFC for Data Integrity issuance attachment: hyperledger/aries-rfcs#809

Would love to hear your feedback!

@swcurran
Copy link
Contributor

Hi All. I found it challenging to review this via comments and so am proposing we iterate in a different way for a bit. While there is lots of good content here, I think there are some key overview adjustments needed. I’m hoping at the call on 2024.01.15 we’ll nail those down.

To make it easier to iterate, I’ve copied this into a HackMD document that we can collaborate on, and then made what I think are the appropriate revisions. The main focus of my changes are:

  • What triggers the use of AnonCreds W3C VC/VP Formats?
  • What attachment formats are we using for the Issue Credential and Present Proofs v2.0 protocols when handling AnonCreds W3C VC credentials?
  • What dependencies are there in getting started? I think they are all now complete.
  • What is in scope and out of scope for this effort.

I’m not the one to say what or how to change the code, but I am trying to use my experience with ACA-Py, AnonCreds, Aries Protocols and VCs to guide the work.

I hope this helps us finalize the changes needed so that the coding can start.

Feel free to make changes directly to this document, use the Comment feature, or to add questions/comments directly in the document. Unfortunately, I didn’t have the “Premium Plan” when I started, but I’ve added that, so we can now track the changes by versions.

@TimoGlastra
Copy link
Contributor

I just created a dev release for the AnonCreds RS library, https://github.com/hyperledger/anoncreds-rs/releases/tag/v0.2.0-dev.7, with wrappers for Python and JS. You can from now on use this dev version. If you encounter any issue with the dev release please open an issue in the AnonCreds RS library, so it can be addressed before we make the stable 0.2.0 release soon

@swcurran
Copy link
Contributor

@ianco — can you please make the update in ACA-Py to reference the newly published artifact? I’ll add an issue (doh!).

Copy link
Contributor

@ianco ianco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi folks, overall this looks good. The only question I have is on the storage format of the new credentials and the impact on the admin API. I think, since we are receiving AnonCreds credentials, they should get picked up by any existing API's that look for AnonCreds credentials, and any storage differences should be handled transparently. I don't know if we will even need to distinguish between AnonCreds credentials received via W3C or the "old" Indy format, but if so this could be a parameter on the query.


We don't need to input any parameters to it as it in turn calls `Credential.from_w3c()` method under the hood

### Format Handler for Issue_credential V2_0 Protocol
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the correct approach (adding a new formathandler)

@tra371
Copy link
Contributor Author

tra371 commented Jan 23, 2024

hey @ianco , per the discussion with my team, we don't have a hard set decision on the storage format yet but it might likely be just json-ld as it's a standard for VCs and we'll see in the implementation stage if json-ld needs to be serialized as plain json for necessary encryptions in the wallet and yes I agree that if there is any need to distinguish between the two formats, we can introduce a new parameter to the query.

@ianco
Copy link
Contributor

ianco commented Jan 23, 2024

hey @ianco , per the discussion with my team, we don't have a hard set decision on the storage format yet but it might likely be just json-ld as it's a standard for VCs and we'll see in the implementation stage if json-ld needs to be serialized as plain json for necessary encryptions in the wallet and yes I agree that if there is any need to distinguish between the two formats, we can introduce a new parameter to the query.

I guess the actual storage format isn't as important as what is returned from the API's.

The existing API's that return anoncreds credentials should include the new anoncreds credentials (received in a W3C "package") in the same format as the existing anoncreds credentials. I.e. it should be a full list of all anoncreds credentials regardless of how they were received. If the new anoncreds-w3c credentials are stored in a different format, then this API needs to do the conversion.

Regarding the existing "w3c" endpoints, I'm not sure if it makes sense to also include the anoncreds-w3c credentials in this API as well ...

@tra371
Copy link
Contributor Author

tra371 commented Jan 23, 2024

hey @ianco , per the discussion with my team, we don't have a hard set decision on the storage format yet but it might likely be just json-ld as it's a standard for VCs and we'll see in the implementation stage if json-ld needs to be serialized as plain json for necessary encryptions in the wallet and yes I agree that if there is any need to distinguish between the two formats, we can introduce a new parameter to the query.

I guess the actual storage format isn't as important as what is returned from the API's.

The existing API's that return anoncreds credentials should include the new anoncreds credentials (received in a W3C "package") in the same format as the existing anoncreds credentials. I.e. it should be a full list of all anoncreds credentials regardless of how they were received. If the new anoncreds-w3c credentials are stored in a different format, then this API needs to do the conversion.

Regarding the existing "w3c" endpoints, I'm not sure if it makes sense to also include the anoncreds-w3c credentials in this API as well ...

ah yes, I see what you mean now. I agree that the storage format doesn't matter very much as long as it can be properly deserialized. The tags for w3c anoncreds will be a bit different than those for the legacy, which looks like this:

tags = {
            "schema_id": schema_id,
            "schema_issuer_did": schema_id_parts[1],
            "schema_name": schema_id_parts[2],
            "schema_version": schema_id_parts[3],
            "issuer_did": cdef_id_parts[1],
            "cred_def_id": cred_def_id,
            "rev_reg_id": cred_recvd.rev_reg_id or "None",
        }

If I understand this correctly, the mime types of the credential are mapped to this tags dictionary before storing it. So, if we can easily distinguish between the two formats by tracking the difference, and it won't change how the API is called to get these credentials I guess. If not, we don't need these w3c endpoints.

Copy link

Quality Gate Passed Quality Gate passed

Kudos, no new issues were introduced!

0 New issues
0 Security Hotspots
No data about Coverage
No data about Duplication

See analysis details on SonarCloud

@ianco ianco merged commit ad58dbe into openwallet-foundation:main Jan 24, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants