Skip to content

Commit

Permalink
Webvh did method (#1542)
Browse files Browse the repository at this point in the history
* Initial commit - Webvh

Signed-off-by: jamshale <[email protected]>

* Update for server changes and refactor

Signed-off-by: jamshale <[email protected]>

* Fix linting

Signed-off-by: jamshale <[email protected]>

* Repair unit tests

Signed-off-by: jamshale <[email protected]>

* Updates from comments

Signed-off-by: jamshale <[email protected]>

* Updates from comments

Signed-off-by: jamshale <[email protected]>

* Return integration test assertions

Signed-off-by: jamshale <[email protected]>

* Fix mis-named test file

Signed-off-by: jamshale <[email protected]>

* Change endorsement verbage to witness

Signed-off-by: jamshale <[email protected]>

* resolve schema

Signed-off-by: PatStLouis <[email protected]>

* add did method and resolver

Signed-off-by: PatStLouis <[email protected]>

* register resolver

Signed-off-by: PatStLouis <[email protected]>

* rename class

Signed-off-by: PatStLouis <[email protected]>

* add pattern regex

Signed-off-by: PatStLouis <[email protected]>

* debug resolver

Signed-off-by: PatStLouis <[email protected]>

* fix class name

Signed-off-by: PatStLouis <[email protected]>

* add base resolver

Signed-off-by: PatStLouis <[email protected]>

* change import path

Signed-off-by: PatStLouis <[email protected]>

* change did regex

Signed-off-by: PatStLouis <[email protected]>

* uncomment did example

Signed-off-by: PatStLouis <[email protected]>

* edit did regex

Signed-off-by: PatStLouis <[email protected]>

* debug resolver

Signed-off-by: PatStLouis <[email protected]>

* debug resolver

Signed-off-by: PatStLouis <[email protected]>

* debug resolver

Signed-off-by: PatStLouis <[email protected]>

* import resolver

Signed-off-by: PatStLouis <[email protected]>

* fix coroutine await

Signed-off-by: PatStLouis <[email protected]>

* regex

Signed-off-by: PatStLouis <[email protected]>

* add attested resource model and schema creation

Signed-off-by: PatStLouis <[email protected]>

* fix import path

Signed-off-by: PatStLouis <[email protected]>

* disable model

Signed-off-by: PatStLouis <[email protected]>

* simplify publication

Signed-off-by: PatStLouis <[email protected]>

* update schema serialization

Signed-off-by: PatStLouis <[email protected]>

* update schema serialization

Signed-off-by: PatStLouis <[email protected]>

* update schema serialization

Signed-off-by: PatStLouis <[email protected]>

* update schema serialization

Signed-off-by: PatStLouis <[email protected]>

* update registry

Signed-off-by: PatStLouis <[email protected]>

* di-proof option deserializing

Signed-off-by: PatStLouis <[email protected]>

* di-proof option deserializing

Signed-off-by: PatStLouis <[email protected]>

* di-proof option deserializing

Signed-off-by: PatStLouis <[email protected]>

* debug upload

Signed-off-by: PatStLouis <[email protected]>

* debug upload

Signed-off-by: PatStLouis <[email protected]>

* debug upload

Signed-off-by: PatStLouis <[email protected]>

* proof set to proof

Signed-off-by: PatStLouis <[email protected]>

* edit resource options

Signed-off-by: PatStLouis <[email protected]>

* linting

Signed-off-by: PatStLouis <[email protected]>

* Add async configuration endpoint

Signed-off-by: jamshale <[email protected]>

* Fix test

Signed-off-by: jamshale <[email protected]>

* debug cred def

Signed-off-by: PatStLouis <[email protected]>

* debug cred def

Signed-off-by: PatStLouis <[email protected]>

* debug cred def

Signed-off-by: PatStLouis <[email protected]>

* Fix test

Signed-off-by: jamshale <[email protected]>

* epublish statuslist

Signed-off-by: PatStLouis <[email protected]>

* add bitstring plugin

Signed-off-by: PatStLouis <[email protected]>

* Initial commit - Webvh

Signed-off-by: jamshale <[email protected]>

* Update for server changes and refactor

Signed-off-by: jamshale <[email protected]>

* Fix linting

Signed-off-by: jamshale <[email protected]>

* Repair unit tests

Signed-off-by: jamshale <[email protected]>

* Updates from comments

Signed-off-by: jamshale <[email protected]>

* Updates from comments

Signed-off-by: jamshale <[email protected]>

* Return integration test assertions

Signed-off-by: jamshale <[email protected]>

* Fix mis-named test file

Signed-off-by: jamshale <[email protected]>

* Change endorsement verbage to witness

Signed-off-by: jamshale <[email protected]>

* Add async configuration endpoint

Signed-off-by: jamshale <[email protected]>

* Fix test

Signed-off-by: jamshale <[email protected]>

* Fix test

Signed-off-by: jamshale <[email protected]>

* fix witness config

Signed-off-by: PatStLouis <[email protected]>

* improve did registration

Signed-off-by: PatStLouis <[email protected]>

* update multikey

Signed-off-by: PatStLouis <[email protected]>

* remove strict ssl

Signed-off-by: PatStLouis <[email protected]>

* remove strict ssl

Signed-off-by: PatStLouis <[email protected]>

* re enable ssl

Signed-off-by: PatStLouis <[email protected]>

* fix multitenant witness

Signed-off-by: PatStLouis <[email protected]>

* fix multitenant witness

Signed-off-by: PatStLouis <[email protected]>

* fix witness kid

Signed-off-by: PatStLouis <[email protected]>

* create aliases constant

Signed-off-by: PatStLouis <[email protected]>

* alias constants

Signed-off-by: PatStLouis <[email protected]>

* clean up witness code

Signed-off-by: PatStLouis <[email protected]>

* fix variable type

Signed-off-by: PatStLouis <[email protected]>

* fix alias creation

Signed-off-by: PatStLouis <[email protected]>

* fix aliases

Signed-off-by: PatStLouis <[email protected]>

* fix did doc context

Signed-off-by: PatStLouis <[email protected]>

* add status list registry object

Signed-off-by: PatStLouis <[email protected]>

* remove async tag

Signed-off-by: PatStLouis <[email protected]>

* devug upload response

Signed-off-by: PatStLouis <[email protected]>

* anoncreds tests

Signed-off-by: PatStLouis <[email protected]>

* debug revocation list

Signed-off-by: PatStLouis <[email protected]>

* debug revocation list

Signed-off-by: PatStLouis <[email protected]>

* keep proof on resolved resource

Signed-off-by: PatStLouis <[email protected]>

* fix upload path

Signed-off-by: PatStLouis <[email protected]>

* fix upload path

Signed-off-by: PatStLouis <[email protected]>

* change revocation registry assertion code for uploads

Signed-off-by: PatStLouis <[email protected]>

* add revocatino registry value object

Signed-off-by: PatStLouis <[email protected]>

* get statuts list timestamp fix

Signed-off-by: PatStLouis <[email protected]>

* add revocation interval timestamps

Signed-off-by: PatStLouis <[email protected]>

* log timestamps

Signed-off-by: PatStLouis <[email protected]>

* add default statuslist timestamp

Signed-off-by: PatStLouis <[email protected]>

* transform timestamp to int

Signed-off-by: PatStLouis <[email protected]>

* fix issuer key variable

Signed-off-by: PatStLouis <[email protected]>

* fix metadata and content variable names

Signed-off-by: PatStLouis <[email protected]>

* improve verification method derivation

Signed-off-by: PatStLouis <[email protected]>

* update tests

Signed-off-by: PatStLouis <[email protected]>

* Updates and fixes with testing and documentation

Signed-off-by: jamshale <[email protected]>

* Small update

Signed-off-by: jamshale <[email protected]>

---------

Signed-off-by: jamshale <[email protected]>
Signed-off-by: PatStLouis <[email protected]>
Co-authored-by: PatStLouis <[email protected]>
Co-authored-by: Patrick St-Louis <[email protected]>
  • Loading branch information
3 people authored Feb 24, 2025
1 parent def1537 commit 0c8f4e0
Show file tree
Hide file tree
Showing 54 changed files with 8,616 additions and 0 deletions.
22 changes: 22 additions & 0 deletions webvh/.devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/python-3/.devcontainer/base.Dockerfile
ARG VARIANT="3.12"
FROM mcr.microsoft.com/devcontainers/python:${VARIANT}

ARG POETRY_VERSION="1.8.3"
ENV POETRY_HOME="/opt/poetry" \
POETRY_VERSION=${POETRY_VERSION}

RUN curl -sSL https://install.python-poetry.org | python3 - \
&& update-alternatives --install /usr/local/bin/poetry poetry /opt/poetry/bin/poetry 900 \
# Enable tab completion for bash
&& poetry completions bash >> /home/vscode/.bash_completion \
# Enable tab completion for Zsh
&& mkdir -p /home/vscode/.zfunc/ \
&& poetry completions zsh > /home/vscode/.zfunc/_poetry \
&& echo "fpath+=~/.zfunc\nautoload -Uz compinit && compinit" >> /home/vscode/.zshrc

COPY pyproject.toml ./
# COPY pyproject.toml poetry.lock ./
RUN poetry config virtualenvs.create true \
&& poetry install --no-root --no-interaction --with integration --extras "aca-py" \
&& rm -rf /root/.cache/pypoetry
59 changes: 59 additions & 0 deletions webvh/.devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/python
{
"name": "webvh",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"VARIANT": "3.12-bullseye",
"POETRY_VERSION": "1.8.3"
}
},
"customizations": {
"vscode": {
"extensions": ["ms-python.python", "ms-python.vscode-pylance"],
"settings": {
"python.testing.pytestArgs": ["./webvh", "--no-cov"],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.testing.pytestPath": "pytest",
"editor.defaultFormatter": null,
"editor.formatOnSave": false, // enable per language
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.organizeImports": true
},
"editor.defaultFormatter": "charliermarsh.ruff",
"ruff.organizeImports": true
},
"ruff.codeAction.fixViolation": {
"enable": true
},
"ruff.fixAll": true,
"ruff.format.args": ["--config=./pyproject.toml"],
"ruff.lint.args": ["--config=./pyproject.toml"]
}
}
},

