Hyperledger Aries ACA-Py Agents Setup and Running Tutorials — Part VII — Proof request, Reveal and Verification

Dr. Yunxi Zhang
9 min readSep 20, 2021

Introduction

In Part I, I’ve introduced the general benefits of using SSI and why Hyperledger Indy and Aries can fit in the big picture. In Part II, a scenario overview and tools were described. Part III shows details on how to set up a Dev environment to run an ACA-Py agent V0.6.0. In Part IV, it focused on the one-time agent level connection channel establishment. Part V described how to create a credential schema as well as its relevant credential definition. Part VI showed how a holder can request a new credential from an issuer, who will then issue a new credential to the holder as per holder’s request, so the holder can receive the newly issued credential from the issuer. This Part VII will present how a proof (aka claim) of a credential is requested from a verifier. The holder will then reveal a proof for the verifier to achieve the proof verification.

Zero-Knowledge Proof and Selective Disclosure of Credentials in ACA-Py’s Current Implantation

By looking at the Zero-Knowledge Proof (ZKP) in Wikipedia, an initial concept of ZKP introduced to readers is that a holder doesn’t need to reveal any physical stuff to a verifier, whilst the holder can still prove to the verifier s/he does hold the stuff. For instance, Alice as a holder has a driving licence that shows her name, ages etc. When Bob asks Alice to prove she can drive, Alice doesn’t have to show Bob her driving licence; instead, Bob can challenge Alice by asking different questions until he believes Alice must have her driving licence as Alice is able to answer all of them correctly, because she wouldn’t have had these knowledge without a driving licence. The key message here is Alice has never shown her driving licence to Bob.

In ACA-Py, the use of ZKP is a bit different and a concept of Selective Disclosure as another feature is also introduced.

figure 1 — ACA-Py’s support for ZKP and Selective Disclosure

Scenario 1 (ZKP without revealing a credential): A verifier only wants to know if a holder has a credential issued by an issuer. So, the holder only reveals the proof showing s/he has got a valid credential issued by the issuer. This scenario aligns with the initial concept of ZKP, but unfortunately, this feature IS NOT supported in ACA-Py (at least until v0.6.0) when this blog is being written. This means at least a small amount of information along with an ACA-Py credential proof will always need to be disclosed.

Scenario 2 (ZKP or/and Selective Disclosure when revealing a credential): in figure 1, a verifier wants to make sure the holder is 16 years-old or above, nickname is Peter. The ZKP used here is John doesn’t have to reveal his real age, but still can prove he’s above 20. The Selective Disclosure here applies to the fact that only 2 attributes along with their values/proofs out of 5 in this credential are disclosed by John.

General Process Overview

There are a few steps involved to enable the verifier to get a a proof of a credential from the issuer and verify it. To simply the description, the below process will only use a single credential, but in fact, multi-credentials are allowed in the process.

Step 1: verifier -> holder: the verifier requests a credential proof request to the holder specifying what credential proofs is needed + a time point requirement to state a credential must be still valid (i.e. not revoked/expired) until then.

Step 2: holder -> verifier: the holder checks his/her credentials to find out what a credential can fulfil the proof request (This is a business logic that should be implemented in a customised app, which is not covered in ACA-Py). Once determining the selected credential, the holder sends a credential proof that will contain only information that needs to be revealed to fulfil verifier’s request.

Step 3: the verifier communicates with the Indy DLT network to verify the validity of holder’s submitted credential proof.

To make below steps to work, please make sure you have completed all the pre steps in my blog series.

Step 1: Verifier sends a credential proof request

By using our example in this blog, let’s say a verifier wants to request a credential proof claiming that (1) a holder’s Last Name and (2) the holder’s Age is over 16.

You can now call a POST API named: /present-proof/send-request on the verifier’s agent. The JSON body is quite long, you could quickly copy the sample body from the holder agent’s Open API (figure 2).

figure 2— API for sending a credential proof request

The bit we need to change in the JSON sample body are mainly the key/value pair as shown below.

“connection_id”: the connection id used by the holder agent that can communicate with the issuer agent.

“proof_request”: this block contains the detailed proof request. Depends on the business requirements, the attributes and values inside it will be different.

“requested_attributes”: this key is inside the “proof_request”, it aims to request particular credential attributes. This key can have one or more sub key/value pairs. The key name can be any String, and a value is another sub key/pair names — with a key named “name” and a value which is a string representing a credential attribute.

Below shows an example that the verifier wants to see the holder’s First Name.

“requested_attributes”: {     “additionalProp1”: {           “name”: “firstname”     }}

“requested_predicates”: this key is also inside the “proof_request”, it aims to request particular predicates (see Scenario 2 in figure 1 as an example). This key can have one ore more sub key/value objects. The key name can be any String, and its value is another key/value objects.

Below shows an example that says it requests the holder must prove he/she is at least 10 years-old and above without showing a real age in the credential proof.

“requested_predicates”: {    “additionalProp2”: {        “name”: “age”,        “p_type”: “>=”,        “p_value”: 10,        “restrictions”: [{}]    }}

“non_revoked”: this key is a very confusing one. Initially, it can have both “from” and “to” as sub keys with values. However, to implement a feature that requesting a credential to be valid from a specific time range has been demonstrated as nearly impossible in the community (at least for the time being). Therefore, the only key/value pair needed is “to” and its value (an epoch representing a particular time point). To understand its details , please see this long conversations I had with the community.

