This application was deprecated on March 14th 2024, there will be no further dependency or security updates.
Four-agent-based proof of concept SSI system for Veritable.
This project is a four-agent-based Self-Sovereign Identity ( SSI ) proof of concept ( PoC ). Each Agent has a distinct role: Issuer
, Holder
, Verifier
and Authority
. This is similar to the standard three-agent SSI model, with the addition of a fourth Authority
role that both issues and verifies credentials.
Issuer
to issue digital credentials.Holder
to hold cryptographic material in a safe place and countersigns any identity proofs.Verifier
to send proof requests to the holder and cryptographically verify those proofs, after receiving them.Authority
to receive proofs from the holder, cryptographically verify those proofs, and then issues further credentials.
The 4 GUIs that can be viewed : | ||
---|---|---|
# | Type & Alias | Link |
1 | Issuer - Consortiq (Pilot Trainer) | localhost:3002 |
2 | Holder - Alice (Drone Pilot) | localhost:3001 |
3 | Verifier - Airops (Airside Ops) | localhost:3003 |
3 | Authority - CAA | localhost:3004 |
The Explorer for the underlying DLT that can be viewed with : | ||
---|---|---|
# | Alias | Link |
NA | Von Explorer | localhost:9000 |
Note: The PoC application shown here, is ideal for demonstration purposes only. Ideally, this codebase should be accompanied by a proper SSI slide-deck presentations and should not be used in production environments, nor similar projects.
For e2e testing we are using Cypress
npm package. Cypress config and tests can be found in ./cypress
folder. Test flows or Cypress specs are located in /cypress/integration
folder. Each spec should represent a flow e.g.
- creating a connection with authority
- requesting proof
- issues a credential
In order to run them locally this will require all services including acapy agents and react clients and Cypress installed along with cypress.env.json file.
Create a new file at the root of this project cypress.env.json
. And specify the below variables
{
"holder_username": "username",
"holder_password": "password",
"holder_url": "http://localhost:3001",
"issuer_url": "http://localhost:3002",
"verifier_url": "http://localhost:3003",
"authority_url": "http://localhost:3004"
}
Start agents and other dependencies
./scripts/start.sh
Running tests locally
./scripts/e2e.sh
The agents are differentiated by different themes. Each are built with different colour, fonts and logo-type symbols.
The Decentralized Ledger Tech component ( DLT ) behind the scene is built from four different DLT validator nodes, all of them created using von-network ( which in turn uses Hyperledger Indy ) which also includes a simple DLT web Explorer, available on port 9000 ( as highlighted above ).
As long as the demo runs in a normal operational mode, only transactions showing information about the creation of credential schemas / credential definition will be visible in the ledger. As a side note, the DLT will include a few NYM transactions at the beginning of the ledger, transactions which carry the NYM information of all the major parties involved. All of those will be there as a result of the Aries Cloudagent Agent ( ACA ) python layer booting up. In this case, we are using, a modified ACA called veritable-aries-cloudagent, detailed below. Everything else, will be off-chain.
The schema, together with the definition, is one of the foundational cryptographic artifacts of the trusted and interoperable SSI system. This is, essentially, the template which encapsulates all the fields required for a particular credential, with rules about how every field should look like, and what field should be encrypted / not encrypted, and in what way. It contains the following fields:
- Flyer Id (e.g.: GBR-RP-1);
- Name (e.g: Alice);
- Surname (e.g: Smith);
- Certificate Title (e.g: Unmanned Aircraft Systems);
- Certificate Subtitle (e.g: Drone Pilot Certificate of Competence);
- Expiration Date (e.g.: 01/01/2030).
- Type (e.g: A2 Open Category)
Note that, as mentioned before, no credential / verification will be stored on the blockchain and, for that reason, a peer to peer connection needs to be created between Consortiq and Alice, for credential creation, and then a second one needs to be created between Airops and Alice for proof requests / verifications.
For privacy purposes, it is unwise for Alice to announce her identity on the blockchain, therefore a peer to peer connection invitation, in a DID Communication ( described in this Medium article ), should be created by the company ( in a business to consumer scenario ) and handed over to the user, to finally establish the encrypted connection. For that reason, it is important to first use the Consortiq GUI to create the invitation, then use the Pilot GUI to receive it, and finally use the Airops GUI to create the other invitation plus the Pilot GUI to finalise the process.
Once all the parties are connected, the creation of multiple credentials will be possible, along with the ability to verify them, based on a set of five fields ( ID, Name, Surname, Type and Valid at least until ). The first four fields must be exactly equal to what the Pilot has in her wallet, otherwise the verification will FAIL. The last field uses a function that compares integer numbers and, for that reason, as long as the date where you perform the verification converted to a number (or whatever is inside that field) is less or equal to the expiration date, the verification will show PASS. This feature is designed to provide an easy way for the verifier to ensure the certificate is still within its expiry date, for the duration of the work undertaken. However, here instead of passing the date in clear text, we have implemented the solution as a zero-knowledge-proof system. This means, when Airops passes the proof presentation request to Alice, the holder's wallet passes a cryptographic proof that their expiry date comes after the data provided by Heathrow, without revealing what that underlying expiry date is.
Note that during the verification step, the peer to peer connection between Consortiq and Alice is not needed, therefore, one can use the Disconnect button to drop the connection between those two. The key takeaway is the fact that the Verifier can get all the information needed, for the verification, from the Holder and the underlying Hyperledger Indy ledger itself.
In terms of software requirements, Docker version 20.10.11 or higher would be highly recommended to have ( use sudo apt-get install docker-ce
or brew cask install docker
).
It goes without saying that DockerCompose should also be present, as in, it is highly recommended to have compose version 1.29.2 or higher ( download it and install it manually or from your terminal with a command like sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
).
That is needed for the backend, for the frontend, Node is needed, ideally NodeJs version 14.17.1 or higher ( sudo apt install nodejs
or brew install node
).
Before moving to requirements related to the frontend, another extra small dependency is required, called JQ, the widely-used command-line JSON parser (used by the Aries Python Cloudagent), ideally v1.6 or higher ( just use sudo apt install -y jq
or brew install jq
to install it ).
All the npm packages will be installed, automatically, when starting the project ( ./scripts/start.sh
), if the node modules folder is not present, as in, if this folder can't be found inside veritable-poc-agents (if there are any issues running this project, one solution would be to delete this folder and start again) .
Just for the record, the following npm packages will be installed ( all other backend dependencies are virtualised ): testing-library/jest-dom^5.14.1
; testing-library/react^11.2.7
; testing-library/user-event^12.8.3
; react^17.0.2
; react-dom^17.0.2
; react-json-view^1.21.3
; react-scripts4.0.3
.
In order to start the application, simply run the included shell script:
./scripts/start.sh
Similarly, to stop everything, use the included shell script ( stop.sh ).
Last, but not least, in case there is a need of a restart, us the restart script ( restart.sh ).
This section speaks about how to go about demoing the SSI fundamentals ( communication / ID creation / ID verification ), as in, what is the recommended sequence of commands to follow, when demonstrating this SSI proof of concept to others.
First Part: Definition Creation Alongside Schema Creation and Credential Creation
The goal of this part is to show, after creating a DID Communication channel between Consortiq and Alice, how to create a set of credentials together with how to create a credential schema plus definition.
To begin, we assume that you already have the backend up and running activated with ./scripts/start.sh
( the Indy-based VON network plus the Aries agent Python system ). As it stands, the current DLT network is made out of virtual nodes that sit on the same local machine but, ultimately, these will be run by trusted members of the aviation ecosystem.
You can demonstrate that the underlying ledger is up and that the four validator nodes are operational by displaying the DLT Explorer in a new tab and by browsing through a few transactions ( localhost:9000 and localhost:9000/browse/domain ).
If you haven't done so already, open the 1st GUI in a new tab ( http://localhost:3001 ) and let it use its own pre-configured endpoint ( Switch to CustomEndpoint - 8021
); open the 2nd GUI ( http://localhost:3002 ) and let this one also use its endpoint ( Switch to CustomEndpoint
); and, finally open the 3rd GUI ( http://localhost:3003 ) and similarly let it use its own pre-configured url ( Switch to CustomEndpoint
) and same applies to last but not least 4th GUI ( http://localhost:3004 ) .
-
Let's start with the creation of the overall credentials structure. In this example, we're allowing the training company ( Drone Training Ltd ) to set the two elements needed for this structure, that is, the credential schema and the credential definition, but in the future, this would be the Civil Aviation Authority ( CAA ) or another suitable authority.
-
The following steps are then required, in the Issuer's browser tab, as in Consortiq's GUI:
Issuer
creates a new credential schema by clicking theCreate
button next theSelect Schema:
list;Issuer
selects the newly schema and then creates the definition by clicking theCreate
button next to theSelect (Cred) Definition:
list;Issuer
selects the newly created definition from the list;Issuer
shows the schema and definition details appearing on the blockchain by opening the DLT Explorer.
-
-
Now, along comes someone who has just been trained. We'll call this person
Alice
. They first need to connect their agent (Holder
agent ) to the drone training company (Issuer
agent ) with the help of a separate off-chain direct p2p connection. This digital handshake would normally take place with a QR code and mobile phones, but here we're using two simple web based interfaces.-
The following steps are required, in the
Issuer
view:Issuer
creates the communication invitation by clicking the+
icon located just under the profile icon and then by hitting the+ Create Invitation
button;Issuer
copies the newly generated invitation string that just materialised under the Create Invitation button;Issuer
gives the invitation string toHolder
.
-
After that, the following steps are required, in the
Holder
view:Holder
takes string which represents fromIssuer
and opens the connection form by clicking the+
icon located under the profile icon;Holder
puts the string in the bottom field next to the second button by using the paste option;Holder
clicks button at the bottom of the form calledReceive Invitation
then waits for the information to go trough;Holder
shows the newly achieved connection by showing the connection counter (1 Connection(s)
) found on the left of theHandshake
icon or by clicking the counter or the hands icon.
-
-
Now the training company gives
Alice
(Holder
) her digital credential to prove she's been trainer to fly.-
The following steps in the
Issuer
are required:Issuer
fills in theFlyer Id
field (GBR-RP-1
);Issuer
fills in theCertificate Title
field (Unmanned Aircraft Systems
);Issuer
fills in theName
field (Alice
);Issuer
fills in theCertificate Subtitle
field (Drone Pilot Certificate of Competence
);Issuer
fills in theSurname
field (Smith
);Issuer
fills in theExpiration Date (dd/mm/yyyy)
field ( a date into the future );Issuer
fills in theType
field (A2 Open Category
).
-
After that, the next steps are required, in the
Holder
view:Issuer
creates the communication invitation by clicking the+
icon located just under the profile icon and then by hitting the+ Create Invitation
button;Issuer
copies the newly generated invitation string that just materialised under the Create Invitation button the first field of the connection form;Issuer
gives the invitation string toHolder
.
-
Second Part: Proof Presentation Verification
In the second, and last part, we assume that the issuance of credentials, from the previous part, has been taken care of and Alice already owns at least one set of credentials in her wallet ( the DID Comm p2p connection between the Holder
and the Issuer
is redundant and could be dropped ).
Here, in this part, Alice
( Holder
) wants to fly her drone at Heathrow Airport
. Heathrow Airops must therefor verify Alice's credentials. In a traditional setting, they would either have to trust the credential presented at face value or phone home to the original issuer for authenticity confirmation. With SSI, this process can be streamlined, meaning that only a short-lived connection between Verifier
and Holder
is needed for virtually any type of check.
-
Similar to the previous step, Alice needs a to perform a digital handshake, as such the following steps are required:
-
As such, the following steps are required in the
Verifier
view:Verifier
creates the communication invitation by clicking the+
icon located just under the profile icon and then by hitting the+ Create Invitation
button;Verifier
copies the newly generated invitation string that just showed up under the Create Invitation button;Verifier
gives the invitation string toHolder
.
-
After that, the following steps are also required, in the
Holder
view:Holder
takes string which represents fromVerifier
and opens the connection form by clicking the+
icon located under the profile icon;Holder
puts the string in the bottom field next to the second button by using the paste option;Holder
clicks button at the bottom of the form calledReceive Invitation
then waits for the information to go trough;Holder
shows the newly achieved connection by showing the connection counter (2 Connection(s)
) found on the left of theHandshake
icon or by clicking the counter or the hands icon.
-
-
Assuming the connection is done, we can focus on the final part of the workflow which is divided in two steps. The Verifier sends a direct request to the Holder's wallet for a cryptographic proof presentation of her credentials.
-
For requesting a proof presentation of Alice's credentials, the following steps are required, in the
Verifier
view:Verifier
selects from theVerification Form
list the second option after Select (Verification Form 1.0
);Verifier
keeps the date field as today's date or a day which before the expiry date (DD/MM/YYYY
);Verifier
fills in theFlyer Id
field (GBR-RP-1
);Verifier
fills in theName
field (Alice
);Verifier
fills in theSurname
field (Smith
);Verifier
fills in theType
field (A2 Open Category
);Verifier
clicks on theSend Proof Req
button;Verifier
shows the fact that the information exchange has been recorded and logged and available on the right under a randomly generatedExchange Id
.
-
Alice's wallet is configured to accept any proof requests from known parties, therefore, the following single step is required, in the
Holder
view:Holder
shows that the presentation request has been recorded and logged on the right hand side under a randomly generatedExchange Id
.
-
-
Now, with the cryptographic signed representation of Alice's certificate, which includes the
Zero-Knowledge Proof
that the expiry date is less than or equal to the selected date, the Verifier can independently verify the signature.-
The Verifier's Agent can only verify the information received from Alice because after that the information will be discarded from the agent's memory, therefore the following steps are needed, in the
Verifier
view:Verifier
selects the correct Id from theVerify the received presentation list
(ID corresponding to what's in the logs column
);Verifier
clicks on theVerify
button;Verifier
shows the success message from the final popup (Verification: PASS
);Verifier
refreshes the browser page;Verifier
shows a counter example the where expiry date represented as an integer is too high or where theName
,Surname
orFlyer ID
is wrong.Verifier
shows the error message from the final popup (Verification: FAIL
).
-
The verification could be streamlined with cameras and QR codes or similar but for simplicity, in this project, like in previous examples, we are using a web form for manual data capture.
In real-world implementation this could have further checks to ensure the drone company was authenticated, but for now we're showing basic functionality.
Now, everything is approved and Alice is ready to fly her drone.
The table below, shows all the backend containerised services, assuming the system is running in normal operational mode ( from docker ps
).
IMAGE | PORTS | NAMES |
---|---|---|
bcgovimages/aries-cloudagent | 0.0.0.0:8051->8002/tcp | veritable-cloudagent-authority |
bcgovimages/aries-cloudagent | 0.0.0.0:8041->8002/tcp | veritable-cloudagent-verifier |
bcgovimages/aries-cloudagent | 0.0.0.0:8031->8002/tcp | veritable-cloudagent-holder |
bcgovimages/aries-cloudagent | 0.0.0.0:8021->8002/tcp | veritable-cloudagent-issuer |
von-network-base | 0.0.0.0:9000->8000/tcp | von_webserver_1 |
von-network-base | 0.0.0.0:9701-9702->9701-9702/tcp | von_node1_1 |
von-network-base | 0.0.0.0:9703-9704->9703-9704/tcp | von_node2_1 |
von-network-base | 0.0.0.0:9705-9706->9705-9706/tcp | von_node3_1 |
von-network-base | 0.0.0.0:9707-9708->9707-9708/tcp | von_node4_1 |
The table below, shows information about the central frontend GUI web service ( it is important to note, here, this service is not containerised ).
# | SERVICE | COMMAND | PORTS | HOST | REPOSITORY |
---|---|---|---|---|---|
Holder | React development server | npm start | 3001 | holder | holder |
Issuer | React development server | npm start | 3002 | issuer | issuer |
Verifier | React development server | npm start | 3003 | verifier | verifier |
Authority | React development server | npm start | 3004 | authority | authority |
To use the tests executable that was proved together with this project, change the working folder to the appropriate one (the folder that holds the script that runs all the tests):
cd tests-agent/
After that, just commence the run shell script:
./run.sh
The script will go trough all the previously mentioned steps, one by one, to test them all, without interacting with the frontend ( agent DID communication
, credentials schema
creation, credentials definition
creation, credential
creation, creating requests for proofs
and proof verifications
).
This shell script will automatically install all the npm dependencies ( npm i
) prior to starting. Here, we are talking only about node-fetch^2.5.0
.
If this script runs correctly, in theory the frontend should also run without issues.
For this section, please check the README-veritable-poc-agents.md file.
In simple terms, the system architecture diagram looks is the one below.
┌──────────────────────────────────────────────────────────────────────────────────────────────┐
│ ReactJS Generic Interface w/ 3 themes (Theme01, 02, 03 for Agent01, 02, 03) │
│ Host: localhost:3000 │
│ localhost:3000/?#1 (Endpoint1) localhost:3000/?#2 (Endpoint2) localhost:3000/?#3 (Endpoint3) │
└──────────────────────────────────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ │ ─────────► │ │ ─────────► │ │
│ Agent01 (ACA Agent) │ │ Agent02 (ACA Agent) │ │ Agent03 (ACA Agent) │
│ Host: localhost:8021 │ │ Host: localhost:8031 │ │ Host: localhost:8041 │
│ AgentRole: Issuer │ │ AgentRole: Holder │ │ AgentRole: Verifier │
│ │ ◄───────── │ │ ◄───────── │ │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────────────────────────────────────────────────┐
│ (Dashboard: localhost:9000) │
│ HyperLedger Indy DLT │
│ Validated by 4 VON nodes │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ │ ───► │ │ ───► │ │ ───► │ │ │
│ │ Node01 │ │ Node01 │ │ Node01 │ │ Node01 │ │
│ │ │ │ │ │ │ │ │ │
│ │ localhost:9701 │ ◄─── │ localhost:9701 │ ◄─── │ localhost:9701 │ ◄─── │ localhost:9701 │ │
│ │ │ │ │ │ │ │ │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ └────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────┘
Another aspect. that needs to be highlighted, is the way the frontend is programmed to communicate with the backend, which has a high degree of flexibility.
One can run the backend on a different machine ( with any custom IP address or port number ) than the frontend machine. In theory, the backend could be uploaded on an on-line machines or multiple machines.
All you need to do to connect to your custom backend is: when you open the GUI, instead of clicking Switch to CustomEndpoint
, select the Dev
option, fill in the Custom Endpoint - UserDefined
with your custom endpoint URL and hit Switch to Custom
, that's it.
To better understand the structure of the React application you can browse the following component diagrams.
All the React components / sub-components / and so on, in this project are developed using the folders-as-components methodology ( this methodology of creating components is described in detail here in this NodeJsOrg article ).
That means that every existing React component here has its own folder with an index.js file inside and the component itself. This makes importing components more elegant. In addition, certain components are grouped inside folders and sub-folders, as highlighted above.
It is highly recommended to keep the same method of creating new components, for consistency.
Steps required to run the underlying ( Indy-based ) VON Network:
von-network / docs / UsingVONNetwork.md
This git submodule is configured to just point to the official repository:
https://github.com/bcgov/von-network/blob/main/docs/UsingVONNetwork.md
When it comes to the topic of license, please refer the LICENSE
file placed in this project here, for all the related info.