# Securing delegate signing with web3
Open: 2022-08-07
Closed:
# **Problem Statement:**
When we register a DID for someone, we
* create a DID using did:ethr
* create a delegate key signing pair
* register that key pair with the Ethereum DID registry SC
* store the keypair in an V3 wallet
* protect access to the Ethereum V3 wallet with a password from/for the user
When the user uses this DID to sign VCs:
* we ask user for his password
* use that to open the V3 wallet with the password and then
* pass the command for the delegate signature of the VC to the wallet.
**Problem:**
1. end to end this only as secure as the password
2. there is no actual web3 signature by the user himself
3. we do not have a web3 tranaction (on e.g. Etherscan) proving that the user actually signed the VC
# **Proposal**
Our backend keeps a mapping of web3 identity to delegate key.
Based on the mapping of
wallet <-> DID
through the convention of DID=did:ethr:$network:wallet
we always ask the user to confirm/sign a web3 transaction before we use that wallet to trigger the DID signing procedure.
**How to secure the V3 wallet**
On the code level this is done through
```
const walletFromKeystore = await EthWallet.fromV3(keystore, 'PASSWORD');
const privateKey = walletFromKeystore.getPrivateKeyString();
```
Instead of asking the user to set the password, we manage the password internally.
Steps:
1. pick a very long and hard password and use that to protect the V3 wallet
2. We encrypt and store this password at the server side
3. We also set up a simple smart contract "web32VC.sol" where users confirm signing of a VC through a web3 transaction with that smart contract. See below ("websig4VC")
**NOTE**
This means the security is now as strong as our secure storage.
**TODO**
In the future this must move to a full custodian wallet for this.
# **User flow: create DID**
1. User creates $DID
2. we create $delegateKeys for $DID
3. we set password
4. we encrypt (symmetric) and store password locally in $passwordFile
5. we need to manage the key for this symmetric encryption through server-side security. This is now the security anchor of the interaction (see TODO).
6. we map user $wallet to user $DID to $passwordFile
# **User flow: use DID to sign VC**
1. User comes to web3 page for DID transactions
2. User connects using web3 --> we identify $wallet and $DID
3. User chooses, e.g to issue VC on Energy Certificates
4. Based on $wallet --> $DID we retrieve password from V3 enrypted storage
5. We use the V3 wallet to retrieve $delegateKeys and have $DID issue the VC
6. we store VC on IPFS and retrieve the $VChashIPFS
7. "web3sig4VC": we present VC to user and ask him to confirm by calling web32VC.confirmVC($VChashIPFS)
# **Security**
The solution (without a custodian wallet) is now based on server-side secure encryption and storage of the password needed to retrieve the delegate key.
This is a small but not fundamental improvement in security.
We will need to improve this by using a Secure Enclave in the future
# **Usability and web3 conformity**
User flow and signature sequence is now fully web3 end to end.
Furthermore we have a valid web3 transaction confirming the user signing the VC with their web3 wallet
# **Summary**
We have proposed a solution to avoid using passwords input by the user to act as the security anchor for the signing of a VC.
We have ensured that every VC is confirmed by the user with a fully validated web3 transaction.
In the transaction we pass the IPFS hash which can be used to terieve the VC from IPFS.
:::info
White:
I agree
* We can use **web3 login** and **encrypt a long password** instead of asking user to input a DID-password<br/> ( ps. This was never in our POC before, of course we can do it, but we need time to study on web3 login )
debate
* We don't need `SC:web32VC.sol`. Since in [did-jwt-vc](https://github.com/decentralized-identity/did-jwt-vc) lib, when we call `verifyCredential`, it will refer to VC.iss to search the DID from `EtherDIDRegistry.sol` and verify it.<br/>Pls refer [the code snippet](https://github.com/decentralized-identity/did-jwt/blob/master/src/JWT.ts#L350) in **did-jwt**.<br/><br/>If we create our own `web32VC.sol`, I will consider it is just a add-on which can have a **double-check** for VC-issuer. It's one of our preference.<br/><br/>We must also think about how to deal with the delegate signer **expired time** in `web32VC.sol`.<br/><br/>so for confirm, do we want this ?
I draw **the following sequenceDiagrams** from my understanding, pls confirm, thanks!
:::
### Create DID
```mermaid
sequenceDiagram
participant User as User
participant FE as FE:DIDregister
participant Registry as SC:DIDregistry
participant API as DID API
User->>FE: 1. Web3 login
User->>FE: 2-1. register DID
FE->>FE: generate DID
FE->>Registry: 2-2. register DID
FE->>API: 3. store DID
API->>API: encrypt pwd, store pwd and keystore to DB
```
### use DID to sign VC
```mermaid
sequenceDiagram
participant User as User
participant FE as FE:signVC
participant BE as BE:API
participant SC as SC:web32VC
User->>FE: 1. Web3 login
FE->>BE: 2. get DID by wallet
BE->>BE: retrieve keystore and encrypted pwd from DB
BE->>BE: decrypt pwd, retrieve DID by pwd
BE-->>FE: return DID
User->>FE: 3-1. sign VC
FE->BE: 3-2. store VC as https-url
FE->>User: 4. present VC, ask to confirm by a txn (optional)
User->>FE: confirm txn
FE->>SC: confirmVC
```
:::info
White:
Questions to clarify:
* VC-link should be a **https-link** or **IPFS-link** ?
* The password will be encrypted/decrypted by a **symmetric/invertable key** (ex. AES), am I correct ?
* $passwordFile means the V3 keystore ?
* Shall we create `web32VC.sol` ?
* If we need to do **web3 login**, the FE is from NRVerse, some of BE is from us, we need to plan/think about **how to integrate** and this part is important but never be clarified at present.
* A basic question from Jan and confirm by KoolTech:<br/>Is **generate VC for NFTicket** an explicit requirement OR an optinoal/additional cool feature ? (Since we need to make sure our time is enough to complete MVP)
* *`encrypt (symmetric) and store password locally in $passwordFile`* -> **locally** means FE or DB ?
:::
:::success
Hary: (2022/08/08)
HI Guo, White: I like the response and we are almost (90%) agreed based on this.
Re. web3 login: that is simply one line of code by which the user connects (use the code from Investor Portal. Cheng, Kenny and Jake know where that is.
I suggest we take care of that code (take it from the investor portal) and simply package it as NFTicketWeb3 library and let NRVerse use it at that high(er) level.
Encryption of pwd: yes, symmetric e.g. AES256
Re. **generate VC for NFTicket** an explicit requirement or OPTIONAL:
It is in a way optional. It is however already in place, so no further work needed EXCEPT the proposal we are discussing.
If we really run into time issues, I can agree to go live based on the current (password-protected delegate signing) code. It would however be (one of) the first developments after the go live.
On
"We don’t need `SC:web32VC.sol`. Since in **did-jwt-vc** lib, when we call verifyCredential, it will refer to VC.iss to search the DID from `EtherDIDRegistry.sol` and verify it.
Pls refer the code snippet in did-jwt.
If we create our own `web32VC.sol`, I will consider it is just a add-on which can have a double-check for VC-issuer. It’s one of our preference."
Two questions:
1. I don't understand how teh code snippet yoou refer helps in giving us a Blockchain transaction
2. proving the customer wallet (NOT the password-protected delegate wallet) having confirmed the VC.
3. "It’s one of our preference.": what is of your preference. I am not sure I understand your direction. Pls. also explain why
:::