Multiple whisper and wallet keys


#1

Hello everyone,
we had a lot of discussions about decoupling the whisper and wallet key after this topic and now we need to implement it to be able to finish the hardware wallet implementation, so that wallet keys remain on the card, and whisper keys can be downloaded to the phone during a session to be able to encrypt/decrypt messages.

The big change will be that the wallet address won’t be derivable from the whisper identity (public key), so without supporting multiple wallets it won’t be possible to send/receive a transaction in a chat without asking for the wallet address with some kind of interaction.

The options that we have are:

1 - updating the chat protocol so that user A can send a wallet address request to user B. User B can accept and reveal its address. User A receives the address and can now send the transaction.

2 - update status-go to and status-react to support multiple wallets and whisper identities. At this point it would be possible to send a chat transaction without interaction, and user B will receive the transaction in the chat address without revealing the main wallet. User B will be able to manage standard BIP44 wallets + the ones derived from the whisper identities.

3 - combine option 1 and 2 so that the whisper and wallet keys are decoupled and chat transactions are sent to the right wallet address.


Since we want to support multiple identities anyway, I think options 2 and 3 are the best ones; option 1 would only be temporary.

If we agree on supporting multiple wallet/whisper keys (sub-accounts) for each account the steps I would like to work on are:

1 - update our go-ethereum patches to save the BIP44 parent key in the main accout keystore file. This will allow to create sub-accounts that are BIP44 compatible. In the current implementation we save the second BIP44 key as a parent extended key to derive sub-accounts, but those addresses will end up having a non-standard derivation path m/44'/60'/0'/0/1/n (where n is the index of the sub-account).

2 - update status-go account creation to create 2 initial key pairs for each account. One for the wallet and one for whisper using a different path that we are trying to propose in the EIPs repository. Each key pair will have an extended key to derive sub wallet/whisper identities.

At this point status-react should be able to create multiple identities using the parent extended key saved in the main account key-pairs, and show multiple wallets.

If we want to implement only the options 2, we only need some support from the wallet team. In case we want to support 1 or 3, we need more support and changes from the chat team as well.

What do you think about it?


#2

Me and Andrei had a talk to today about this (in terms of the identity).

The diagram we used to reference was this one:

We concluded that for now, it is probably best if we ignore the “multiple identity” aspect of creating profiles around various whisper keys within a single 12-word recovery phrase, and to make it easier to manage multiple “accounts” (12 word recovery phrases).

This means we still need to separate the whisper key from the wallet key, which means what you’re are discussing here is all still relevant, just wanted to mention that detail.

I feel that keeping the two master keys (wallet and whisper) so that the option to derive sub accounts is a good one, but to only have a single profile around an “account” (12-word recovery phrase). This also allows us to have multiple wallet addresses, which is reasonable based on human-requirements for various collections of money and various security risks…

for example, I’d want my public profile to be linked by default to a “hot wallet” type account while still being able to manage a “safe - funds” type account.


#3

Thank you @petty! Yes I agree if we keep just one whisper identity it’s easier. And having the parent of that key allows us having multiple identities in the future.
I also confirm that the whisper and wallet parent keys are derived from the same 12 mnemonic words.

What we need to decide now is where to send tokens in chat transactions, since whisper and wallet keys are different.

1 - update protocol to implement an address request so that I can send you tokens in your BIP44 wallet, that is not derivable from the public key you use to chat.

2 - having multiple BIP44 wallets + 1 wallet with address derived from the whisper key, so that I can send you tokens deriving an address from your contact ID, and then you can move those funds to another standard wallet. this “whisper wallet” won’t be visible if you import your status account in metamask.


#4

I’m strongly for option number 1.

This increases compatibility across wallets, and doesn’t have a deterministic way for someone to get to a wallet address from a contact ID.

Option 1 also allows you to set the exposure you want in your profile.


#5

For sure this solution is the best one for privacy and security, and it doesn’t add complexity for the user experience.

I agree to implement this, but we need now to plan how to change the chat protocol.
I had a call with @goranjovic now so I think he will summarize the options here.


#6

Just an idea, but have folks thought about inverting this assumed relationship?

