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.
Context
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 go-acapy-client
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’.
Presentation Proposal
|
|
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.
The 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 Name
, or Names
, but not both. When you use Names
, you are required to add Restrictions
. The Restrictions
can have a couple of values. So far I have found:
|
|
The Swagger documentation describes:
|
|
The 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 Names
, and 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 CredentialDefinitionID
.
|
|
Matching credentials can also be retrieved by using the third parameter (wql
) of client.GetCredentials(10, 0, "")
. You can read more about WQL in a previous blog post.
The 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-respond-presentation-proposal
, --auto-respond-presentation-request
and --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.
Connectionless Proof
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 request_presentation~attach[0].data.base64
. The ~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 go-acapy-client
yet.
Conclusion
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.