"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"moby": false
}
},

// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",

"remoteEnv": {
"RUST_LOG": "aries-askar::log::target=error"
},

"mounts": [],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [3000, 3001],
"postCreateCommand": "bash ./.devcontainer/post-install.sh"
}
11 changes: 11 additions & 0 deletions webvh/.devcontainer/post-install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
set -ex

# Convenience workspace directory for later use
WORKSPACE_DIR=$(pwd)

# install all ACA-Py requirements
python -m pip install --upgrade pip

# Generate Poetry Lock file
poetry lock --no-update
64 changes: 64 additions & 0 deletions webvh/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Run/Debug Witness",
"type": "debugpy",
"request": "launch",
"module": "acapy_agent",
"justMyCode": false,
"args": ["start", "--arg-file=${workspaceRoot}/docker/witness.yml"]
},
{
"name": "Run/Debug Multitenant",
"type": "debugpy",
"request": "launch",
"module": "acapy_agent",
"justMyCode": false,
"args": ["start", "--arg-file=${workspaceRoot}/docker/multitenant.yml"]
},
{
"name": "Run/Debug Controller",
"type": "debugpy",
"request": "launch",
"module": "acapy_agent",
"justMyCode": false,
"args": ["start", "--arg-file=${workspaceRoot}/docker/controller.yml"]
},
{
"name": "ruff - webvh",
"type": "debugpy",
"request": "launch",
"module": "ruff",
"console": "integratedTerminal",
"sudo": true,
"justMyCode": false,
"cwd": "${workspaceFolder}/webvh",
"args": ["check", "."]
},
{
"name": "ruff fix - webvh",
"type": "debugpy",
"request": "launch",
"module": "ruff",
"console": "integratedTerminal",
"sudo": true,
"justMyCode": false,
"cwd": "${workspaceFolder}/webvh",
"args": ["check", ".", "--fix"]
},
{
"name": "Python: Debug Tests",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"purpose": ["debug-test"],
"console": "integratedTerminal",
"justMyCode": false
}
]
}

197 changes: 197 additions & 0 deletions webvh/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# did:webvh Plugin

## Description

This plugin provides support for the webvh did method. It provides a controller role that interacts with a did webvh server to resolve and create dids, and a witness role that interacts with the did controller to sign did requests.

### Components
- `server` - The server component is responsible for handling requests from the did controller and witness components. It is responsible for verifying the upload requests are signed by proof a trusted source and hosting the did.json and did.jsonl files.
- `controller` - The controller is the agent that is responsible for the did. It can create and update webvh dids and anoncreds objects and interact with other agents. The controller does not have the ability to sign with the key that is verified by the server, and needs to get a proof from an agent which does have the correct key(s).
- `witness` - The witness is the agent that is responsible for signing requests from the controller. The witness has the ability to sign with the key that is verified by the server, and can provide a proof to the controller that it is a trusted source. It can also create dids and anoncreds objects itself and act as a controller by self signing the upload requests with the server.

#### Server
The server currently used by the plugin is located at https://github.com/decentralized-identity/didwebvh-server-py. The server currently contains a single public multikey that is created from the witness agent. It will only allow dids to be created where the original request is signed by that key. After the initial did is created the public multikey from the controller is obtained from the original request and stored by the server. Any updates to the did must be signed by the controller key.
Other implementations of the server are very much possible, but any servers the use this plugin much have the same API and verification process.