What if the master key wasn’t the Chat key, but rather the Wallet key was the master key and the chat key was derived at a perhaps fixed offset from the Wallet key. Since the derived key can’t lead back to the master key this seems like an interesting way of looking at it, that may present some new possibilities. I think??

Just had a chat with Cori and he cleared things up for me.


#7

Summary of the call with @gravityblast

Right now we use the same private key for both whisper messages and wallet transactions. This is the key that’s going to be stored in the Status keycard.
The idea is that once installed, this key would never be copied from the keycard. Instead every time user has to sign a transaction, the card would do the signing. That works fine for wallet transactions.

The problem starts when we need to sign and decrypt whisper messages. If we wanted to do the same thing for chat messages, users would need to practically keep the card right next to the phone as long as they are chatting. This would completely break the security model that keycard offers, as one of the main assumptions it depends on is that users would keep phone and keycard apart most of the time. Also, signing and decrypting whisper messages through keycard would be extremely slow, due to technical limitations.

So, the only way to effectively use chat is to keep the key in the phone, at least in memory, but that would obviously defeat the purpose of using a keycard.

We’ve entertained several possible solutions:

  1. Wallet-only accounts with Keycard

If the problem is only with whisper, we can remove disable Chat feature for accounts with keys managed by Keycard. So, we’d be able to log in to the app and sign transactions in both Wallet and Browser using the Keycard. But not send or receive any whisper messages. This is the extremely conservative solution.

  1. Separate keys for Chat and Wallet

Both keys stored on Keycard. Wallet key never leaves the card, instead card does the signing. Whisper key copied to the phone memory upon login, to let the app sign and decrypt the messages, but not persisted on the phone.

Here we have several sub-options:

  • One wallet identity without whisper and one whisper identity without a wallet

Wallet key would be stored and always kept in keycard. Whisper key would be stored on keycard, but copied to app upon login. In this case participants would need to exchange their wallet addresses prior to being able to /send assets in chat.

  • Multiple Wallet identities, exactly one of which also has a whisper identity derived from the same key

In this case, keys for all identities would be stored in the keycard. Wallet-only keys would only be kept in the card, and card would handle transaction signing. The one key that’s used for both Chat and Wallet would be copied to the phone upon login. One consequence is that whisper messages can be exchanged without a constant presence of keycard around. Other consequence is that transaction signing can also be done without the keycard in the case of this one particular wallet.

The purpose of the extra Wallet which is associated with whisper is only to receive any assets sent via chat and to send any assets to chat participants. This wallet is to be considered as more “warm” than cold, even when account is secured with a keycard. We need a good name for it - to set it apart from other, non-exposed wallets.


#8

It is imperative that we have a complete separation of the wallet keys and the chat keys. In my very strong opinion, option 2 is the only option. It should operate just as the graphic above (excluding the “anonymous profiles” section which is being taken out).

The best option for the keycard is the first bulletpoint of option 2. Tapping for transactions using the wallet, and loging in and keeping the whisper key in memory, but not persisting. This allows us to separately optimize for the functionality / security / privacy of each very different function, and not tie them together. This also works with the proposed EIP of setting paths for non-wallet keys, and should future proof cross-compatibility if people start using the derived keys of wallet paths for more wallets later down the line. It also allows us to introduce multiple identities later on if we so choose to. It also allows us to have multiple wallet accounts for various reasons (and permissions), and the option for the user to choose which one is automatically attached to the whisper key for chat send/receiving (default wallet option).

Remember that receiving only requires an address, and not the keys associated with it. So we can simply assign a “default” address to a whisper key and receiving functionality is available, whereas the sending functionality is all local and appropriate to do with the keycard in hand.

I will update the graphic to be in line with all of this.


#9

Here is an updated diagram based on these changes, please comment and let me know what needs to be changed, edited.


#10

Thank you @petty, that chart is really useful!

This are the steps I’m already implementing for the decoupling

https://notes.status.im/xIn9qA-3SWCbp7jkJCJjOg

Note that this is only for the decoupling, it doesn’t involve the Keycard.
For anyone interested, please help with ideas on point 6 of that document (" Sharing Wallet Address for in-chat Transactions.").


#11

for point 6 I would go for option 2, disclosing on demand sounds better to me, and also allows us to for example to have wallets not tight to status for example (say I send you my ledger address instead), but adds a barrier on sending transactions potentially,

