diff --git a/concepts/0167-data-consent-lifecycle/README.md b/concepts/0167-data-consent-lifecycle/README.md
index fcf5029cf..26a6fbe16 100644
--- a/concepts/0167-data-consent-lifecycle/README.md
+++ b/concepts/0167-data-consent-lifecycle/README.md
@@ -26,6 +26,7 @@
* [Proof Request](#proof-request)
* [Performing Proof Request](#performing-proof-request)
* [Certification Revocation](#certification-revocation)
+* [Implementation Reference](#Implementation Reference)
* [Reference](#reference)
* [Annex A: PDP Schema mapping to Kantara Consent Receipt](#annex-a-pdp-schema-mapping-to-kantara-consent-receipt)
* [Prior art](#prior-art)
@@ -410,6 +411,28 @@ These are the steps covered with certification revocation:
- data authority initiated revocation (if owns schema base)
+## Implementation Reference
+
+A python jupyter notebook is available as reference implementation
+to help with implementation. The base for this example is
+getting-started jupyter notebook. In order to run the example take
+the following steps.
+
+1. Clone indy-sdk \
+
+ git clone https://github.com/hyperledger/indy-sdk.git
+2. Copy over following files to doc/getting-started \
+ - [consent-flow.ipynb](./reference-implementation/consent-flow.ipynb)
+ - [docker-compose.yml](./reference-implementation/docker-compose.yml) *
+
+ Note * - Reason for changing the docker-compose.yml is to be able to
+ view consent-flow.ipynb.
+
+3. Ready to start docker-compose \
+
+ docker-compose up
+4. Open html link and run consent-flow.ipynb
+
## Reference
*Provide guidance for implementers, procedures to inform testing,
diff --git a/concepts/0167-data-consent-lifecycle/reference-implementation/consent-flow.ipynb b/concepts/0167-data-consent-lifecycle/reference-implementation/consent-flow.ipynb
new file mode 100644
index 000000000..7276909b3
--- /dev/null
+++ b/concepts/0167-data-consent-lifecycle/reference-implementation/consent-flow.ipynb
@@ -0,0 +1,1025 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import asyncio\n",
+ "import time\n",
+ "from indy import anoncreds, crypto, did, ledger, pool, wallet, blob_storage\n",
+ "\n",
+ "import json\n",
+ "from typing import Optional\n",
+ "import os\n",
+ "\n",
+ "async def onboarding(_from, to):\n",
+ " print(\"\\\"{}\\\" -> Create and store in Wallet \\\"{} {}\\\" DID\".format(_from['name'], _from['name'], to['name']))\n",
+ " (from_to_did, from_to_key) = await did.create_and_store_my_did(_from['wallet'], \"{}\")\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Send Nym to Ledger for \\\"{} {}\\\" DID\".format(_from['name'], _from['name'], to['name']))\n",
+ " await send_nym(_from['pool'], _from['wallet'], _from['did'], from_to_did, from_to_key, None)\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Send connection request to {} with \\\"{} {}\\\" DID and nonce\"\n",
+ " .format(_from['name'], to['name'], _from['name'], to['name']))\n",
+ " connection_request = {\n",
+ " 'did': from_to_did,\n",
+ " 'nonce': 123456789\n",
+ " }\n",
+ "\n",
+ " if 'wallet' not in to:\n",
+ " print(\"\\\"{}\\\" -> Create wallet\".format(to['name']))\n",
+ " try:\n",
+ " await wallet.create_wallet(to['wallet_config'], to['wallet_credentials'])\n",
+ " except IndyError as ex:\n",
+ " if ex.error_code == ErrorCode.PoolLedgerConfigAlreadyExistsError:\n",
+ " pass\n",
+ " to['wallet'] = await wallet.open_wallet(to['wallet_config'], to['wallet_credentials'])\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Create and store in Wallet \\\"{} {}\\\" DID\".format(to['name'], to['name'], _from['name']))\n",
+ " (to_from_did, to_from_key) = await did.create_and_store_my_did(to['wallet'], \"{}\")\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Get key for did from \\\"{}\\\" connection request\".format(to['name'], _from['name']))\n",
+ " from_to_verkey = await did.key_for_did(_from['pool'], to['wallet'], connection_request['did'])\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Anoncrypt connection response for \\\"{}\\\" with \\\"{} {}\\\" DID, verkey and nonce\"\n",
+ " .format(to['name'], _from['name'], to['name'], _from['name']))\n",
+ " to['connection_response'] = json.dumps({\n",
+ " 'did': to_from_did,\n",
+ " 'verkey': to_from_key,\n",
+ " 'nonce': connection_request['nonce']\n",
+ " })\n",
+ " to['anoncrypted_connection_response'] = \\\n",
+ " await crypto.anon_crypt(from_to_verkey, to['connection_response'].encode('utf-8'))\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Send anoncrypted connection response to \\\"{}\\\"\".format(to['name'], _from['name']))\n",
+ " _from['anoncrypted_connection_response'] = to['anoncrypted_connection_response']\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Anondecrypt connection response from \\\"{}\\\"\".format(_from['name'], to['name']))\n",
+ " _from['connection_response'] = \\\n",
+ " json.loads((await crypto.anon_decrypt(_from['wallet'], from_to_key,\n",
+ " _from['anoncrypted_connection_response'])).decode(\"utf-8\"))\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Authenticates \\\"{}\\\" by comparision of Nonce\".format(_from['name'], to['name']))\n",
+ " assert connection_request['nonce'] == _from['connection_response']['nonce']\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Send Nym to Ledger for \\\"{} {}\\\" DID\".format(_from['name'], to['name'], _from['name']))\n",
+ " await send_nym(_from['pool'], _from['wallet'], _from['did'], to_from_did, to_from_key, None)\n",
+ "\n",
+ " return from_to_did, from_to_key, to_from_did, to_from_key, _from['connection_response']\n",
+ "\n",
+ "\n",
+ "async def get_verinym(_from, from_to_did, from_to_key, to, to_from_did, to_from_key):\n",
+ " print(\"\\\"{}\\\" -> Create and store in Wallet \\\"{}\\\" new DID\".format(to['name'], to['name']))\n",
+ " (to_did, to_key) = await did.create_and_store_my_did(to['wallet'], \"{}\")\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Authcrypt \\\"{} DID info\\\" for \\\"{}\\\"\".format(to['name'], to['name'], _from['name']))\n",
+ " to['did_info'] = json.dumps({\n",
+ " 'did': to_did,\n",
+ " 'verkey': to_key\n",
+ " })\n",
+ " to['authcrypted_did_info'] = \\\n",
+ " await crypto.auth_crypt(to['wallet'], to_from_key, from_to_key, to['did_info'].encode('utf-8'))\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Send authcrypted \\\"{} DID info\\\" to {}\".format(to['name'], to['name'], _from['name']))\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Authdecrypted \\\"{} DID info\\\" from {}\".format(_from['name'], to['name'], to['name']))\n",
+ " sender_verkey, authdecrypted_did_info_json, authdecrypted_did_info = \\\n",
+ " await auth_decrypt(_from['wallet'], from_to_key, to['authcrypted_did_info'])\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Authenticate {} by comparision of Verkeys\".format(_from['name'], to['name'], ))\n",
+ " assert sender_verkey == await did.key_for_did(_from['pool'], _from['wallet'], to_from_did)\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Send Nym to Ledger for \\\"{} DID\\\" with {} Role\"\n",
+ " .format(_from['name'], to['name'], to['role']))\n",
+ " await send_nym(_from['pool'], _from['wallet'], _from['did'], authdecrypted_did_info['did'],\n",
+ " authdecrypted_did_info['verkey'], to['role'])\n",
+ "\n",
+ " return to_did\n",
+ "\n",
+ "\n",
+ "async def send_nym(pool_handle, wallet_handle, _did, new_did, new_key, role):\n",
+ " nym_request = await ledger.build_nym_request(_did, new_did, new_key, None, role)\n",
+ " await ledger.sign_and_submit_request(pool_handle, wallet_handle, _did, nym_request)\n",
+ "\n",
+ "\n",
+ "async def send_schema(pool_handle, wallet_handle, _did, schema):\n",
+ " schema_request = await ledger.build_schema_request(_did, schema)\n",
+ " await ledger.sign_and_submit_request(pool_handle, wallet_handle, _did, schema_request)\n",
+ "\n",
+ "\n",
+ "async def send_cred_def(pool_handle, wallet_handle, _did, cred_def_json):\n",
+ " cred_def_request = await ledger.build_cred_def_request(_did, cred_def_json)\n",
+ " await ledger.sign_and_submit_request(pool_handle, wallet_handle, _did, cred_def_request)\n",
+ "\n",
+ "\n",
+ "async def get_schema(pool_handle, _did, schema_id):\n",
+ " get_schema_request = await ledger.build_get_schema_request(_did, schema_id)\n",
+ " get_schema_response = await ledger.submit_request(pool_handle, get_schema_request)\n",
+ " return await ledger.parse_get_schema_response(get_schema_response)\n",
+ "\n",
+ "\n",
+ "async def get_cred_def(pool_handle, _did, cred_def_id):\n",
+ " get_cred_def_request = await ledger.build_get_cred_def_request(_did, cred_def_id)\n",
+ " get_cred_def_response = await ledger.submit_request(pool_handle, get_cred_def_request)\n",
+ " return await ledger.parse_get_cred_def_response(get_cred_def_response)\n",
+ "\n",
+ "\n",
+ "async def get_credential_for_referent(search_handle, referent):\n",
+ " credentials = json.loads(\n",
+ " await anoncreds.prover_fetch_credentials_for_proof_req(search_handle, referent, 10))\n",
+ " return credentials[0]['cred_info']\n",
+ "\n",
+ "\n",
+ "async def prover_get_entities_from_ledger(pool_handle, _did, identifiers, actor):\n",
+ " schemas = {}\n",
+ " cred_defs = {}\n",
+ " rev_states = {}\n",
+ " for item in identifiers.values():\n",
+ " print(\"\\\"{}\\\" -> Get Schema from Ledger\".format(actor))\n",
+ " (received_schema_id, received_schema) = await get_schema(pool_handle, _did, item['schema_id'])\n",
+ " schemas[received_schema_id] = json.loads(received_schema)\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Get Credential Definition from Ledger\".format(actor))\n",
+ " (received_cred_def_id, received_cred_def) = await get_cred_def(pool_handle, _did, item['cred_def_id'])\n",
+ " cred_defs[received_cred_def_id] = json.loads(received_cred_def)\n",
+ "\n",
+ " if 'rev_reg_seq_no' in item:\n",
+ " pass # TODO Create Revocation States\n",
+ "\n",
+ " return json.dumps(schemas), json.dumps(cred_defs), json.dumps(rev_states)\n",
+ "\n",
+ "\n",
+ "async def verifier_get_entities_from_ledger(pool_handle, _did, identifiers, actor):\n",
+ " schemas = {}\n",
+ " cred_defs = {}\n",
+ " rev_reg_defs = {}\n",
+ " rev_regs = {}\n",
+ " for item in identifiers:\n",
+ " print(\"\\\"{}\\\" -> Get Schema from Ledger\".format(actor))\n",
+ " (received_schema_id, received_schema) = await get_schema(pool_handle, _did, item['schema_id'])\n",
+ " schemas[received_schema_id] = json.loads(received_schema)\n",
+ "\n",
+ " print(\"\\\"{}\\\" -> Get Credential Definition from Ledger\".format(actor))\n",
+ " (received_cred_def_id, received_cred_def) = await get_cred_def(pool_handle, _did, item['cred_def_id'])\n",
+ " cred_defs[received_cred_def_id] = json.loads(received_cred_def)\n",
+ "\n",
+ " if 'rev_reg_seq_no' in item:\n",
+ " pass # TODO Get Revocation Definitions and Revocation Registries\n",
+ "\n",
+ " return json.dumps(schemas), json.dumps(cred_defs), json.dumps(rev_reg_defs), json.dumps(rev_regs)\n",
+ "\n",
+ "\n",
+ "async def auth_decrypt(wallet_handle, key, message):\n",
+ " from_verkey, decrypted_message_json = await crypto.auth_decrypt(wallet_handle, key, message)\n",
+ " decrypted_message_json = decrypted_message_json.decode(\"utf-8\")\n",
+ " decrypted_message = json.loads(decrypted_message_json)\n",
+ " return from_verkey, decrypted_message_json, decrypted_message"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "pycharm": {}
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Getting started -> started\n",
+ "=== 1/9: Open Ledger ==\n",
+ "Open Pool Ledger: pool1\n",
+ "==============================\n",
+ "== 2/9: Setup Steward ==\n",
+ "=== Getting Trust Anchor credentials for Faber, Acme, Thrift and Government ==\n",
+ "------------------------------\n",
+ "\"Sovrin Steward\" -> Create wallet\n",
+ "\"Sovrin Steward\" -> Create and store in Wallet DID from seed\n",
+ "==============================\n",
+ "== 3/9: Onboarded Goverment ==\n",
+ "== Getting Trust Anchor credentials - Government Onboarding ==\n",
+ "------------------------------\n",
+ "\"Sovrin Steward\" -> Create and store in Wallet \"Sovrin Steward Government\" DID\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Sovrin Steward Government\" DID\n",
+ "\"Sovrin Steward\" -> Send connection request to Government with \"Sovrin Steward Government\" DID and nonce\n",
+ "\"Government\" -> Create wallet\n",
+ "\"Government\" -> Create and store in Wallet \"Government Sovrin Steward\" DID\n",
+ "\"Government\" -> Get key for did from \"Sovrin Steward\" connection request\n",
+ "\"Government\" -> Anoncrypt connection response for \"Sovrin Steward\" with \"Government Sovrin Steward\" DID, verkey and nonce\n",
+ "\"Government\" -> Send anoncrypted connection response to \"Sovrin Steward\"\n",
+ "\"Sovrin Steward\" -> Anondecrypt connection response from \"Government\"\n",
+ "\"Sovrin Steward\" -> Authenticates \"Government\" by comparision of Nonce\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Government Sovrin Steward\" DID\n",
+ "==============================\n",
+ "== Getting Trust Anchor credentials - Government getting Verinym ==\n",
+ "------------------------------\n",
+ "\"Government\" -> Create and store in Wallet \"Government\" new DID\n",
+ "\"Government\" -> Authcrypt \"Government DID info\" for \"Sovrin Steward\"\n",
+ "\"Government\" -> Send authcrypted \"Government DID info\" to Sovrin Steward\n",
+ "\"Sovrin Steward\" -> Authdecrypted \"Government DID info\" from Government\n",
+ "\"Sovrin Steward\" -> Authenticate Government by comparision of Verkeys\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Government DID\" with TRUST_ANCHOR Role\n",
+ "==============================\n",
+ "== 4/9: Onboarded Faber ==\n",
+ "== Getting Trust Anchor credentials - Faber Onboarding ==\n",
+ "------------------------------\n",
+ "\"Sovrin Steward\" -> Create and store in Wallet \"Sovrin Steward Faber\" DID\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Sovrin Steward Faber\" DID\n",
+ "\"Sovrin Steward\" -> Send connection request to Faber with \"Sovrin Steward Faber\" DID and nonce\n",
+ "\"Faber\" -> Create wallet\n",
+ "\"Faber\" -> Create and store in Wallet \"Faber Sovrin Steward\" DID\n",
+ "\"Faber\" -> Get key for did from \"Sovrin Steward\" connection request\n",
+ "\"Faber\" -> Anoncrypt connection response for \"Sovrin Steward\" with \"Faber Sovrin Steward\" DID, verkey and nonce\n",
+ "\"Faber\" -> Send anoncrypted connection response to \"Sovrin Steward\"\n",
+ "\"Sovrin Steward\" -> Anondecrypt connection response from \"Faber\"\n",
+ "\"Sovrin Steward\" -> Authenticates \"Faber\" by comparision of Nonce\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Faber Sovrin Steward\" DID\n",
+ "==============================\n",
+ "== Getting Trust Anchor credentials - Faber getting Verinym ==\n",
+ "------------------------------\n",
+ "\"Faber\" -> Create and store in Wallet \"Faber\" new DID\n",
+ "\"Faber\" -> Authcrypt \"Faber DID info\" for \"Sovrin Steward\"\n",
+ "\"Faber\" -> Send authcrypted \"Faber DID info\" to Sovrin Steward\n",
+ "\"Sovrin Steward\" -> Authdecrypted \"Faber DID info\" from Faber\n",
+ "\"Sovrin Steward\" -> Authenticate Faber by comparision of Verkeys\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Faber DID\" with TRUST_ANCHOR Role\n",
+ "Create blob storage\n",
+ "==============================\n",
+ "== 5/9: Onboarded Acme ==\n",
+ "== Getting Trust Anchor credentials - Acme Onboarding ==\n",
+ "------------------------------\n",
+ "\"Sovrin Steward\" -> Create and store in Wallet \"Sovrin Steward Acme\" DID\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Sovrin Steward Acme\" DID\n",
+ "\"Sovrin Steward\" -> Send connection request to Acme with \"Sovrin Steward Acme\" DID and nonce\n",
+ "\"Acme\" -> Create wallet\n",
+ "\"Acme\" -> Create and store in Wallet \"Acme Sovrin Steward\" DID\n",
+ "\"Acme\" -> Get key for did from \"Sovrin Steward\" connection request\n",
+ "\"Acme\" -> Anoncrypt connection response for \"Sovrin Steward\" with \"Acme Sovrin Steward\" DID, verkey and nonce\n",
+ "\"Acme\" -> Send anoncrypted connection response to \"Sovrin Steward\"\n",
+ "\"Sovrin Steward\" -> Anondecrypt connection response from \"Acme\"\n",
+ "\"Sovrin Steward\" -> Authenticates \"Acme\" by comparision of Nonce\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Acme Sovrin Steward\" DID\n",
+ "==============================\n",
+ "== Getting Trust Anchor credentials - Acme getting Verinym ==\n",
+ "------------------------------\n",
+ "\"Acme\" -> Create and store in Wallet \"Acme\" new DID\n",
+ "\"Acme\" -> Authcrypt \"Acme DID info\" for \"Sovrin Steward\"\n",
+ "\"Acme\" -> Send authcrypted \"Acme DID info\" to Sovrin Steward\n",
+ "\"Sovrin Steward\" -> Authdecrypted \"Acme DID info\" from Acme\n",
+ "\"Sovrin Steward\" -> Authenticate Acme by comparision of Verkeys\n",
+ "\"Sovrin Steward\" -> Send Nym to Ledger for \"Acme DID\" with TRUST_ANCHOR Role\n",
+ "==============================\n",
+ "=== 6/9: Schema setup ==\n",
+ "=== Credential Schemas Setup ==\n",
+ "------------------------------\n",
+ "\"Government\" -> Create \"Job-Certificate\" Schema\n",
+ "\"Government\" -> Send \"Job-Certificate\" Schema to Ledger\n",
+ "\"Government\" -> Create \"PDP\" Schema\n",
+ "\"Government\" -> Send \"PDP\" Schema to Ledger\n",
+ "==============================\n",
+ "=== 7/9: Faber Consent Receipt Setup ==\n",
+ "=== Faber Credential Definition Setup ==\n",
+ "------------------------------\n",
+ "\"Faber\" -> Get \"PDP\" Schema from Ledger\n",
+ "\"Faber\" -> Create and store in Wallet \"Faber PDP\" Credential Definition\n",
+ "\"Faber\" -> Send \"Faber PDP\" Credential Definition to Ledger\n",
+ "==============================\n",
+ "=== 8/9: Acme Proof ==\n",
+ "=== Acme Credential Definition Setup ==\n",
+ "------------------------------\n",
+ "\"Acme\" -> Get from Ledger \"Job-Certificate\" Schema\n",
+ "\"Acme\" -> Create and store in Wallet \"Acme Job-Certificate\" Credential Definition\n",
+ "\"Acme\" -> Send \"Acme Job-Certificate\" Credential Definition to Ledger\n",
+ "==============================\n",
+ "== 9/9: Alice onboarded ==\n",
+ "== Prep - Alice Onboarding ==\n",
+ "------------------------------\n",
+ "\"Faber\" -> Create and store in Wallet \"Faber Alice\" DID\n",
+ "\"Faber\" -> Send Nym to Ledger for \"Faber Alice\" DID\n",
+ "\"Faber\" -> Send connection request to Alice with \"Faber Alice\" DID and nonce\n",
+ "\"Alice\" -> Create wallet\n",
+ "\"Alice\" -> Create and store in Wallet \"Alice Faber\" DID\n",
+ "\"Alice\" -> Get key for did from \"Faber\" connection request\n",
+ "\"Alice\" -> Anoncrypt connection response for \"Faber\" with \"Alice Faber\" DID, verkey and nonce\n",
+ "\"Alice\" -> Send anoncrypted connection response to \"Faber\"\n",
+ "\"Faber\" -> Anondecrypt connection response from \"Alice\"\n",
+ "\"Faber\" -> Authenticates \"Alice\" by comparision of Nonce\n",
+ "\"Faber\" -> Send Nym to Ledger for \"Alice Faber\" DID\n",
+ "Getting started -> done\n",
+ "*********************************************\n",
+ "*********************************************\n",
+ "*** Creating Consent Receipt Certificatem ***\n",
+ "*********************************************\n",
+ "*********************************************\n",
+ "==============================\n",
+ "=== Getting PDP with Faber ==\n",
+ "==============================\n",
+ "== Getting PDP with Faber - Onboarding ==\n",
+ "------------------------------\n",
+ "\"Faber\" -> Create and store in Wallet \"Faber Alice\" DID\n",
+ "\"Faber\" -> Send Nym to Ledger for \"Faber Alice\" DID\n",
+ "\"Faber\" -> Send connection request to Alice with \"Faber Alice\" DID and nonce\n",
+ "\"Alice\" -> Create and store in Wallet \"Alice Faber\" DID\n",
+ "\"Alice\" -> Get key for did from \"Faber\" connection request\n",
+ "\"Alice\" -> Anoncrypt connection response for \"Faber\" with \"Alice Faber\" DID, verkey and nonce\n",
+ "\"Alice\" -> Send anoncrypted connection response to \"Faber\"\n",
+ "\"Faber\" -> Anondecrypt connection response from \"Alice\"\n",
+ "\"Faber\" -> Authenticates \"Alice\" by comparision of Nonce\n",
+ "\"Faber\" -> Send Nym to Ledger for \"Alice Faber\" DID\n",
+ "==============================\n",
+ "== Getting PDP with Faber - Getting PDP Credential ==\n",
+ "------------------------------\n",
+ "\"Faber\" -> Create \"PDP\" Credential Offer for Alice\n",
+ "\"Faber\" -> Get key for Alice did\n",
+ "\"Faber\" -> Authcrypt \"PDP\" Credential Offer for Alice\n",
+ "\"Faber\" -> Send authcrypted \"PDP\" Credential Offer to Alice\n",
+ "\"Alice\" -> Authdecrypted \"PDP\" Credential Offer from Faber\n"
+ ]
+ },
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "1114098bb96a4349959bf80cc78f30d3",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "VBox(children=(Box(children=(Box(children=(HTML(value='\\n
Privay Policy
\\n Purpose
\\n …"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\"Alice\" -> Create and store \"Alice\" Master Secret in Wallet\n",
+ "\"Alice\" -> Get \"Faber PDP\" Credential Definition from Ledger\n",
+ "\"Alice\" -> Create \"PDP\" Credential Request for Faber\n",
+ "\"Alice\" -> Authcrypt \"PDP\" Credential Request for Faber\n",
+ "\"Alice\" -> Send authcrypted \"PDP\" Credential Request to Faber\n",
+ "\"Faber\" -> Authdecrypt \"PDP\" Credential Request from Alice\n",
+ "\"Faber\" -> Create \"PDP\" Credential for Alice\n",
+ "\"Faber\" -> Authcrypt \"PDP\" Credential for Alice\n",
+ "\"Faber\" -> Send authcrypted \"PDP\" Credential to Alice\n",
+ "\"Alice\" -> Authdecrypted \"PDP\" Credential from Faber\n",
+ "\"Alice\" -> Store \"PDP\" Credential from Faber\n",
+ "Consent Receipt Certificate\n",
+ "{\"schema_id\":\"QFhKsBzE8ZVThtdEc4swwf:2:PDP:1.2\",\"cred_def_id\":\"G2BcB9MJCuGxGAKeYX62u8:3:CL:541:TAG1\",\"rev_reg_id\":null,\"values\":{\"expiration\":{\"raw\":\"2020-07-01\",\"encoded\":\"20200701\"},\"id\":{\"raw\":\"123-45-6789\",\"encoded\":\"3124141231422543541\"},\"first_name\":{\"raw\":\"Alice\",\"encoded\":\"1139481716457488690172217916278103335\"},\"limitation\":{\"raw\":\"360\",\"encoded\":\"360\"},\"last_name\":{\"raw\":\"Garcia\",\"encoded\":\"5321642780241790123587902456789123452\"},\"consent\":{\"raw\":\"1\",\"encoded\":\"1\"},\"validity_ttl\":{\"raw\":\"3\",\"encoded\":\"3\"}},\"signature\":{\"p_credential\":{\"m_2\":\"114149088040006641764699089875860843854045970786461354058704713399501515931137\",\"a\":\"70306835669066111361540999085770737234442113499954857422121593225721814789428722560887232933232250832395263603406977646196095994661926141608237811131759249773538838886254978680057860884913616526510239541242904988870668235772991206055560970482652385437557430912071294012488580826178990773099399654294549282801688205449580137480041174188338486688464133888105516978261619143577807872089559436144743171618561974958956409254393263471567731960849385588001833323797802996462691034939502665964287981536780022417027006778602128707912192656408117285068936055923263217917121753028634889580429128764627904114176055927616768797207\",\"e\":\"259344723055062059907025491480697571938277889515152306249728583105665800713306759149981690559193987143012367913206299323899696942213235956742929850138290324646550051479827899473067\",\"v\":\"6506508806032766069727550137568911163958828128389051338321755397390118681468319703967877230306595628055815015667172150190669333972888809915591886788531906634873683356356479187124137812670369400042500780929137844842200125263320337299095749632541803899246287554732462839482507024900559123804836806610834084988543502556080764455812635482727022569518909458331404680886528387182089215157135128313487662488975184027756483425024273591233472604308924436408267169487145112076020495996313353258953760539768150657964085928364344923076679122705983136377531985301716255731630621671411710144343408099094676800764082732426358100735571433642311475821620302382409061699610072214739717962481386785854580071676135207551598078600893451615993581471931124106903449670853027174862002008441814045819958901504729200752163757993594497140947112014\"},\"r_credential\":null},\"signature_correctness_proof\":{\"se\":\"5871070722555296023225621358182294069229040248932159825571695869751340419181006699291245757569952142953012733521176207717523938800381468614843980486744919086984205185727830626963582181401773749945218829404921457330809815380353965021956164892949164758420919431824038138523674956835862185489456307843508838365952216144623575975556108706045869807110905377283903001260631085790713219907139753514201426939490345560305442003211696712233720737769603252352826163348511565037897907850484259494290837585557666501322411745134540326874942704396425742663372013388849591403642025607631392469861916080318607282668997443603282019243\",\"c\":\"72311222642326098106468309283792752672440425237712995478296279984591162967815\"},\"rev_reg\":null,\"witness\":null}\n",
+ "*********************************************\n",
+ "*********************************************\n",
+ "*** Performing Proof (without PII) ***\n",
+ "*********************************************\n",
+ "==============================\n",
+ "=== Apply for the job with Acme ==\n",
+ "==============================\n",
+ "== Apply for the job with Acme - Onboarding ==\n",
+ "------------------------------\n",
+ "\"Acme\" -> Create and store in Wallet \"Acme Alice\" DID\n",
+ "\"Acme\" -> Send Nym to Ledger for \"Acme Alice\" DID\n",
+ "\"Acme\" -> Send connection request to Alice with \"Acme Alice\" DID and nonce\n",
+ "\"Alice\" -> Create and store in Wallet \"Alice Acme\" DID\n",
+ "\"Alice\" -> Get key for did from \"Acme\" connection request\n",
+ "\"Alice\" -> Anoncrypt connection response for \"Acme\" with \"Alice Acme\" DID, verkey and nonce\n",
+ "\"Alice\" -> Send anoncrypted connection response to \"Acme\"\n",
+ "\"Acme\" -> Anondecrypt connection response from \"Alice\"\n",
+ "\"Acme\" -> Authenticates \"Alice\" by comparision of Nonce\n",
+ "\"Acme\" -> Send Nym to Ledger for \"Alice Acme\" DID\n",
+ "==============================\n",
+ "== Apply for the job with Acme - PDP proving ==\n",
+ "------------------------------\n",
+ "\"Acme\" -> Create \"PDP\" Proof Request\n",
+ "\"Acme\" -> Get key for Alice did\n",
+ "\"Acme\" -> Authcrypt \"PDP\" Proof Request for Alice\n",
+ "\"Acme\" -> Send authcrypted \"PDP\" Proof Request to Alice\n",
+ "\"Alice\" -> Authdecrypt \"PDP\" Proof Request from Acme\n",
+ "\"Alice\" -> Get credentials for \"PDP\" Proof Request\n",
+ "\"Alice\" -> Get Schema from Ledger\n",
+ "\"Alice\" -> Get Credential Definition from Ledger\n",
+ "\"Alice\" -> Create \"PDP\" Proof\n",
+ "\"Alice\" -> Authcrypt \"PDP\" Proof for Acme\n",
+ "\"Alice\" -> Send authcrypted \"PDP\" Proof to Acme\n",
+ "\"Acme\" -> Authdecrypted \"PDP\" Proof from Alice\n",
+ "\"Acme\" -> Get Schema from Ledger\n",
+ "\"Acme\" -> Get Credential Definition from Ledger\n",
+ "\"Acme\" -> Verify \"PDP\" Proof from Alice\n",
+ "\"Acme\" -> Verify \"PDP\" Proof from Alice\n",
+ "PDP Proof Request\n",
+ "{'version': '0.1', 'name': 'PDP', 'nonce': '1432422343242122312411212', 'requested_predicates': {}, 'requested_attributes': {'attr3_referent': {'name': 'validity_ttl', 'restrictions': [{'cred_def_id': 'G2BcB9MJCuGxGAKeYX62u8:3:CL:541:TAG1'}]}, 'attr2_referent': {'name': 'consent', 'restrictions': [{'cred_def_id': 'G2BcB9MJCuGxGAKeYX62u8:3:CL:541:TAG1'}]}}}\n",
+ "Attribute consent confirmed\n",
+ "Attribute validity_ttl confirmed\n",
+ "Proof confirmed\n",
+ "*********************************************\n",
+ "*********************************************\n",
+ "*** Close ledger ***\n",
+ "*********************************************\n",
+ " \"Sovrin Steward\" -> Close and Delete wallet\n",
+ "\"Government\" -> Close and Delete wallet\n",
+ "\"Faber\" -> Close and Delete wallet\n",
+ "\"Acme\" -> Close and Delete wallet\n",
+ "\"Alice\" -> Close and Delete wallet\n",
+ "Close and Delete pool\n"
+ ]
+ }
+ ],
+ "source": [
+ "import asyncio\n",
+ "import time\n",
+ "from indy import anoncreds, crypto, did, ledger, pool, wallet, blob_storage\n",
+ "import os\n",
+ "import json\n",
+ "from typing import Optional\n",
+ "from ipywidgets import Box, Layout, VBox, Output, HTML\n",
+ "import ipywidgets as widgets\n",
+ "\n",
+ "async def run():\n",
+ " print(\"Getting started -> started\")\n",
+ " print(\"=== 1/9: Open Ledger ==\")\n",
+ "\n",
+ "\n",
+ " # Set protocol version 2 to work with Indy Node 1.4\n",
+ " await pool.set_protocol_version(2)\n",
+ " \n",
+ " pool_ = {\n",
+ " 'name': 'pool1',\n",
+ " 'config': json.dumps({\"genesis_txn\": '/home/indy/sandbox/pool_transactions_genesis'})\n",
+ " }\n",
+ " print(\"Open Pool Ledger: {}\".format(pool_['name']))\n",
+ "\n",
+ " try:\n",
+ " await pool.create_pool_ledger_config(pool_['name'], pool_['config'])\n",
+ " except:\n",
+ " pass\n",
+ " pool_['handle'] = await pool.open_pool_ledger(pool_['name'], None)\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"== 2/9: Setup Steward ==\")\n",
+ " print(\"=== Getting Trust Anchor credentials for Faber, Acme, Thrift and Government ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " print(\"\\\"Sovrin Steward\\\" -> Create wallet\")\n",
+ " steward = {\n",
+ " 'name': \"Sovrin Steward\",\n",
+ " 'wallet_config': json.dumps({'id': 'sovrin_steward_wallet'}),\n",
+ " 'wallet_credentials': json.dumps({'key': 'steward_wallet_key'}),\n",
+ " 'pool': pool_['handle'],\n",
+ " 'seed': '000000000000000000000000Steward1'\n",
+ " }\n",
+ "\n",
+ " try:\n",
+ " await wallet.create_wallet(steward['wallet_config'], steward['wallet_credentials'])\n",
+ " except IndyError as ex:\n",
+ " if ex.error_code == ErrorCode.WalletAlreadyExistsError:\n",
+ " pass\n",
+ "\n",
+ " steward['wallet'] = await wallet.open_wallet(steward['wallet_config'], steward['wallet_credentials'])\n",
+ "\n",
+ " print(\"\\\"Sovrin Steward\\\" -> Create and store in Wallet DID from seed\")\n",
+ " steward['did_info'] = json.dumps({'seed': steward['seed']})\n",
+ " steward['did'], steward['key'] = await did.create_and_store_my_did(steward['wallet'], steward['did_info'])\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"== 3/9: Onboarded Goverment ==\")\n",
+ " print(\"== Getting Trust Anchor credentials - Government Onboarding ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " government = {\n",
+ " 'name': 'Government',\n",
+ " 'wallet_config': json.dumps({'id': 'government_wallet'}),\n",
+ " 'wallet_credentials': json.dumps({'key': 'government_wallet_key'}),\n",
+ " 'pool': pool_['handle'],\n",
+ " 'role': 'TRUST_ANCHOR'\n",
+ " }\n",
+ " steward['did_for_government'], steward['key_for_government'], government['did_for_steward'], \\\n",
+ " government['key_for_steward'], _ = await onboarding(steward, government)\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"== Getting Trust Anchor credentials - Government getting Verinym ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " government['did'] = await get_verinym(steward, steward['did_for_government'], steward['key_for_government'],\n",
+ " government, government['did_for_steward'], government['key_for_steward'])\n",
+ " \n",
+ " print(\"==============================\")\n",
+ " print(\"== 4/9: Onboarded Faber ==\")\n",
+ " print(\"== Getting Trust Anchor credentials - Faber Onboarding ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " faber = {\n",
+ " 'name': 'Faber',\n",
+ " 'wallet_config': json.dumps({'id': 'faber_wallet'}),\n",
+ " 'wallet_credentials': json.dumps({'key': 'faber_wallet_key'}),\n",
+ " 'pool': pool_['handle'],\n",
+ " 'role': 'TRUST_ANCHOR'\n",
+ " }\n",
+ " steward['did_for_faber'], steward['key_for_faber'], faber['did_for_steward'], faber['key_for_steward'], _ = \\\n",
+ " await onboarding(steward, faber)\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"== Getting Trust Anchor credentials - Faber getting Verinym ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " faber['did'] = \\\n",
+ " await get_verinym(steward, steward['did_for_faber'], steward['key_for_faber'],\n",
+ " faber, faber['did_for_steward'], faber['key_for_steward'])\n",
+ " \n",
+ " print(\"Create blob storage\")\n",
+ " faber['tails_writer_config'] = json.dumps({'base_dir': str(os.path.join(\"/tmp\",\"tails\")), 'uri_pattern': ''})\n",
+ " faber['tails_writer'] = await blob_storage.open_writer('default', faber['tails_writer_config'])\n",
+ " \n",
+ " print(\"==============================\")\n",
+ " print(\"== 5/9: Onboarded Acme ==\")\n",
+ " print(\"== Getting Trust Anchor credentials - Acme Onboarding ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " acme = {\n",
+ " 'name': 'Acme',\n",
+ " 'wallet_config': json.dumps({'id': 'acme_wallet'}),\n",
+ " 'wallet_credentials': json.dumps({'key': 'acme_wallet_key'}),\n",
+ " 'pool': pool_['handle'],\n",
+ " 'role': 'TRUST_ANCHOR'\n",
+ " }\n",
+ " steward['did_for_acme'], steward['key_for_acme'], acme['did_for_steward'], acme['key_for_steward'], _ = \\\n",
+ " await onboarding(steward, acme)\n",
+ " \n",
+ " print(\"==============================\")\n",
+ " print(\"== Getting Trust Anchor credentials - Acme getting Verinym ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " acme['did'] = await get_verinym(steward, steward['did_for_acme'], steward['key_for_acme'],\n",
+ " acme, acme['did_for_steward'], acme['key_for_steward'])\n",
+ " \n",
+ " print(\"==============================\")\n",
+ " print(\"=== 6/9: Schema setup ==\")\n",
+ " print(\"=== Credential Schemas Setup ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " print(\"\\\"Government\\\" -> Create \\\"Job-Certificate\\\" Schema\")\n",
+ " job_certificate = {\n",
+ " 'name': 'Job-Certificate',\n",
+ " 'version': '0.2',\n",
+ " 'attributes': ['first_name', 'last_name', 'salary', 'employee_status', 'experience']\n",
+ " }\n",
+ " (government['job_certificate_schema_id'], government['job_certificate_schema']) = \\\n",
+ " await anoncreds.issuer_create_schema(government['did'], job_certificate['name'], job_certificate['version'],\n",
+ " json.dumps(job_certificate['attributes']))\n",
+ " job_certificate_schema_id = government['job_certificate_schema_id']\n",
+ "\n",
+ " print(\"\\\"Government\\\" -> Send \\\"Job-Certificate\\\" Schema to Ledger\")\n",
+ " await send_schema(government['pool'], government['wallet'], government['did'], government['job_certificate_schema'])\n",
+ "\n",
+ " print(\"\\\"Government\\\" -> Create \\\"PDP\\\" Schema\")\n",
+ " pdp = {\n",
+ " 'name': 'PDP',\n",
+ " 'version': '1.2',\n",
+ " 'attributes': ['first_name', 'last_name', 'id', 'expiration', 'limitation', 'consent', 'validity_ttl']\n",
+ " }\n",
+ " (government['pdp_schema_id'], government['pdp_schema']) = \\\n",
+ " await anoncreds.issuer_create_schema(government['did'], pdp['name'], pdp['version'],\n",
+ " json.dumps(pdp['attributes']))\n",
+ " pdp_schema_id = government['pdp_schema_id']\n",
+ "\n",
+ " print(\"\\\"Government\\\" -> Send \\\"PDP\\\" Schema to Ledger\")\n",
+ " await send_schema(government['pool'], government['wallet'], government['did'], government['pdp_schema'])\n",
+ "\n",
+ " time.sleep(1) # sleep 1 second before getting schema\n",
+ " \n",
+ " print(\"==============================\")\n",
+ " print(\"=== 7/9: Faber Consent Receipt Setup ==\")\n",
+ " print(\"=== Faber Credential Definition Setup ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Get \\\"PDP\\\" Schema from Ledger\")\n",
+ " (faber['pdp_schema_id'], faber['pdp_schema']) = \\\n",
+ " await get_schema(faber['pool'], faber['did'], pdp_schema_id)\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Create and store in Wallet \\\"Faber PDP\\\" Credential Definition\")\n",
+ " pdp_cred_def = {\n",
+ " 'tag': 'TAG1',\n",
+ " 'type': 'CL',\n",
+ " 'config': {\"support_revocation\": False}\n",
+ " }\n",
+ " (faber['pdp_cred_def_id'], faber['pdp_cred_def']) = \\\n",
+ " await anoncreds.issuer_create_and_store_credential_def(faber['wallet'], faber['did'],\n",
+ " faber['pdp_schema'], pdp_cred_def['tag'],\n",
+ " pdp_cred_def['type'],\n",
+ " json.dumps(pdp_cred_def['config']))\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Send \\\"Faber PDP\\\" Credential Definition to Ledger\")\n",
+ " await send_cred_def(faber['pool'], faber['wallet'], faber['did'], faber['pdp_cred_def'])\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"=== 8/9: Acme Proof ==\")\n",
+ " print(\"=== Acme Credential Definition Setup ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " print(\"\\\"Acme\\\" -> Get from Ledger \\\"Job-Certificate\\\" Schema\")\n",
+ " (acme['job_certificate_schema_id'], acme['job_certificate_schema']) = \\\n",
+ " await get_schema(acme['pool'], acme['did'], job_certificate_schema_id)\n",
+ "\n",
+ " print(\"\\\"Acme\\\" -> Create and store in Wallet \\\"Acme Job-Certificate\\\" Credential Definition\")\n",
+ " job_certificate_cred_def = {\n",
+ " 'tag': 'TAG1',\n",
+ " 'type': 'CL',\n",
+ " 'config': {\"support_revocation\": False}\n",
+ " }\n",
+ " (acme['job_certificate_cred_def_id'], acme['job_certificate_cred_def']) = \\\n",
+ " await anoncreds.issuer_create_and_store_credential_def(acme['wallet'], acme['did'],\n",
+ " acme['job_certificate_schema'],\n",
+ " job_certificate_cred_def['tag'],\n",
+ " job_certificate_cred_def['type'],\n",
+ " json.dumps(job_certificate_cred_def['config']))\n",
+ "\n",
+ " print(\"\\\"Acme\\\" -> Send \\\"Acme Job-Certificate\\\" Credential Definition to Ledger\")\n",
+ " await send_cred_def(acme['pool'], acme['wallet'], acme['did'], acme['job_certificate_cred_def'])\n",
+ " \n",
+ " print(\"==============================\")\n",
+ " print(\"== 9/9: Alice onboarded ==\")\n",
+ " print(\"== Prep - Alice Onboarding ==\")\n",
+ " print(\"------------------------------\")\n",
+ " \n",
+ " alice = {\n",
+ " 'name': 'Alice',\n",
+ " 'wallet_config': json.dumps({'id': 'alice_wallet'}),\n",
+ " 'wallet_credentials': json.dumps({'key': 'alice_wallet_key'}),\n",
+ " 'pool': pool_['handle'],\n",
+ " }\n",
+ " faber['did_for_alice'], faber['key_for_alice'], alice['did_for_faber'], alice['key_for_faber'], \\\n",
+ " faber['alice_connection_response'] = await onboarding(faber, alice)\n",
+ " \n",
+ " print(\"Getting started -> done\")\n",
+ " \n",
+ " print(\"*********************************************\")\n",
+ " print(\"*********************************************\")\n",
+ " print(\"*** Creating Consent Receipt Certificatem ***\")\n",
+ " print(\"*********************************************\")\n",
+ " print(\"*********************************************\")\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"=== Getting PDP with Faber ==\")\n",
+ " print(\"==============================\")\n",
+ " print(\"== Getting PDP with Faber - Onboarding ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " faber['did_for_alice'], faber['key_for_alice'], alice['did_for_faber'], alice['key_for_faber'], \\\n",
+ " faber['alice_connection_response'] = await onboarding(faber, alice)\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"== Getting PDP with Faber - Getting PDP Credential ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Create \\\"PDP\\\" Credential Offer for Alice\")\n",
+ " faber['pdp_cred_offer'] = \\\n",
+ " await anoncreds.issuer_create_credential_offer(faber['wallet'], faber['pdp_cred_def_id'])\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Get key for Alice did\")\n",
+ " faber['alic_key_for_faber'] = \\\n",
+ " await did.key_for_did(faber['pool'], faber['wallet'], faber['alice_connection_response']['did'])\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Authcrypt \\\"PDP\\\" Credential Offer for Alice\")\n",
+ " faber['authcrypted_pdp_cred_offer'] = \\\n",
+ " await crypto.auth_crypt(faber['wallet'], faber['key_for_alice'], faber['alic_key_for_faber'],\n",
+ " faber['pdp_cred_offer'].encode('utf-8'))\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Send authcrypted \\\"PDP\\\" Credential Offer to Alice\")\n",
+ " alice['authcrypted_pdp_cred_offer'] = faber['authcrypted_pdp_cred_offer']\n",
+ " print(\"\\\"Alice\\\" -> Authdecrypted \\\"PDP\\\" Credential Offer from Faber\")\n",
+ " alice['faber_key_for_alice'], alice['pdp_cred_offer'], authdecrypted_pdp_cred_offer = \\\n",
+ " await auth_decrypt(alice['wallet'], alice['key_for_faber'], alice['authcrypted_pdp_cred_offer'])\n",
+ " alice['pdp_schema_id'] = authdecrypted_pdp_cred_offer['schema_id']\n",
+ " alice['pdp_cred_def_id'] = authdecrypted_pdp_cred_offer['cred_def_id']\n",
+ "\n",
+ "\n",
+ " # privacy agreement\n",
+ " form_item_layout = Layout(\n",
+ " display='flex',\n",
+ " flex_flow='row',\n",
+ " justify_content='space-between'\n",
+ " )\n",
+ " \n",
+ " form_items = [\n",
+ " Box([HTML(value= '''\n",
+ " Privay Policy
\n",
+ " Purpose
\n",
+ " Private Data is collected to improve services. The data is used for purpose a, b and c.
\n",
+ " Data collected
\n",
+ " Data is collected while using the service which expires on 2020-07-01. After this period if \n",
+ " service is not renewed then no more data is collected.
\n",
+ " Data limitation
\n",
+ " Data is only kept for a duration of 1 year.
\n",
+ " Data sharing
\n",
+ " Data may be shared with your consent with Acme to provided additional service of \n",
+ " recommendation on study plan in order to secure a job after college.\n",
+ " ''')], layout=form_item_layout),\n",
+ " Box([HTML(value='Once you have read the privacy policy indicate if you agree with the conditions of using of your \\\n",
+ " private data.')], layout=form_item_layout)\n",
+ " ]\n",
+ "\n",
+ " form = Box(form_items, layout=Layout(\n",
+ " display='flex',\n",
+ " flex_flow='column',\n",
+ " border='solid 2px',\n",
+ " align_items='stretch',\n",
+ " width='100%'\n",
+ " ))\n",
+ "\n",
+ " out_cert = Output()\n",
+ " display(VBox([form,out_cert]))\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Create and store \\\"Alice\\\" Master Secret in Wallet\")\n",
+ " alice['master_secret_id'] = await anoncreds.prover_create_master_secret(alice['wallet'], None)\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Get \\\"Faber PDP\\\" Credential Definition from Ledger\")\n",
+ " (alice['faber_pdp_cred_def_id'], alice['faber_pdp_cred_def']) = \\\n",
+ " await get_cred_def(alice['pool'], alice['did_for_faber'], alice['pdp_cred_def_id'])\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Create \\\"PDP\\\" Credential Request for Faber\")\n",
+ " (alice['pdp_cred_request'], alice['pdp_cred_request_metadata']) = \\\n",
+ " await anoncreds.prover_create_credential_req(alice['wallet'], alice['did_for_faber'],\n",
+ " alice['pdp_cred_offer'], alice['faber_pdp_cred_def'],\n",
+ " alice['master_secret_id'])\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Authcrypt \\\"PDP\\\" Credential Request for Faber\")\n",
+ " alice['authcrypted_pdp_cred_request'] = \\\n",
+ " await crypto.auth_crypt(alice['wallet'], alice['key_for_faber'], alice['faber_key_for_alice'],\n",
+ " alice['pdp_cred_request'].encode('utf-8'))\n",
+ "\n",
+ " #TODO: values come from entry overlay\n",
+ " \n",
+ " print(\"\\\"Alice\\\" -> Send authcrypted \\\"PDP\\\" Credential Request to Faber\")\n",
+ " alice['pdp_cred_values'] = json.dumps({\n",
+ " \"first_name\": {\"raw\": \"Alice\", \"encoded\": \"1139481716457488690172217916278103335\"},\n",
+ " \"last_name\": {\"raw\": \"Garcia\", \"encoded\": \"5321642780241790123587902456789123452\"},\n",
+ " \"id\": {\"raw\": \"123-45-6789\", \"encoded\": \"3124141231422543541\"},\n",
+ " \"expiration\": {\"raw\": \"2020-07-01\", \"encoded\": \"20200701\"},\n",
+ " \"limitation\": {\"raw\": \"360\", \"encoded\": \"360\"},\n",
+ " \"consent\": {\"raw\": \"1\", \"encoded\": \"1\"},\n",
+ " \"validity_ttl\": {\"raw\": \"3\", \"encoded\": \"3\"}\n",
+ " })\n",
+ " \n",
+ " faber['authcrypted_pdp_cred_request'] = alice['authcrypted_pdp_cred_request']\n",
+ " faber['alice_pdp_cred_values'] = alice['pdp_cred_values']\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Authdecrypt \\\"PDP\\\" Credential Request from Alice\")\n",
+ " faber['alice_key_for_faber'], faber['pdp_cred_request'], _ = \\\n",
+ " await auth_decrypt(faber['wallet'], faber['key_for_alice'], faber['authcrypted_pdp_cred_request'])\n",
+ " \n",
+ " #TODO: verify that default values are not modified/hacked\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Create \\\"PDP\\\" Credential for Alice\")\n",
+ "\n",
+ " # Issuer Opens Tails reader\n",
+ " faber['blob_storage_reader_cfg_handle'] = await blob_storage.open_reader('default', faber['tails_writer_config'])\n",
+ " \n",
+ " # pdp_cred is cred_json\n",
+ " faber['pdp_cred'], faber['cred_revoc_id'], faber['revoc_reg_delta_json'] = \\\n",
+ " await anoncreds.issuer_create_credential(faber['wallet'], faber['pdp_cred_offer'],\n",
+ " faber['pdp_cred_request'],\n",
+ " faber['alice_pdp_cred_values'], None, None)\n",
+ "\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Authcrypt \\\"PDP\\\" Credential for Alice\")\n",
+ " faber['authcrypted_pdp_cred'] = \\\n",
+ " await crypto.auth_crypt(faber['wallet'], faber['key_for_alice'], faber['alice_key_for_faber'],\n",
+ " faber['pdp_cred'].encode('utf-8'))\n",
+ "\n",
+ " print(\"\\\"Faber\\\" -> Send authcrypted \\\"PDP\\\" Credential to Alice\")\n",
+ " alice['authcrypted_pdp_cred'] = faber['authcrypted_pdp_cred']\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Authdecrypted \\\"PDP\\\" Credential from Faber\")\n",
+ " _, alice['pdp_cred'], _ = \\\n",
+ " await auth_decrypt(alice['wallet'], alice['key_for_faber'], alice['authcrypted_pdp_cred'])\n",
+ "\n",
+ " #TODO: Alice should verify that same values as she sends it\n",
+ " print(\"\\\"Alice\\\" -> Store \\\"PDP\\\" Credential from Faber\")\n",
+ " _, alice['pdp_cred_def'] = await get_cred_def(alice['pool'], alice['did_for_faber'],\n",
+ " alice['pdp_cred_def_id'])\n",
+ "\n",
+ " await anoncreds.prover_store_credential(alice['wallet'], None, alice['pdp_cred_request_metadata'],\n",
+ " alice['pdp_cred'], alice['pdp_cred_def'], None)\n",
+ " \n",
+ " print('Consent Receipt Certificate')\n",
+ " print(alice['pdp_cred'])\n",
+ " \n",
+ " print(\"*********************************************\")\n",
+ " print(\"*********************************************\")\n",
+ " print(\"*** Performing Proof (without PII) ***\")\n",
+ " print(\"*********************************************\")\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"=== Apply for the job with Acme ==\")\n",
+ " print(\"==============================\")\n",
+ " print(\"== Apply for the job with Acme - Onboarding ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " acme['did_for_alice'], acme['key_for_alice'], alice['did_for_acme'], alice['key_for_acme'], \\\n",
+ " acme['alice_connection_response'] = await onboarding(acme, alice)\n",
+ "\n",
+ " print(\"==============================\")\n",
+ " print(\"== Apply for the job with Acme - PDP proving ==\")\n",
+ " print(\"------------------------------\")\n",
+ "\n",
+ " print(\"\\\"Acme\\\" -> Create \\\"PDP\\\" Proof Request\")\n",
+ " acme['pdp_proof_request'] = json.dumps({\n",
+ " 'nonce': '1432422343242122312411212',\n",
+ " 'name': 'PDP',\n",
+ " 'version': '0.1',\n",
+ " 'requested_attributes': {\n",
+ " 'attr2_referent': {\n",
+ " 'name': 'consent',\n",
+ " 'restrictions': [{'cred_def_id': faber['pdp_cred_def_id']}]\n",
+ " } \n",
+ ",\n",
+ " 'attr3_referent': {\n",
+ " 'name': 'validity_ttl',\n",
+ " 'restrictions': [{'cred_def_id': faber['pdp_cred_def_id']}]\n",
+ " } \n",
+ " },\n",
+ " 'requested_predicates': {}\n",
+ " })\n",
+ " \n",
+ " print(\"\\\"Acme\\\" -> Get key for Alice did\")\n",
+ " acme['alice_key_for_acme'] = \\\n",
+ " await did.key_for_did(acme['pool'], acme['wallet'], acme['alice_connection_response']['did'])\n",
+ "\n",
+ " print(\"\\\"Acme\\\" -> Authcrypt \\\"PDP\\\" Proof Request for Alice\")\n",
+ " acme['authcrypted_pdp_proof_request'] = \\\n",
+ " await crypto.auth_crypt(acme['wallet'], acme['key_for_alice'], acme['alice_key_for_acme'],\n",
+ " acme['pdp_proof_request'].encode('utf-8'))\n",
+ "\n",
+ " print(\"\\\"Acme\\\" -> Send authcrypted \\\"PDP\\\" Proof Request to Alice\")\n",
+ " alice['authcrypted_pdp_proof_request'] = acme['authcrypted_pdp_proof_request']\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Authdecrypt \\\"PDP\\\" Proof Request from Acme\")\n",
+ " alice['acme_key_for_alice'], alice['pdp_proof_request'], _ = \\\n",
+ " await auth_decrypt(alice['wallet'], alice['key_for_acme'], alice['authcrypted_pdp_proof_request'])\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Get credentials for \\\"PDP\\\" Proof Request\")\n",
+ "\n",
+ " search_for_pdp_proof_request = \\\n",
+ " await anoncreds.prover_search_credentials_for_proof_req(alice['wallet'],\n",
+ " alice['pdp_proof_request'], None)\n",
+ "\n",
+ " cred_for_attr2 = await get_credential_for_referent(search_for_pdp_proof_request, 'attr2_referent')\n",
+ " cred_for_attr3 = await get_credential_for_referent(search_for_pdp_proof_request, 'attr3_referent')\n",
+ "\n",
+ " await anoncreds.prover_close_credentials_search_for_proof_req(search_for_pdp_proof_request)\n",
+ "\n",
+ " alice['creds_for_pdp_proof'] = {cred_for_attr2['referent']: cred_for_attr2,\n",
+ " cred_for_attr3['referent']: cred_for_attr3}\n",
+ "\n",
+ " alice['schemas'], alice['cred_defs'], alice['revoc_states'] = \\\n",
+ " await prover_get_entities_from_ledger(alice['pool'], alice['did_for_acme'],\n",
+ " alice['creds_for_pdp_proof'], alice['name'])\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Create \\\"PDP\\\" Proof\")\n",
+ " alice['pdp_requested_creds'] = json.dumps({\n",
+ " 'self_attested_attributes': {},\n",
+ " 'requested_attributes': {\n",
+ " 'attr2_referent': {'cred_id': cred_for_attr2['referent'], 'revealed': True},\n",
+ " 'attr3_referent': {'cred_id': cred_for_attr3['referent'], 'revealed': True}\n",
+ " },\n",
+ " 'requested_predicates': {}\n",
+ " })\n",
+ "\n",
+ " alice['pdp_proof'] = \\\n",
+ " await anoncreds.prover_create_proof(alice['wallet'], alice['pdp_proof_request'],\n",
+ " alice['pdp_requested_creds'], alice['master_secret_id'],\n",
+ " alice['schemas'], alice['cred_defs'], alice['revoc_states'])\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Authcrypt \\\"PDP\\\" Proof for Acme\")\n",
+ " alice['authcrypted_pdp_proof'] = \\\n",
+ " await crypto.auth_crypt(alice['wallet'], alice['key_for_acme'], alice['acme_key_for_alice'],\n",
+ " alice['pdp_proof'].encode('utf-8'))\n",
+ "\n",
+ " print(\"\\\"Alice\\\" -> Send authcrypted \\\"PDP\\\" Proof to Acme\")\n",
+ " acme['authcrypted_pdp_proof'] = alice['authcrypted_pdp_proof']\n",
+ " \n",
+ " print(\"\\\"Acme\\\" -> Authdecrypted \\\"PDP\\\" Proof from Alice\")\n",
+ " _, acme['pdp_proof'], decrypted_pdp_proof = \\\n",
+ " await auth_decrypt(acme['wallet'], acme['key_for_alice'], acme['authcrypted_pdp_proof'])\n",
+ "\n",
+ " acme['schemas'], acme['cred_defs'], acme['revoc_ref_defs'], acme['revoc_regs'] = \\\n",
+ " await verifier_get_entities_from_ledger(acme['pool'], acme['did'],\n",
+ " decrypted_pdp_proof['identifiers'], acme['name'])\n",
+ "\n",
+ " print(\"\\\"Acme\\\" -> Verify \\\"PDP\\\" Proof from Alice\")\n",
+ " try:\n",
+ " assert '1' == \\\n",
+ " decrypted_pdp_proof['requested_proof']['revealed_attrs']['attr2_referent']['raw']\n",
+ " assert2 = ' confirmed'\n",
+ " except:\n",
+ " assert2 = ' failed'\n",
+ " \n",
+ " print(\"\\\"Acme\\\" -> Verify \\\"PDP\\\" Proof from Alice\")\n",
+ " try:\n",
+ " assert '3' == \\\n",
+ " decrypted_pdp_proof['requested_proof']['revealed_attrs']['attr3_referent']['raw']\n",
+ " assert3 = ' confirmed'\n",
+ " except:\n",
+ " assert3 = ' failed'\n",
+ " try:\n",
+ " assert await anoncreds.verifier_verify_proof(acme['pdp_proof_request'], acme['pdp_proof'],\n",
+ " acme['schemas'], acme['cred_defs'], acme['revoc_ref_defs'],\n",
+ " acme['revoc_regs'])\n",
+ " proof1 = 'Proof confirmed'\n",
+ " except AssertionError as e:\n",
+ " proof1 = 'Proof failed'\n",
+ " \n",
+ " print('PDP Proof Request')\n",
+ " print(json.loads(acme['pdp_proof_request']))\n",
+ " print('Attribute '+json.loads(acme['pdp_proof_request'])['requested_attributes']['attr2_referent']['name'] + assert2)\n",
+ " print('Attribute '+json.loads(acme['pdp_proof_request'])['requested_attributes']['attr3_referent']['name'] + assert3)\n",
+ " print(proof1)\n",
+ " \n",
+ " print(\"*********************************************\")\n",
+ " print(\"*********************************************\")\n",
+ " print(\"*** Close ledger ***\")\n",
+ " print(\"*********************************************\")\n",
+ "\n",
+ " print(\" \\\"Sovrin Steward\\\" -> Close and Delete wallet\")\n",
+ " await wallet.close_wallet(steward['wallet'])\n",
+ " await wallet.delete_wallet(steward['wallet_config'], steward['wallet_credentials'])\n",
+ "\n",
+ " print(\"\\\"Government\\\" -> Close and Delete wallet\")\n",
+ " await wallet.close_wallet(government['wallet'])\n",
+ " await wallet.delete_wallet(government['wallet_config'], government['wallet_credentials'])\n",
+ " \n",
+ " try:\n",
+ " print(\"\\\"Faber\\\" -> Close and Delete wallet\")\n",
+ " await wallet.close_wallet(faber['wallet'])\n",
+ " await wallet.delete_wallet(faber['wallet_config'], faber['wallet_credentials'])\n",
+ " except:\n",
+ " pass\n",
+ " \n",
+ " try:\n",
+ " print(\"\\\"Acme\\\" -> Close and Delete wallet\")\n",
+ " await wallet.close_wallet(acme['wallet'])\n",
+ " await wallet.delete_wallet(acme['wallet_config'], acme['wallet_credentials'])\n",
+ " except:\n",
+ " pass\n",
+ " \n",
+ " try:\n",
+ " print(\"\\\"Alice\\\" -> Close and Delete wallet\")\n",
+ " await wallet.close_wallet(alice['wallet'])\n",
+ " await wallet.delete_wallet(alice['wallet_config'], alice['wallet_credentials'])\n",
+ " except:\n",
+ " pass\n",
+ " \n",
+ " print(\"Close and Delete pool\")\n",
+ " await pool.close_pool_ledger(pool_['handle'])\n",
+ " await pool.delete_pool_ledger_config(pool_['name'])\n",
+ " \n",
+ "if __name__ == '__main__':\n",
+ " loop = asyncio.new_event_loop()\n",
+ " asyncio.set_event_loop(loop)\n",
+ " loop.run_until_complete(run())\n",
+ " time.sleep(1) # FIXME waiting for libindy thread complete\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "pycharm": {}
+ },
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "hide_input": false,
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.5.2"
+ },
+ "stem_cell": {
+ "cell_type": "raw",
+ "metadata": {
+ "pycharm": {
+ "metadata": false
+ }
+ },
+ "source": ""
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}
diff --git a/concepts/0167-data-consent-lifecycle/reference-implementation/docker-compose.yml b/concepts/0167-data-consent-lifecycle/reference-implementation/docker-compose.yml
new file mode 100644
index 000000000..913bd0ae7
--- /dev/null
+++ b/concepts/0167-data-consent-lifecycle/reference-implementation/docker-compose.yml
@@ -0,0 +1,52 @@
+version: '2'
+services:
+ indy_pool:
+ build:
+ context: ../../ci/
+ dockerfile: indy-pool.dockerfile
+ args:
+ pool_ip: '10.0.0.2'
+ image: indy_pool
+ container_name: indy_pool
+ working_dir: /home/indy
+ ports:
+ - "9701:9701"
+ - "9702:9702"
+ - "9703:9703"
+ - "9704:9704"
+ - "9705:9705"
+ - "9706:9706"
+ - "9707:9707"
+ - "9708:9708"
+ networks:
+ pool_network:
+ ipv4_address: 10.0.0.2
+ volumes:
+ - sandbox:/var/lib/indy/sandbox/
+ jupyter:
+ build:
+ context: .
+ dockerfile: getting-started.dockerfile
+ command: jupyter notebook --ip=0.0.0.0
+ image: getting-started
+ container_name: getting_started
+ working_dir: /home/indy
+ volumes:
+ - ./:/home/indy
+ - sandbox:/home/indy/sandbox
+ ports:
+ - "8888:8888"
+ networks:
+ - pool_network
+ links:
+ - indy_pool
+networks:
+ pool_network:
+ driver: bridge
+ ipam:
+ driver: default
+ config:
+ -
+ subnet: 10.0.0.0/24
+volumes:
+ sandbox: