Skip to content

Latest commit

 

History

History
334 lines (281 loc) · 13.5 KB

File metadata and controls

334 lines (281 loc) · 13.5 KB

Aries RFC 0592: Indy Attachment Formats for Requesting and Presenting Credentials

Summary

This RFC registers attachment formats used with Hyperledger Indy-style ZKP-oriented credentials in Issue Credential Protocol 2.0 and Present Proof Protocol 2.0. These formats are generally considered v2 formats, as they align with the "anoncreds2" work in Hyperledger Ursa and are a second generation implementation. They began to be used in production in 2018 and are in active deployment in 2021.

Motivation

Allows Indy-style credentials to be used with credential-related protocols that take pluggable formats as payloads.

Reference

cred filter format

The potential holder uses this format to propose criteria for a potential credential for the issuer to offer.

The identifier for this format is hlindy/cred-filter@v2.0. It is a base64-encoded version of the data structure specifying zero or more criteria from the following (non-base64-encoded) structure:

{
    "schema_issuer_did": "<schema_issuer_did>",
    "schema_name": "<schema_name>",
    "schema_version": "<schema_version>",
    "schema_id": "<schema_identifier>",
    "issuer_did": "<issuer_did>",
    "cred_def_id": "<credential_definition_identifier>"
}

The potential holder may not know, and need not specify, all of these criteria. For example, the holder might only know the schema name and the (credential) issuer DID. Recall that the potential holder may specify target attribute values and MIME types in the credential preview.

For example, the JSON (non-base64-encoded) structure might look like this:

{
    "schema_issuer_did": "did:sov:4RW6QK2HZhHxa2tg7t1jqt",
    "schema_name": "bcgov-mines-act-permit.bcgov-mines-permitting",
    "issuer_did": "did:sov:4RW6QK2HZhHxa2tg7t1jqt"
}

A complete propose-credential message from the Issue Credential protocol 2.0 embeds this format at /filters~attach/data/base64:

{
    "@id": "<uuid of propose message>",
    "@type": "https://didcomm.org/issue-credential/%VER/propose-credential",
    "comment": "<some comment>",
    "formats" : [{
        "attach_id": "<attach@id value>",
        "format": "hlindy/cred-filter@v2.0"
    }],
    "filters~attach": [{
        "@id": "<attach@id value>",
        "mime-type": "application/json",
        "data": {
            "base64": "ewogICAgInNjaGVtYV9pc3N1ZXJfZGlkIjogImRpZDpzb3Y... (clipped)... LMkhaaEh4YTJ0Zzd0MWpxdCIKfQ=="
        }
    }]
}

cred abstract format

This format is used to clarify the structure and semantics (but not the concrete data values) of a potential credential, in offers sent from issuer to potential holder.

The identifier for this format is hlindy/cred-abstract@v2.0. It is a base64-encoded version of the data returned from indy_issuer_create_credential_offer().

The JSON (non-base64-encoded) structure might look like this:

{
    "schema_id": "4RW6QK2HZhHxa2tg7t1jqt:2:bcgov-mines-act-permit.bcgov-mines-permitting:0.2.0",
    "cred_def_id": "4RW6QK2HZhHxa2tg7t1jqt:3:CL:58160:default",
    "nonce": "57a62300-fbe2-4f08-ace0-6c329c5210e1",
    "key_correctness_proof" : <key_correctness_proof>
}

A complete offer-credential message from the Issue Credential protocol 2.0 embeds this format at /offers~attach/data/base64:

{
    "@type": "https://didcomm.org/issue-credential/%VER/offer-credential",
    "@id": "<uuid of offer message>",
    "replacement_id": "<issuer unique id>",
    "comment": "<some comment>",
    "credential_preview": <json-ld object>,
    "formats" : [
        {
            "attach_id" : "<attach@id value>",
            "format": "hlindy/cred-abstract@v2.0"
        }
    ],
    "offers~attach": [
        {
            "@id": "<attach@id value>",
            "mime-type": "application/json",
            "data": {
                "base64": "ewogICAgInNjaGVtYV9pZCI6ICI0Ulc2UUsySFpoS... (clipped)... jb3JyZWN0bmVzc19wcm9vZj4KfQ=="
            }
        }
    ]
}