or we could have a mixture of the two (advertise in public messages/contact requests, send back an address when requested), as option one does not completely solves the issue, for example if they add me as a contact through their pk, I won’t have the wallet address until a message is sent back.


#12

good points!

If I request your wallet address, shall I save it to in my address book or shall I request the address every time I need to send a transaction?


#13

I guess once is out no need to ask for it again, otherwise it would cause quite a lot of friction, but we likely want to give the user a way to notify of changes in their wallet address (say you lost access for whatever reason).

But I am so far from wallet usage that my opinion is probably not well informed, @goranjovic what are your thoughts?


#14

I would avoid having “external” addresses and just use the first standard BIP44 wallet that’s derived from the same mnemonic of the whisper key.


#15

just out of curiosity, how does it work if a user doesn’t have a keycard?


#16

Given the additional steps we’re proposing to overall experience by decoupling keys, I’d advocate for saving the wallet address to my address book once requested and not have to to repeat this request each time I want to send a transaction. It’s also understandable (imo) if something happens to Alice’s account that I would need to send a new request.


#17

We talked about it in the dev meeting but I add the answer here as well.
Even without using the Keycard, at account creation/recovery we will generate 2 keys. The first one is the one we have now, used for transactions. The second one will be injected in whisper.
The only difference with the keycard is that the wallet key doesn’t leave the card.


#18

Key migration

The migration to separate whisper key is a breaking change, and would be important to have a defined “protocol” on how to handle this with users and informing correctly the impacts of the change.

Changeing the communication key impacts in:

  1. History of messages
    • might cause confusion in the information (but the data should be consistent);
    • the information consistency could be kept by exporting the contacts data and use this snapshot to compare older messages.
  2. Public contact code
    • will need that Status usernames update their contact code in the registry;
    • if we have gas abstraction, status could cover those costs with security (one time per address).

Changing the payment key impacts in:

  1. Ownership of assets ETH:
    • ETH;
    • multiple ERC20 classes;
    • multiple NFTs units and classes.
  2. Ownership of Contracts:
    • multisigs;
    • ENS nodes.

I think that migration of account keys are more breaking then the migration of whisper keys, and we should only migrate account keys if needed, and perhaps don’t force it (but opt-in).

Account contracts

I think this should be done only once, and when we migrate to an Account Contract that can be updated by user, like: https://github.com/status-im/snt-gas-relay/blob/improvements/test-dapp/contracts/deploy/DelayedUpdatableInstance.sol)

An account contract is an contract which is capable of executing transactions using a set of controlled user instructions (e.g. multisig, gas relay)

Universal Logins

Universal logins will help managing the user whisper keys and wallet access, removing the hurdle of upgrading contact code on ENS Usernames for new whisper key, or the transfer of assets for new account key.

Proposed account contract https://github.com/status-im/snt-gas-relay/blob/improvements/test-dapp/contracts/identity/Identity.sol

Whisper Keys on Identity

The keys listed by this Identity contract could be used to make messages linkable to a single Identity, even if the user changes the message key.
User configures public whisper key: Identity.addKey(whisperKeyHash, ENCRYPTION_KEY, keyType);
User replaces public whisper key:
Identity.replaceKey(oldWhisperKeyHash, newWhisperKeyHash, newKeyType);

User sends a public whisper message:
<msg regular payload> + <address of identity>

Account keys on Identity

Account keys would allow the access of inchain permission to call in Account Contract.
This account key would be held by Keycard and would have the permission to change the “whisper keys”.

EIP 1581

This helps with what we need, and interopreability is under Status Priciples, but we should be careful if it breaks other priciples, as Privacy.
Overall this EIP LGTM.


#19

#20

Thank you @ricardo3!
Just to clarify, the migration will change only the whisper key, so the wallet key will be the same.
It should be ok to manage those contracts, is that correct?

Also, we could just use this new feature by default for new user and opt-in for current users.

  • New User: account is created with 2 different keys
  • Existing user who upgrades Status: we can leave the keys as they are, or ask to upgrade.
  • Account recovery/upgrade: user can opt-in for the new keys or keep the legacy keys. In case the user upgrades we can update the contracts with the new whisper ID.

What do you think?