A commandline tool that simulates a wallet which can hold and interact with verifiable credentials
The wallet is meant as a tool for develolopers and implementors of verifiable credential services.
WIP. Currently there's still just a single command, but once that is working through the happy path, we will split it up into smaller commands.
Planned commands are:
-
vc-wallet offer
- given a credential offer, resolves it if necessary, and prints a normalized offer to stdout. Amongst the information is:- Whether the offer is by value or by reference
- Whether the credential request goes via the Authorization Code Flow or is pre-authorized
- Any potential pre-shared secrets, or requirement thereof
- The credential type, types or credentials in the offer
- It returns the issuer url
-
vc-wallet issuer
- given a normalized offer, or an issuer URL, requests issuer metadata and shows- possible Proof types and algorithms the issuer supports
- issuers' authorization server if set
- issuers' endpoint
- issuers' DID
- issuers' public key(s)
- issuers' supported credential types.
-
vc-wallet authorize
- given a the url of the authorization server,- print the authorization URL to stdout
- start a local webserver to receive the callback
- Allow the user to choose the callback url with host, port and path that the listener will bind to
- exchange the authorization code for an access token
- print the resulting access token to stdout on success
- print the error to stderr on failure
-
vc-wallet request
- given a normalized offer and one of below, requests the credential from the issuer- EITHER an access token,
- OR a pre-shared secret
- allow the user to choose a proof type and algorithm using a commandline argument
- show the user the proof that will be sent to the issuer
- request the credential from the issuer
- print the credential to stdout
-
vc-wallet verify
- given a credential, verifies the proof and the credential- show the user the proof that was sent by the issuer
- verify the proof
- verify the credential
- print the verification results to stdout
-
vc-wallet present
- given a presentation request, shows the user credentials that can be offered- show the user the presentation request
- show the user the credentials that can be offered from a glob, directory or list of credentials in JSON on disk
- allow the user to pick a credential to offer
- check if the credential can be offered according to the request
- show the user the data that will be sent to the verifier
- send the proof and credential to the verifier
-
vc-wallet interactive
- given only a credential offer, walk the user through the entire flow.- On each step, show the user what has been resolved, which calls were made,
- what the next step will be with a prompt to continue or abort.
- For each step, ask the user what values and choices they must provide.
- Show the user the contents of the final credential and the proof.
Other TODOs and fixes, aside from the abovementioned commands and features:
- Move
issuer_state
from Credential Request to Authorization Request. - Make
issuer_state
required when it is in the offer. - Move KEYPAIR and DIDKEY to commandline arguments - potentially with reference to a file rather than the value itself. Could default to a known location on disk.
- Have
issuer-metadata
try several URLS and pick the first one that resolves rather than only .well-known/openid-credential-issuer
- A user should be able to follow the flow and steps very clearly.
- Any options or choices should be left to the user to choose.
- Any error or possible mistake should lead to immediate termination with clear errors.
- Any error that indicates a misconfigured issuer, or other service, but that can be recovered from, should be logged and the user prompted with options to fix it.
- Third party libraries should be wrapped in a way that they adhere to these above design goals.
- Results should be printed to stdout as plain text or json.
- Commands that take an input, should take it from stdin.
- The wallet is entirely stateless. Any state needed for signing, listing, requesting must be passed into the commands as input.
- We support only the latest versions of specs.
- It is not a benchmark or test suite to check compliance with specifications.
- It does not implement all options and all features, but it may.
- Features are only implemented if someone needs them, not just because a spec says that something (optional) could be considered.
- There is no secure storage, nor any data encryption.
- We don't generate keys, certificates, JWTs, JWKs or DIDs. We assume the user has them.
- Do we want to interactivly prompt a user, or rather take commandline arguments?
- Do we want multiple small that can be piped and if so, how do we deal with the more complex flows that would chain together these flows conditionally? Maybe offer both?
- Do we want to support all possible signing algorithms, and proof types or only the most common ones?
- Do we want to support all possible flows, or only the most common ones?
- Do we want to support all possible credential types, or only the most common ones?
- Do we want to add checks or limations to High Assurance Interoperability Profile (HAIP)?
- Do we want to add checks or limitations to Decentralized Identity Interoperability Profile (DID)
- Resolve and "normalize" the offer-by-reference to a full offer.
- Determine wether we have an authorized code flow or a pre-authorized flow.
- Visualize the progress of the flow in a sequence diagram or similar in the terminal.
- Determine the issuers capabilities wrt to proof types and algorithms, fail if we can't provide the right proof, and offer cli-options to provide one proof when we support more.
- Deferred Credential Requests
- Encrypted Credential Responses
- Implement VCs using JSON-LD
- Implement VCs using ISO mDL
- Implement VCs using IETF SD-JWT VC
The wallet is stateless, but you might want to store some data, like keys, certificates, JWTs, JWKs or DIDs.
We currently use environment variables to store this data. In future this will be moved to commmandline arguments.
You can use the provided .env.template: Copy it to .env and fill in the values. The .env file is ignored by git, so you can safely store your secrets there.
NOTE: We do not load the .env file automatically, you have to do that yourself. Use e.g. zenv or any runner that can load .env files.
When retrieving a Verifiable Credential, the wallet will provide a Proof of Possession and key material to the issuer.
The spec allows several types and structures. We limit ourselves to the following:
- Only one proof, we don't support multiple proofs.
- Only the JWT proof type.
- Key generated with ed25519 algorithm.
- A did:key DID.
- Install didkit
- Generate a key with didkit
didkit key generate ed25519 > keys/key.json
- Convert the key to a did:key DID
didkit key to did --key-path keys/key.json > keys/did.txt
- Store the keypair json and the did:key in ENV vars, so the wallet can use them.
4.1. as ENV vars
export KEYPAIR=$(cat keys/key.json) export DIDKEY=$(cat keys/did.txt)
4.2. in .env file
bash echo "KEYPAIR=$(cat keys/key.json | tr -d \"\n")" >> .env echo "DIDKEY=$(cat keys/did.txt)" >> .env
TODO: implement arguments to pass the keypair and did:key as input to the commands. NOTE: The wallet is stateless, so the keypair and did:key must be provided as input to the commands. For now, we pass them, using ENV vars.