The same structure can be embedded at /offers~attach/data/base64 in an offer-credential message.

cred request format

This format is used to formally request a credential. It differs from the credential abstract above in that it contains a cryptographic commitment to a link secret; an issuer can therefore use it to bind a concrete instance of an issued credential to the appropriate holder. (In contrast, the credential abstract describes the schema and cred def, but not enough information to actually issue to a specific holder.)

The identifier for this format is hlindy/cred-req@v2.0. It is a base64-encoded version of the data returned from indy_prover_create_credential_req().

The JSON (non-base64-encoded) structure might look like this:

{
    "prover_did" : "did:sov:abcxyz123",
    "cred_def_id" : "4RW6QK2HZhHxa2tg7t1jqt:3:CL:58160:default",
    // Fields below can depend on Cred Def type
    "blinded_ms" : <blinded_master_secret>,
    "blinded_ms_correctness_proof" : <blinded_ms_correctness_proof>,
    "nonce": "fbe22300-57a6-4f08-ace0-9c5210e16c32"
}

A complete request-credential message from the Issue Credential protocol 2.0 embeds this format at /requests~attach/data/base64:

{
    "@id": "cf3a9301-6d4a-430f-ae02-b4a79ddc9706",
    "@type": "https://didcomm.org/issue-credential/%VER/request-credential",
    "comment": "<some comment>",
    "formats": [{
        "attach_id": "7cd11894-838a-45c0-a9ec-13e2d9d125a1",
        "format": "hlindy/cred-req@v2.0"
    }],
    "requests~attach": [{
        "@id": "7cd11894-838a-45c0-a9ec-13e2d9d125a1",
        "mime-type": "application/json",
        "data": {
            "base64": "ewogICAgInByb3Zlcl9kaWQiIDogImRpZDpzb3Y6YWJjeHl.. (clipped)... DAtNTdhNi00ZjA4LWFjZTAtOWM1MjEwZTE2YzMyIgp9"
        }
    }]
}

credential format

A concrete, issued Indy credential may be transmitted over many protocols, but is specifically expected as the final message in Issuance Protocol 2.0. The identifier for its format is hlindy/cred@v2.0.

This is a credential that's designed to be held but not shared directly. It is stored in the holder's wallet and used to derive a novel ZKP or W3C-compatible verifiable presentation just in time for each sharing of credential material.

This is the format emitted by libindy's indy_issuer_create_credential() function. It is JSON-based and might look like this:

{
    "schema_id": "4RW6QK2HZhHxa2tg7t1jqt:2:bcgov-mines-act-permit.bcgov-mines-permitting:0.2.0",
    "cred_def_id": "4RW6QK2HZhHxa2tg7t1jqt:3:CL:58160:default",
    "rev_reg_id", "EyN78DDGHyok8qw6W96UBY:4:EyN78DDGHyok8qw6W96UBY:3:CL:56389:CardossierOrgPerson:CL_ACCUM:1-1000",
    "values": {
        "attr1" : {"raw": "value1", "encoded": "value1_as_int" },
        "attr2" : {"raw": "value2", "encoded": "value2_as_int" }
    },
    // Fields below can depend on Cred Def type
    "signature": <signature>,
    "signature_correctness_proof": <signature_correctness_proof>
    "rev_reg": <revocation registry state>
    "witness": <witness>
}

An exhaustive description of the format is out of scope here; it is more completely documented in white papers, source code, and other Indy materials.

proof request format

This format is used to formally request a verifiable presenation (proof) derived from an Indy-style ZKP-oriented credential. It can also be used by a holder to propose a presentation.

