In part 1 I gave an introduction to the terms used in the Self-Sovereign Identity space. In part 2 I explained the tools and command-line arguments for the development environment. In part 3 I set up two agents, and they connect using the invite and request/response protocol. In part 4 I introduced the
go-acapy-client library that allows you to interact with ACA-py from Go. In part 5 credentials got issued over the established connection between the agents. In part 6 I discussed revocation. In this part I am going to create a proof presentation of an issued credential and verify it.
You have received credentials, for example a driver’s license, a passport or your degree. These credentials are not just useful to have, they are useful because your can prove that they are yours. The party that wants to verify your credentials can verify the signatures of the credentials are correct as well.
The Present Proof dance
There are two parties involved: the prover and the verifier
- Prover sends proposal (verifier receives proposal) (this step is optional)
- Verifier sends request (prover receives request)
- Prover sends presentation proof (verifier receives presentation proof)
- Verifier verifies presentation proof
- Verifier sends presentation proof acknowledgement (prover receives presentation proof acknowledgement)
You can read more about the protocol at RFC0037.
Present Proof with
Presenting proof is the most difficult part of Aries, at least in my opinion. There seem to be many possibilities, but the documentation for it is rather scarce.
In part 5 I explained how to issue credentials, and in part 6 I talked about revocation. For presenting proof to work out, you need to create credentials that have the option to be revoked. If the issuer has not set up a revocation registry when the credential definition got created, then the holder cannot send a presentation. When the holder tries to send a presentation, the following error will occur:
400: Error when constructing proof: Error: Invalid structure. Caused by: Revocation Registry Id not found. CommonInvalidStructure.
With that out of the way, let’s take a look at step 2 in the dance, creating a ‘request for presentation’.
Let’s go over the fields.
ConnectionID is the connection you want to request a presentation proof from.
Comment is the text you can send with the request that can be displayed to the user.
ProofRequest is constructed using a name (“Please prove to me that you have these”), a nonce (“1234567890”), the requested predicates, the requested attributes, a version number, and a time interval within which the attributes should be valid.
What the value of the nonce should be, or how to generate it, is not yet clear to me.
The requested attributes are constructed like:
A couple of things to note here. First, you can either use
Names, but not both. When you use
Names, you are required to add
Restrictions can have a couple of values. So far I have found:
The Swagger documentation describes:
go-acapy-client library supports all the keys except for the last one. The last key looks like WQL, but I have yet to confirm if that is enforced.
These restrictions are sent to the prover, who can find credentials that match the restrictions, and based on those send a proof. So far it doesn’t look like the prover is checking these restrictions, it might be that the verifier will verify the restriction.
Second, the keys used in the
requestedAttributes, can be chosen freely. These are the keys that the prover will use when he responds with a presentation.
Third, both the
acapy.ProofRequest and the individual requested attributes have a
NonRevoked field. When a proof presentation is created by the prover, it will check for each attribute if it is valid in the specified
NonRevoked time interval. It will first check if the individual requested attribute has a
NonRevoked field, if it has not, it will use the
ProofRequest.NonRevoked value. If both don’t have a
NonRevoked specified, then no time interval is taken into account.
Fourth, if the
NonRevoked time interval is before the revocation registry has been created, then the prover will face an error when constructing a proof:
That’s about it for the requested attributes, now let’s take a look at the requested predicates.
Again the same rules apply to using
Name exclusive or with
Restrictions being required when using
Names. The same rules about
NonRevoked overriding the
NonRevoked of the presentation request itself.
There are two extra fields here, the
PType and the
PValue. They can be used for requesting attributes with rules for the value. For example, a predicate can define that the attribute ‘age’ should have a value greater than or equal to ‘18’. There are four predicate-types available:
Constructing a Presentation Proof
After receiving a presentation request, a presentation proof can be constructed.
The attributes that go into a presentation proof are directly linked to the presentation request. For example, if the presentation request has a restriction on the
CredentialDefinitionID, then the prover needs to find a credential in its wallet that matches the
Matching credentials can also be retrieved by using the third parameter (
client.GetCredentials(10, 0, ""). You can read more about WQL in a previous blog post.
Revealed value needs to be
true to reveal the value in the proof. When the attribute is not revealed, the following error will show up:
I haven’t looked into the predicates and self-attested attributes yet, Aries RFC0037 describes a lot more detail that I haven’t used yet. I’ll take a look into that in a later stage.
Verifying Presentation Proof
The verification of a presentation proof is relatively straight-forward:
When the presentation is verified, an update will be sent to the prover that the presentation has been acknowledged.
Development and debugging
There are a couple of parameters available to automate the steps in this process. They are
--auto-verify-presentation. They automated the steps that I described. The parameter
--debug-presentations can be used to print extra output for debugging the presentations.
These proofs require a connection to be established beforehand. But what if there is no connection yet? Let’s say you are at a bar and need to prove that you are above the legal drinking age? In that case a connectionless proof presentation can be made.
To do that, first a request has to be created using:
client.CreatePresentationRequest(...). The resulting json should be base64 encoded and attached in a request at
~service object is required for the prover to know how to contact the verifier.
This object needs to be transformed into a QR code which can be scanned by the verifier. One problem with that is that the base64 encoded proof can become quite large, and there is a limit to the amount of data that can be represented in a QR code. There are two solutions to this.
The first option is, instead of creating a QR code that contains the data, a URL can be constructed with the connectionless proof data as a base64 encoded query parameter:
The second option is to store the data in a database and to make it accessible using a unique identifier. Accessing the URL would retrieve the data from the database and return it as json.
Aries RFC0434 describes the process of using these out-of-band messages. It also raps about url shortening as described in the second option.
There is no functionality for connectionless proofs or other out-of-bound messages in
Constructing a presentation proposal and a presentation proof is not the most straight-forward part of Aries. I have described a simple process with simple attributes and need to discover the other parts later on. Please shoot me a message in case you have any queries or tips.
This is going to be the last blog post in this series, however I will write about the other parts of presenting a proof, new features added to
go-acapy-client, and an issuer and verifier that I’m creating using
go-acapy-client in the future.