This page documents basic wallet implementation for aries-framework-go covering universal wallet 2020 interfaces.
Some useful links
- Universal Wallet 2020
- Initial Proposal for Universal wallet 2020
- Presentation Exchange
High-level Framework Architecture
Aries Framework Go wallet has plugin based architecture which can be used to replace specific features to customize a wallet. Features like KMS, VDR, storage provider etc
Initialize wallet:
option 1 : If "wallet per agent instance" approach to be used for aries-framework-go, all additional wallet specific initialization steps like creating keys, DIDs can be either performed during very first access to any of the below interface functions or it can be done using a dedicated initialization method.
option 2: If "multiple wallets per agent instance" approach to be used. Then challenges in handling data leaks between wallet users to be discussed.
For managing wallet using wallet server, we should support creating multiple wallet user profiles in single agent instance (i.e multiple kms & multi user EDV).
- localkms to support name spacing
- EDV store to provide vault id based support
Use did:key as default DID plugin for initializing DIDs and keys (for import/export).
For credential issuer/prove/verify interfaces, options like verification method, controller etc will be used.
Wallet core features:
Basic wallet features independent of wallet types (like VC wallet, currency wallet etc) will be part of core interface.
- export produces serialized wallet representation which will be encrypted without leaking any information about wallet contents (not even count).
The serialized output will be in the form of VC (refer: https://w3c-ccg.github.io/universal-wallet-interop-spec/contexts/wallet-v1.json)
Sample: exported-wallet.json - import loads serialized representation into wallet. This operation should have the knowledge of key or password used to export wallet contents.
Sample: imported-wallet.json Lock: transforms wallet contents from plaintext to ciphertext.Sample: locked-wallet.jsonUnlock: transforms wallet contents from ciphertext to plaintext. Needs knowledge of key/password used to lock the wallet.Sample: unlocked-wallet.json
Note: we are going to support only export and import options. Since exported wallets are always locked, no need to have explicit lock/unlock wallet interfaces.
API Dependencies:
- KMS: use key plugin for cryptographic operations, if not provided then fallback to aries-framework-go kms api.
- VDRI: use DID plugin, if not provided then fallback to aries-framework-go vdri api.
Questions:
Does aries wallet really needs universal wallet lock/unlock feature?
→ Lock/Unlock features are only suitable for wallets having local wallet content storages. In case of remote wallet content storage like EDV, there is no need of converting wallet contents to ciphertext (lock) or back to plaintext (unlock). But to support interoperability wallet might have to specify its state as 'LOCKED' or 'UNLOCKED', so that serialized representation of exported wallet can be imported into any wallet with local content storage.- Should we provide password in each api call as given in specification?
→ Password seems too specific, an issue to be opened to update specifications to include any kind of auth tokens.
VC wallet features:
VC plugin adds verifiable credential features to the wallet. By default aries-framework-go verifiable command features will be used for creating and verifying credentials/presentations.
The additional interface 'presentationSubmission' can be used to submit presentation definitions to the wallet and to get presentation submission as response.
- Verify: verifies a verifiable credential or a verifiable presentation.
- Issue: adds proof to a verifiable credential.
- Prove: creates a verifiable presentation (adding proof to presentation).
- PresentationExchange & QueryByFrame: will be part of Query interface.
API Dependencies:
- KMS: use key plugin for cryptographic operations, if not provided then fallback to aries-framework-go kms api.
- VDRI: use DID plugin, if not provided then fallback to aries-framework-go vdri api.
Questions:
Why we need a new query interface for querying VCs using presentation exchange? Why can't we use existing 'query' interface from store plugin?→ 'add' interface function from store plugin can be used to add any data model. Modifying 'query' interface to support presentation exchange may increase the complexity for non-VC data model users.
RESOLVED IN SPEC: query interface can be customized to match underlying wallet implementation.
Plugins: Non core interfaces (need not to be exported)
Key plugin:
Key plugin provides 2 interfaces : verifyRaw & signRaw. Framework will use aries-framework-go kms provider for these wallet features.
This plugins can be injected to customize the wallet to use other kms implementations like webkms.
API Dependencies:
- KMS: use key plugin for cryptographic operations, if not provided then fallback to aries-framework-go kms api.
Store plugin:
Store plugins adds features for maintaining wallet content stores. Framework will use aries storage provider for these wallet features.
Store plugin should be able to add/remove/query all data models from universal wallet specifications. (Note: add/remove/query interfaces should be generic enough to support all data models)
This plugin can be injected to customize the wallet to use custom storage providers like encrypted data vaults.
Questions:
- As per specifications for query interface, how can we use map and reduce functional arguments effectively for REST bindings?
→ we can use functional arguments in JS bindings & SDK bindings. But REST & mobile bindings it needs to be modified to support some sort of generic query feature.
DID plugin:
Unlike other plugins, DID plugin functions won't be part of exposed wallet APIs, since aries-framework-go already has vdri interfaces exposed.
This plugin can only be used to inject custom DID features like using custom did methods for wallet operations.
Questions:
- Why can't we get rid of this plugin and use ask client's to use their customized aries framework go vdri.
→ to be decided during design discussion
Bindings
aries-framework-go wallet is going to be available in all the bindings - Go SDK, REST, JS & Mobile
User Profile Design
In addition to SDK, VC wallet can also be hosted in a server (aries command REST binding), WASM (aries JS binding), mobile (aries mobile binding). Care should be able to support multiple users with separate kms & partitioned stores.
In order to do that we have to introduce 2 APIs for creating and request profiles
- createProfile: This API creates user's wallet profile and returns info of profile created (ID and any other information needed by client). It returns error if wallet profile is already created or if profile creation fails.
Here are the arguments that can be used to create user profile- username: unique loginname to identity user. This parameter will also be used as db namespace,
- remoteKMS options:
- key server URL: webkms key server URI
- local KMS options:
- passphrase: secret in case of localkms. VC wallet will create `hkdf` masterlocker(secret lock service) using this passphrase to encrypt master key.
- secret lock service: (for SDK binding only), If client doesn't want to share passphrase then client can provide secret lock service which will be used by VCwallet to encrypt master key.
- getProfile: Takes a username string and returns profile info containing profile ID or any other information needed for client.
- updateProfile: Client can change its KMS settings anytime by using update profile. Wallet contents will be preserved, but client may lose its keys depending on KMS setting updates.
For example, client changes its passphrase in case of localkms or secret service.
Open & Close wallet APIs (need naming suggestions):
Since profile KMS requires locking/unlocking features, it is not a good idea to expect user kms secret/token in each wallet api calls due to below reasons.
- complexity of handling secrets in each API calls.
- not user friendly
- creating KMS instance per user for each API call is expensive operation.
Solution: client has to unlock the wallet before calling any wallet interface APIs and lock the wallet back done. Wallet will also auto lock if unused for certain amount of time.
This leads to introduction of 2 more APIs given below:
- Open wallet:
- In case of local KMS,
- Supply passphrase or secret lock service to 'Open wallet API' to unlock master lock and initialize aries local KMS instance.
- This KMS instance will be kept in cache till the expiry duration provided by client.
- This token has to be supplied by client while calling each VC wallet APIs. Once token expires cache gets cleared and kms instance will be destroyed, then client has to unlock it again to get new token.
- Calling unlock on already unlocked wallet will return error "Profile already unlocked", if client loses/compromises token then he/she has to lock the wallet to destroy kms instance and has to open wallet again to get new token.
- In case of remote KMS,
- Supply auth token to unlock the wallet which will initialize aries remote KMS instance. Auth token will be part of remotekms instance's header function which will be remembered for all KMS operation till token expires.
- This KMS instance will be kept in cache till the expiry duration provided by client.
- This token has to be supplied by client while calling each VC wallet APIs. Once token expires cache gets cleared and kms instance will be destroyed, then client has to unlock it again to get new token.
- Calling unlock on already unlocked wallet will return error "Profile already unlocked", if client loses/compromises token then he/she has to lock the wallet to destroy kms instance and has to open wallet again to get new token.
- In case of local KMS,
- Close wallet: Can be called by user to lock the wallet back, recommended during wallet logout. Wallet will be closed by itself when previously issued token expires. Calling close on already closed wallet will not return any error.