The identifier for this format is hlindy/proof-req@v2.0. It is a base64-encoded version of the data returned from indy_prover_search_credentials_for_proof_req().

Here is a sample proof request that embodies the following: "Using a government-issued ID, disclose the credential holder’s name and height, hide the credential holder’s sex, get them to self-attest their phone number, and prove that their age is at least 18":

{
    "nonce": “2934823091873049823740198370q23984710239847”, 
    "name":"proof_req_1",
    "version":"0.1",
    "requested_attributes":{
        "attr1_referent": {"name":"sex"},
        "attr2_referent": {"name":"phone"},
        "attr3_referent": {"names": ["name", "height"], "restrictions": <restrictions specifying government-issued ID>}
    },
    "requested_predicates":{
        "predicate1_referent":{"name":"age","p_type":">=","p_value":18}
    }
}

proof format

This is the format of an Indy-style ZKP. It plays the same role as a W3C-style verifiable presentation (VP) and can be mapped to one.

The identifier for this format is hlindy/proof@v2.0. It is a version of the (JSON-based) data emitted by libindy's indy_prover_create_proof()) function. A proof that responds to the previous proof request sample looks like this:

{
  "proof":{
    "proofs":[
      {
        "primary_proof":{
          "eq_proof":{
            "revealed_attrs":{
              "height":"175",
              "name":"1139481716457488690172217916278103335"
            },
            "a_prime":"5817705...096889",
            "e":"1270938...756380",
            "v":"1138...39984052",
            "m":{
              "master_secret":"375275...0939395",
              "sex":"3511483...897083518",
              "age":"13430...63372249"
            },
            "m2":"1444497...2278453"
          },
          "ge_proofs":[
            {
              "u":{
                "1":"152500...3999140",
                "2":"147748...2005753",
                "0":"8806...77968",
                "3":"10403...8538260"
              },
              "r":{
                "2":"15706...781609",
                "3":"343...4378642",
                "0":"59003...702140",
                "DELTA":"9607...28201020",
                "1":"180097...96766"
              },
              "mj":"134300...249",
              "alpha":"827896...52261",
              "t":{
                "2":"7132...47794",
                "3":"38051...27372",
                "DELTA":"68025...508719",
                "1":"32924...41082",
                "0":"74906...07857"
              },
              "predicate":{
                "attr_name":"age",
                "p_type":"GE",
                "value":18
              }
            }
          ]
        },
        "non_revoc_proof":null
      }
    ],
    "aggregated_proof":{
      "c_hash":"108743...92564",
      "c_list":[ 6 arrays of 257 numbers between 0 and 255]
    }
  },
  "requested_proof":{
    "revealed_attrs":{
      "attr1_referent":{
        "sub_proof_index":0,
        "raw":"Alex",
        "encoded":"1139481716457488690172217916278103335"
      }
    },
    "revealed_attr_groups":{
      "attr4_referent":{
        "sub_proof_index":0,
        "values":{
          "name":{
            "raw":"Alex",
            "encoded":"1139481716457488690172217916278103335"
          },
          "height":{
            "raw":"175",
            "encoded":"175"
          }
        }
      }
    },
    "self_attested_attrs":{
      "attr3_referent":"8-800-300"
    },
    "unrevealed_attrs":{
      "attr2_referent":{
        "sub_proof_index":0
      }
    },
    "predicates":{
      "predicate1_referent":{
        "sub_proof_index":0
      }
    }
  },
  "identifiers":[
    {
      "schema_id":"NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0",
      "cred_def_id":"NcYxi...cYDi1e:2:gvt:1.0:TAG_1",
      "rev_reg_id":null,
      "timestamp":null
    }
  ]
}

Implementations

The following lists the implementations (if any) of this RFC. Please do a pull request to add your implementation. If the implementation is open source, include a link to the repo or to the implementation within the repo. Please be consistent in the "Name" field so that a mechanical processing of the RFCs can generate a list of all RFCs supported by an Aries implementation.

Name / Link Implementation Notes

|