Below shows an example. Semantically, it requests a credential proof where its original credential is valid at least until an epoch value of 1632155444. Translating this value to a human-readable time by using this service, it is: Mon, 20 Sep 2021 16:30:44 GMT.

“non_revoked”: {    “to”: 1632155444}

Eventually, the entire body is shown in figure 3 below.

figure 3 — a body payload for sending a credential proof request in the verifier’s agent

Once successful, a long JSON payload will be returned. Figure 4 only shows an excerpt. Line 45 shows its state as “request_sent”.

figure 4 — request has been sent

Step 2: Holder reveals a credential proof

You can now call a GET API named: /present-proof/records on the holder’s agent (see figure 5).

figure 5 — API call to get all proof requests records i the holder’s agent

Once successful, we can see a long JSON response, only an excerpt as shown in figure 6. Note down the value (29cda5c5-a877-4bc4-9369-2dad925e2c57 in my case) for the key “presentation_exchange_id”, as we will need it later on.

figure 6 — JSON response for getting all proof request records on the holder’s agent

As we know, in our example, the holder already has obtained a credential from the issuer including (1) lastname (2) firstname and (3) age. The value put for each are: (1) Peter (2) Pan and (3) 14. Therefore, the holder can reveal a credential proof based on this credential to the verifier. Note, as mentioned earlier, the business function such as searching local credentials to find out which credentials can fulfil the verifier’s request should be implemented separately in an customised app, as this feature is not provisioned by ACA-Py yet.

You need to call a GET API named: /credentials to get the detailed credentials (see figure 7). Note down the value for the key named “referent”, that’s also known as the credential_id that will be used later on. In my case, it’s bfc60c27-a632–40f1–8fa4–4edcdf91ba88 as shown in line 4.

figure 7 — Credential details

You can now call a POST API named: /present-proof/records/{pres_ex_id}/send-presentation on the holder’s agent. The JSON body is quite long, you could quickly copy the sample body from the holder agent’s Open API (figure 8).

figure 8— API for sending a credential proof

The bit we need to change in the JSON sample body are mainly the key/value pair as shown below.

“requested_attributes”: this key can have one or more key/value objects that show how a holder can specify what credentials s/he believes can fulfil the credential attribute request in the credential proof request.

As we know the holder does have a credential that has an attribute named “first name”. Below shows an example, the sub key named additionalProp1 is obtained from the request as shown in line 7 in figure 3. In response to this request, we put the credential id we’ve obtained in line 4 in figure 7. Also put a true value to “revealed” means the holder agrees to reveal this credential.

“requested_attributes”: {    “additionalProp1”: {        “cred_id”: “bfc60c27-a632–40f1–8fa4–4edcdf91ba88”,        “revealed”: true     }}

“requested_predicates”: this key can have one or more key/value objects that how a holder can specify what credentials s/he can fulfil the predicate part in the credential proof request.

Since the holder’s credential also has an age that shows s/he is 14 years-old that can fulfil the predicate request — over 10 years-old. Below shows an example, the sub key named additionalProp2 is obtained from the request as shown in line 13 in figure 3. The value for the time stamp is the same as the proof request as shown in line 23 in figure 3.

“requested_predicates”: {     “additionalProp2”: {         “cred_id”: “bfc60c27-a632–40f1–8fa4–4edcdf91ba88”,         “timestamp”: 1632155444     }}

Eventually, the final payload looks like figure 9.

figure 9 — JSON body payload for revealing the credential proof in the holder’s agent

When calling this API, remember to replace {pres_ex_id} in the api with the right value. In my case, the value is 29cda5c5-a877–4bc4–9369–2dad925e2c57 as shown in line 32 in figure 6.

Once successful, a very long JSON payload will be returned. The key message we want to check is its state as shown in figure 10. It indicates a presentation is sent.

figure 10 — JSON response after revealing the credential proof in the holder’s agent

Step 3: Verifier verifies credential proof

You can now call a GET API named: /present-proof/records on the verifier’s agent. We can see a very long JSON response here. The state attribute in line 2621 shows its value as “presentation_received” (see figure 11). This tells us a presentation is available in the verifier’s agent. Note down the value for the attribute named “presentation_exchange_id” here (6b6de1b6–537e-44b8-aaa6–5869e9c8e305 in line 2619 in my case).

figure 11 — JSON response shows a credential proof as a presentation is received in the verifier’s agent

You can now call a POST API named:
​/present-proof​/records​/{pres_ex_id}​/verify-presentation (see figure 12).

figure 12 — API call to verify a presented credential proof

Once successful, a long JSON payload will be returned, but we only want to find an attribute named “state” with its value “verified” (see figure 13).

figure 13 — Credential Proof verification has succeeded

Conclusion

This blog shows ACA-Py’s (V0.6.0) current capability of ZKP and how a verifier can request and verify a credential proof from a holder in a happy-path scenario. Obviously, scenarios such as verification failure will also happen in reality, but this will be left to a reader to figure out by him/herself as by following this tutorial, one should be already familiar with the APIs in Swagger. This part concludes this blog series. In the future, some advanced topics related to ACA-Py will be presented. Hope to see you there soon.

--

--

Dr. Yunxi Zhang

Dr. Zhang works as a Tech Arch at Accenture. His interests cover Enterprise System Architecture, DLT, Cloud Services and DevOps.