andrewwhitehead / anoncreds-w3c-mapping

Python scripts for mapping between Anoncreds presentations and W3C credentials
5 stars 3 forks source link

Notes on using AnonCreds VC in W3C Format to include an LD-Signature #4

Open swcurran opened 1 year ago

swcurran commented 1 year ago

ACA-Py Process:

Here is a current example of working /issue-credential-v2/send:

{
    "connection_id": "b71d5dfe-80f4-46f0-8792-f61b28c1be0a",
    "filter": {
      "ld_proof": {
        "credential": {
          "@context": [
            "https://www.w3.org/2018/credentials/v1",
            "https://www.w3.org/2018/credentials/examples/v1",
            "https://andrewwhitehead.github.io/anoncreds-w3c-mapping/schema.json"
          ],
          "type": [
            "VerifiableCredential",
            "AnonCredsCredential"
          ],
          "issuer": "did:key:z6MkoohH6KMVyiYtAEKNqkfELtKkrhU1kE2Pqwu1gmTfHkto",
          "issuanceDate": "2022-11-09T01:03:20Z",
          "credentialSchema": {
            "type": "AnonCredsDefinition",
            "schema": "3avoBCqDMFHFaKUHug9s8W:2:fabername:0.1.0",
            "definition": "3avoBCqDMFHFaKUHug9s8W:3:CL:13:default"
          },
          "credentialSubject": {
            "attribute": [
              {
                "name": "name",
                "value": "Alice Jones"
              }
            ]
          }
        },
        "options": {
          "proofType": "Ed25519Signature2018"
        }
    }
  }
}

Resulting signed Credential, retrieved using the Post /credentials/w3c admin endpoint:

    {
      "contexts": [
        "https://www.w3.org/2018/credentials/examples/v1",
        "https://andrewwhitehead.github.io/anoncreds-w3c-mapping/schema.json",
        "https://www.w3.org/2018/credentials/v1"
      ],
      "expanded_types": [
        "https://anoncreds.example/2022/ns#AnonCredsCredential",
        "https://www.w3.org/2018/credentials#VerifiableCredential"
      ],
      "schema_ids": [],
      "issuer_id": "did:key:z6MkoohH6KMVyiYtAEKNqkfELtKkrhU1kE2Pqwu1gmTfHkto",
      "subject_ids": [
        "did:key:zUC7DKQSph2TkpniKzPApAA1EJDoSYwfEiSzsPuZzger1ppTVod1NN9VJjY64icfKfr2vxokdwetM6srydoHoqYVUP4g2P2k8QMSfaLQYB4iXFyfx673dXfaRfy7iBop83iNUC5"
      ],
      "proof_types": [
        "Ed25519Signature2018"
      ],
      "cred_value": {
        "@context": [
          "https://www.w3.org/2018/credentials/v1",
          "https://www.w3.org/2018/credentials/examples/v1",
          "https://andrewwhitehead.github.io/anoncreds-w3c-mapping/schema.json"
        ],
        "type": [
          "VerifiableCredential",
          "AnonCredsCredential"
        ],
        "issuer": "did:key:z6MkoohH6KMVyiYtAEKNqkfELtKkrhU1kE2Pqwu1gmTfHkto",
        "issuanceDate": "2022-11-09T01:03:20Z",
        "credentialSubject": {
          "attribute": [
            {
              "name": "name",
              "value": "Alice Jones"
            }
          ],
          "id": "did:key:zUC7DKQSph2TkpniKzPApAA1EJDoSYwfEiSzsPuZzger1ppTVod1NN9VJjY64icfKfr2vxokdwetM6srydoHoqYVUP4g2P2k8QMSfaLQYB4iXFyfx673dXfaRfy7iBop83iNUC5"
        },
        "proof": {
          "type": "Ed25519Signature2018",
          "proofPurpose": "assertionMethod",
          "verificationMethod": "did:key:z6MkoohH6KMVyiYtAEKNqkfELtKkrhU1kE2Pqwu1gmTfHkto#z6MkoohH6KMVyiYtAEKNqkfELtKkrhU1kE2Pqwu1gmTfHkto",
          "created": "2022-11-09T19:47:25.084875+00:00",
          "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..rwNLAKCRbhZD7ZYCNcyBfpEcRZXu4liJWcOQoFkUt9roTNV2bKbhqisrn6zkhm4GOvY-ysQdZ_4KBnVqkDuKBw"
        },
        "credentialSchema": {
          "type": "AnonCredsDefinition",
          "schema": "3avoBCqDMFHFaKUHug9s8W:2:fabername:0.1.0",
          "definition": "3avoBCqDMFHFaKUHug9s8W:3:CL:13:default"
        }
      },
      "cred_tags": {},
      "record_id": "409bc3191f904e988958ad6e05feed76"
    }
swcurran commented 1 year ago

Questions:

Thanks!

andrewwhitehead commented 1 year ago

That's odd that it would require the example context, I'm pretty sure we don't use any terms from there.

We could add proofPurpose, verificationMethod or created to the proof but I think it would need to be authenticated by the ZKP somehow. verificationMethod would normally reference the issuer's public key, in this case maybe the cred def. Those properties are currently defined by the proof method, so they are not required for all proofs.

swcurran commented 1 year ago

The example context was not needed for the "pure" AnonCreds credential. I'm pretty sure that somewhere along the line, ACA-Py is adding id into the credentialSubject, and so to get that processed, the example context is needed.