## Configuration

### Create the witness signing key
The first thing to do is setup the witness key that is used by the server to authenticate any new dids. In the witness agent it is identified using a key id (kid) `webvh:{server domain}@witnessKey`. You can create the key manually or it will be created automatically when using the `POST /did/webvh/configuration` endpoint.

Witness - `POST /did/webvh/configuration`
```json
{
"auto_attest": true,
"server_url": "https://id.test-suite.app",
"witness": true
}
```
- auto_attest - If true the witness will automatically sign any requests from the controller. If false the witness will need to sign the requests manually.
- server_url - The url of the server that the witness is using.
- witness - If true the agent will be setup as a witness agent.
- witness_key - If a public multikey is provided it will be used instead as the witness signing key.

### Connect the witness and controller agents

Create an invitation from the witness agent and accept it from the controller agent.

Witness - `POST /out-of-bound/create-invitation`
```json
{
"handshake_protocols": [
"https://didcomm.org/didexchange/1.1"
]
}
```
This is the most basic invitation that can be created. It is using didexchange 1.1 as the handshake protocol.

Response
```json
{
"state": "initial",
"trace": false,
"invi_msg_id": "e66babc0-420c-4d77-8f9b-82a3400eda78",
"oob_id": "7eea7ce9-4dbe-4b72-bb4d-af24c16d77a0",
"invitation": {
"@type": "https://didcomm.org/out-of-band/1.1/invitation",
"@id": "e66babc0-420c-4d77-8f9b-82a3400eda78",
"label": "webvh-witness",
"handshake_protocols": [
"https://didcomm.org/didexchange/1.1"
],
"services": [
{
"id": "#inline",
"type": "did-communication",
"recipientKeys": [
"did:key:z6MkqPPz5BSZrPr3se95qMToWeMa4ExeK9hu7JNfxnHtP7WB#z6MkqPPz5BSZrPr3se95qMToWeMa4ExeK9hu7JNfxnHtP7WB"
],
"serviceEndpoint": "http://localhost:3000"
}
]
},
"invitation_url": "http://localhost:3000?oob=eyJAdHlwZSI6ICJodHRwczovL2RpZGNvbW0ub3JnL291dC1vZi1iYW5kLzEuMS9pbnZpdGF0aW9uIiwgIkBpZCI6ICJlNjZiYWJjMC00MjBjLTRkNzctOGY5Yi04MmEzNDAwZWRhNzgiLCAibGFiZWwiOiAid2Vidmgtd2l0bmVzcyIsICJoYW5kc2hha2VfcHJvdG9jb2xzIjogWyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMSJdLCAic2VydmljZXMiOiBbeyJpZCI6ICIjaW5saW5lIiwgInR5cGUiOiAiZGlkLWNvbW11bmljYXRpb24iLCAicmVjaXBpZW50S2V5cyI6IFsiZGlkOmtleTp6Nk1rcVBQejVCU1pyUHIzc2U5NXFNVG9XZU1hNEV4ZUs5aHU3Sk5meG5IdFA3V0IjejZNa3FQUHo1QlNaclByM3NlOTVxTVRvV2VNYTRFeGVLOWh1N0pOZnhuSHRQN1dCIl0sICJzZXJ2aWNlRW5kcG9pbnQiOiAiaHR0cDovL2xvY2FsaG9zdDozMDAwIn1dfQ"
}
```
The controller will use the base64 encoded invitation_url to accept the invitation. In an application this could be provided as a QR code or a deep link.

The connection is identified in the controller by an alias. You are able to set this up manually or via command line. The easiest way is by providing it when configuring the controller.

Controller - `POST /did/webvh/configuration`
```json
{
"server_url": "https://id.test-suite.app",
"witness": false,
"witness_invitation": "http://localhost:3000?oob=eyJAdHlwZSI6ICJodHRwczovL2RpZGNvbW0ub3JnL291dC1vZi1iYW5kLzEuMS9pbnZpdGF0aW9uIiwgIkBpZCI6ICJlNjZiYWJjMC00MjBjLTRkNzctOGY5Yi04MmEzNDAwZWRhNzgiLCAibGFiZWwiOiAid2Vidmgtd2l0bmVzcyIsICJoYW5kc2hha2VfcHJvdG9jb2xzIjogWyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMSJdLCAic2VydmljZXMiOiBbeyJpZCI6ICIjaW5saW5lIiwgInR5cGUiOiAiZGlkLWNvbW11bmljYXRpb24iLCAicmVjaXBpZW50S2V5cyI6IFsiZGlkOmtleTp6Nk1rcVBQejVCU1pyUHIzc2U5NXFNVG9XZU1hNEV4ZUs5aHU3Sk5meG5IdFA3V0IjejZNa3FQUHo1QlNaclByM3NlOTVxTVRvV2VNYTRFeGVLOWh1N0pOZnhuSHRQN1dCIl0sICJzZXJ2aWNlRW5kcG9pbnQiOiAiaHR0cDovL2xvY2FsaG9zdDozMDAwIn1dfQ"
}
```
You should get a status success response and the controller logs should say `Connected to witness agent`

### Auto attest

This setting should be used with caution as it will automatically sign any requests from the controller. If you are using this setting it should be for testing purposes, or you should be sure any agent that creates a connection with the witness agent is trusted.

Controller - `POST /did/webvh/create`
```json
{
"options": {
"identifier": "accounting",
"namespace": "finance",
"parameters": {
"portable": false,
"prerotation": false
}
}
}
```
- identifier - The identifier for the did. If this isn't provided it will be a randomly generated uuid.
- namespace - This is required and is the root identifier for the did.
- parameters - This is an optional object that can be used to set the did to be portable or prerotated. If portable is true the did will be able to be moved to another server. If prerotation is true the did will be able to be rotated by the controller.