There is some weird things in the ACA-Py implementation of LD-Signatures, I think -- see this ACA-Py Issue I created. I think id is added in if not present, but added in badly. May be in the demo code or in ACA-Py itself.

andrewwhitehead commented 1 year ago

If the credential already has a proof (or more) I believe ACA-Py should be stripping that off before generating the new proof and adding it to the original credential.

I doubt we have handling for multiple proofs at the moment, never mind unit tests, but it might not be that hard to add.

PatStLouis commented 1 year ago

@swcurran Some questions/observations I have:

  1. Shouldn't the did method used for the schema/cred_def be included so they can be resolved, maybe providing a resolver service endpoint along with it?
  2. In the provided example a new wallet with the did:key method is created, any issue with using a public did:sov wallet?
  3. One can also use the json-ld sign/verify endpoints for a simpler demonstration (however this won't deliver the credential, only issue it)

Here's an example I was playing around with, following the current vc-api spec. I also added a totally made-up/incorrect credentialStatus method to provide the revocation registry associated with the cred_def.

The body can be pasted into the "doc" section of an aca-py's admin api json-ld/sign endpoint and use the verkey from the verificationMethod for the "verkey" section of the payload. Obviously the issuer did/verification method will have to be changed according to your agent.

{
    "credential": {
        "@context": [
            "https://www.w3.org/2018/credentials/v1",
            "https://www.w3.org/2018/credentials/examples/v1",
            "https://andrewwhitehead.github.io/anoncreds-w3c-mapping/schema.json"
        ],
        "type": [
            "VerifiableCredential",
            "AnonCredsCredential"
        ],
        "id": "did:web:idlab.org",
        "issuer": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM",
        "issuanceDate": "2023-02-23 18:39:30.294333",
        "credentialStatus": {
            "type": "TailsRevocation2023",
            "uri": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM:4:9PGvwPsJMLXrmtiNwTaQTM:3:CL:18546:Idlab demo:CL_ACCUM:62bc54d2-e7de-4974-8e8e-1eb2e65fcbb1"
        },
        "credentialSchema": {
            "type": "AnonCredsDefinition",
            "id": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM:3:CL:18546:Idlab demo",
            "schema": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM:2:idlab_demo:0.0.3"
        },
        "credentialSubject": {
            "id": "did:web:did.actor:alice",
            "givenName": "Alice"
        }
    },
    "options": {
        "verificationMethod": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM#5a36pxvK2KDpaFVXD8bwRxhcjPRdZXratDrTKxnUDAhc",
        "proofPurpose": "assertionMethod",
        "type": "Ed25519Signature2018"
    }
}

The verifier will then be able to resolve the did, schema, cred_def and rev_reg.

Here is the VC obtained, which you should be able to verify for yourself.

{
    "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://www.w3.org/2018/credentials/examples/v1",
        "https://andrewwhitehead.github.io/anoncreds-w3c-mapping/schema.json"
    ],
    "type": [
        "VerifiableCredential",
        "AnonCredsCredential"
    ],
    "id": "did:web:idlab.org",
    "issuer": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM",
    "issuanceDate": "2023-02-23 18:51:21.741980",
    "credentialStatus": {
        "type": "TailsRevocation2023",
        "uri": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM:4:9PGvwPsJMLXrmtiNwTaQTM:3:CL:18546:Idlab demo:CL_ACCUM:62bc54d2-e7de-4974-8e8e-1eb2e65fcbb1"
    },
    "credentialSchema": {
        "type": "AnonCredsDefinition",
        "id": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM:3:CL:18546:Idlab demo",
        "schema": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM:2:idlab_demo:0.0.3"
    },
    "credentialSubject": {
        "id": "did:web:did.actor:alice",
        "givenName": "Alice"
    },
    "proof": {
        "verificationMethod": "did:indy:bcovrin:dev:9PGvwPsJMLXrmtiNwTaQTM#5a36pxvK2KDpaFVXD8bwRxhcjPRdZXratDrTKxnUDAhc",
        "proofPurpose": "assertionMethod",
        "type": "Ed25519Signature2018",
        "created": "2023-02-23T23:55:41Z",
        "jws": "eyJhbGciOiAiRWREU0EiLCAiYjY0IjogZmFsc2UsICJjcml0IjogWyJiNjQiXX0..Kyky_ps9h8QvQa8C4cqpN_FWiMp-jppnmcg4QmOx1z73BfKBI6ud6Kiu7QlnyEOkCrxd745sNRzjgRC3eXqLCA"
    }
}

You can verify this credential on the admin json-ld/verify endpoint using the verkey from the verificationMethod and it will return true.

Furthermore the credentialSubjet.id could be set to a did:key from the holder an enable the nonTransferable property for some sort of holder-binding.

swcurran commented 1 year ago

Responses to your questions/comments:

  1. The ID of the schema/cred def implies the AnonCreds Method to use. Embedded within the object is the controller ID that created the AnonCreds object (Schema or CredDef) and that ID might also be included in the ID of the object itself — as does for any Hyperledger Indy AnonCreds method (using Legacy Indy or did:indy).

  2. For the LD Signature, a published key, such as one on a Hyperledger Indy ledger (a did:sov or a did:indy) definitely could be used.

  3. Agreed.

On the examples — very cool. I had to reread your comment about the CredentialStatus :-) . Interesting to see if the data for the AnonCreds revocation proof could go into that part of the Credential.