Response - Unless there's a problem connecting with the witness or server you should get a success response with the did document.
```json
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "did:webvh:QmQ3m3nAL8Ds7bpnHHbiPZsSs9x6RmMJXomNYHgMrmghnU:id.test-suite.app:finance:accounting",
"authentication": [
"did:webvh:QmQ3m3nAL8Ds7bpnHHbiPZsSs9x6RmMJXomNYHgMrmghnU:id.test-suite.app:finance:accounting#key-01"
],
"assertionMethod": [
"did:webvh:QmQ3m3nAL8Ds7bpnHHbiPZsSs9x6RmMJXomNYHgMrmghnU:id.test-suite.app:finance:accounting#key-01"
],
"verificationMethod": [
{
"id": "did:webvh:QmQ3m3nAL8Ds7bpnHHbiPZsSs9x6RmMJXomNYHgMrmghnU:id.test-suite.app:finance:accounting#key-01",
"type": "Multikey",
"controller": "did:webvh:QmQ3m3nAL8Ds7bpnHHbiPZsSs9x6RmMJXomNYHgMrmghnU:id.test-suite.app:finance:accounting",
"publicKeyMultibase": "z6Mknsk9KAs7UofpuZsuSzBkmxZjo63WRwAAj1mnifkVLhqh"
}
]
}
```

### Manual attest

Controller - Create did:webvh same as above

```json
{
"status": "pending",
"message": "The witness is pending."
}
```

Witness get pending - `GET /did/webvh/pending`
```json
{
"results": [
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/multikey/v1"
],
"id": "did:web:id.test-suite.app:finance:cfbac7a9-0e0c-4bd8-af71-05e33f9e47a5",
"verificationMethod": [
{
"id": "did:web:id.test-suite.app:finance:cfbac7a9-0e0c-4bd8-af71-05e33f9e47a5#key-01",
"type": "Multikey",
"controller": "did:web:id.test-suite.app:finance:cfbac7a9-0e0c-4bd8-af71-05e33f9e47a5",
"publicKeyMultibase": "z6Mkv4ZvmGpzfkxH9xvNq5mA3zwZoHuBisiQUyfCgXCfHeh4"
}
],
"authentication": [
"did:web:id.test-suite.app:finance:cfbac7a9-0e0c-4bd8-af71-05e33f9e47a5#key-01"
],
"assertionMethod": [
"did:web:id.test-suite.app:finance:cfbac7a9-0e0c-4bd8-af71-05e33f9e47a5#key-01"
],
"proof": [
{
"type": "DataIntegrityProof",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:key:z6MkkiMtuEqx8NJcJTTWANmwfpAxZM54jy9Sv867xCN63tpT#z6MkkiMtuEqx8NJcJTTWANmwfpAxZM54jy9Sv867xCN63tpT",
"cryptosuite": "eddsa-jcs-2022",
"expires": "2025-02-20T22:43:40+00:00",
"domain": "id.test-suite.app",
"challenge": "6c0bbc23-be56-5f35-b873-3313c33b319b",
"proofValue": "z9T5HpCDZVZ1c3LgM5ctrYPm2erJR8Ww9o369577beiHc4Dz49See8t78VioPDt76AbRP7r2DnesezY4dBxYTVQ7"
}
]
}
]
}
```
Gets a list of pending did docs that need to be attested.

Witness - Attest a did doc - `POST /did/webvh/attest?id=did:web:id.test-suite.app:finance:cfbac7a9-0e0c-4bd8-af71-05e33f9e47a5`
```json
{
"status": "success",
"message": "Witness successful."
}
```

Controller - The controller gets a message `Received witness response: attested` and will finish creating the did. The did should now be resolvable and available in local storage.
Loading

0 comments on commit 0c8f4e0

Please sign in to comment.