Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solve Key Management #73

Closed
D4nte opened this issue Apr 28, 2021 · 15 comments
Closed

Solve Key Management #73

D4nte opened this issue Apr 28, 2021 · 15 comments
Projects

Comments

@D4nte
Copy link
Contributor

D4nte commented Apr 28, 2021

Problem

For identity (signatures) and encryption purposes, the user needs access to a key pair, therefor referenced to as Waku keypair.

There is currently no straightforward solution possible via the standard Web3 Wallet API.

Cryptographic needs

The following encryption and signature schemes are defined in Waku v2 and would ideally be available with the adopted solution. However, it can be changed/evolved if we go for a generic API-type solution:

Waku, see 26/WAKU-PAYLOAD for details:

  • ECDSA Signature of Keccak-256 hash of application payload.
  • Symmetric Encryption using AES-256-GCM.
  • Asymmetric Encryption using ECIES: secp256k1, KDF SHA-256, HMAC SHA-256, AES-128-CTR.

The encrypted data is flags|payload-length|payload|padding|signature with flags = size of payload-length | signature-presence (2 bytes field).

Encryption and signature can also be defined at application level. For example, EIP-712 is used for a couple of smart-contract and non-smart-contract enabled apps.

Ideal solution

For an ideal UX, the following properties need to be satisfied:

  1. Ability to backup and then recover the Waku keypair after device loss.
  2. Ability to access the Waku private key or an API for decryption purposes in a friction-less and programmatic manner.
  3. Ability to access the Waku private key or an API for signature purposes in a friction-less and programmatic manner.
  4. Unlinkability of Waku keypair with Ethereum account (if Ethereum keys are used to facilitate property 1.)
  5. Ability to generate new Waku keypair if needed, conserving properties 1-4 and unlinkability between the Waku keypairs.
  6. Usable with the standard/common Web3 API (e.g.: Status wallet, MetaMask, geth, Wallet Connect), if a Web3 wallet is at all needed.
  7. Secure and cryptographically sound, using industry standards such as BIP-32, EIP-1581

tl;dr

Jump to Moving Forward to see the proposal and work back to selected solution(s).

Potential Solutions

A. MetaMask's eth_decrypt API

Overview

As demonstrated in https://github.com/status-im/js-waku/tree/main/examples/eth-pm-wallet-encryption, MetaMask provides an API to:

  • Retrieve the encryption public key of the Ethereum account: eth_getEncryptionPublicKey
  • Decrypt messages encrypted using said key (schema x25519-xsalsa20-poly1305): eth_decrypt

The public key is computed from entropy associated with the specified user account, using the nacl implementation of the X25519_XSalsa20_Poly1305 algorithm.

Also see https://ethereum-magicians.org/t/eip-1024-cross-client-encrypt-decrypt/505

Properties

  1. yes, key comes from Ethereum keys.
  2. No, user needs to validate action in MetaMask, encryption seems to be locked in to x25519-xsalsa20-poly1305.
  3. No, user needs to use Ethereum key to sign.
  4. Unsure, nacl derivation.
  5. No, only one key is offered
  6. No, not available with Status, geth,
  7. Unsure, uses Nacl derivation

Preliminary conclusion

This solution does not satisfy enough properties to be considered.
We could review the API and propose improvements but it may be better to design a new API from scratch that fits our purposes instead.

B. Generate keys and provide ways to back up and recover

Overview

A naive approach is to simply generate a keypair using common JavaScript libraries.

A way to backup and recover the keys needs to be provided to the user, independently to their Ethereum account.

Properties

  1. Yes but hard, as it cannot be delegated to the Ethereum account. The app needs to provide secure way (seed words, export/import, etc) for the user to backup and recover Waku keys.
  2. Yes, the app generates and handle Waku keys.
  3. Yes, the app generates and handle Waku keys.
  4. Yes, as the Waku Keys are unrelated to the Ethereum account.
  5. Yes, the generate key can be used as HD root key and subsequent keys can then be derived using BIP-32.
  6. Not applicable.
  7. Yes.

Preliminary conclusion

Property 1 is a challenge, the only challenge, of this solution.
It is a strong candidate, only upped by a solution that would allow deterministic derivation of keys from an Ethereum account.

C. Generate private key from Ethereum signature

Overview

Ask the user to sign a message such as "This signature is used to generate your waku private key, do not share with other parties" and hash the resulting signature. The hash is then used the Waku private key.

Properties

  1. Yes, can be deterministically generated from the Ethereum account. As long as the user has access to their Ethereum account, they have access to their Waku key.
  2. Yes, the dApp holds the private key.
  3. Yes, the dApp holds the private key
  4. It is not possible to deduce the Ethereum account from the Waku key thanks to the hashing step.
  5. The resulting key can be used as entropy to create a HD key to derive further keys.
  6. Yes, just need access to eth_signTypedData
  7. No, not really. There are several issues with this approach:
    a. It is unsure whether we are introducing a data bias by using the hash of a signature as a private key. I assume it somehow reduces the set of possible values. More research would be needed to affirm it does not makes the private key less secure due to the pseudo-randomness property of the source (ECDSA signature).
    b. dApp and wallets usually do not put an emphasis in keeping signatures secret (in comparison to keeping private key secrets). Hence, the resulting signature could be leaked by the wallet or dApp framework simply because this specific, odd, usecase was not kept in mind when designing the wallet/dapp
    c. User footgun: Most of the security of this method rely on the user refusing the sign the exact same message for another dApp.

Preliminary conclusion

While this method would allow to fulfill most properties with the current Web3 API, it brings some UX security challenge.
At this point, it would be safer to push the user to backup their Waku key the same way than they backup their Ethereum key than asking them to never sign twice the same message with two different dApp.

Do note this is used by other projects, hence this conclusion may need revision:

D. Use EIP-1775

Overview

tl;dr:

EIP-1775 propose the implementation of new wallet api wallet_getAppKeyForAccount that produce an application private key, unique to the dApp and derived from the user's Ethereum account.

The dApp is identified by there domain name, making sure that no 2 dApp can access the same private key.

Properties

  1. Yes, deterministically generated from the Ethereum account
  2. Yes, the dApp holds the private key
  3. Yes, the dApp holds the private key
  4. It is not possible to deduce the Ethereum account from the Waku key as the Waku key is a hash result of Ethereum private key | dApp domain name
  5. The resulting key can be used as entropy to create a HD key to derive further keys.
  6. Wallets MUST implement EIP-1775, it is not commonly (at all?) available
  7. A downside of this approach is that the dApp is trusted with the waku private key.

Preliminary conclusion

Each key is tied to an app's id (e.g. domain name).

For a use case that involves several platforms (web, mobile) then the generated waku key could be different.
Which makes it more complicated, yet possible, for a user to preserve the same identity across platforms.
Cross-signing methods could one way to resolve this (see Matrix protocol, more investigation necessary).

This approach also mean that the dApp is trusted with the waku private key.

Overall, this could be a possible long term approach. More discussion is needed to understand why this EIP is not adopted.

A safer solution would be to have the wallet expose decryption and signing APIs for non-wallet purposes that do not require user approval at each action, but only once per key/dapp/session: e.g., user confirms that the dApp can use non-wallet key to decrypt and/or sign for the whole session.
EIP-2255 proposes such permission based design.

However, this brings other challenges such as: what decryption/signature method should be allowed?

E. Extensible crypto for wallet

Overview

An API that allow registering and then using algorithm with the wallet by way of wasm blob.
Principally designed for ZK algo.

See https://ethereum-magicians.org/t/extensible-crypto-for-wallets/2546/19

Properties

TODO

Preliminary Conclusion

It is not really adopted (no EIP). It has potential to provide a generic solution that could be used for our use case but it may also be overkill as we only need signature and encryption using existing algorithms, not new ZK ones.

F. EIP-2844: Add DID related methods to the JSON-RPC

Overview

This EIP describes three new methods to add to the JSON-RPC that enables wallets to support Decentralized Identifiers (DIDs) as well as JSON Object Signing and Encryption (JOSE). These standards enables wallets to support data decryption as well as authenticated data, both in standard formats using JOSE. With these new methods apps can request the DID from a users wallet, from which a DID document can be resolved. The DID document contains public keys that can be used for encryption and signature verification. This enables Alice to discover Bobs public keys by only knowing Bobs DID. This EIP does not enforce the user of any particular DID method or JOSE algorithms, wallets are free to implement these however they wish.

Properties

  1. Kind of, this EIP does not cover the key generation and leaves it up to the wallet implementation. It does give the freedom to the wallet to generate a different DID per dApp or use case, see did_authenticate API that takes aud (domain name of the dApp) and paths (permissions) as input. EIP-1581 could then be used for deterministic generation of the DIDs/keys from the Ethereum account.
  2. Yes, the UX would be to call did_authenticate first to give specific permission for this dApp (e.g. sign), no user interaction would then be needed when using did_decryptJWE as long as aud and paths matches a previous auth.
  3. Uncertain, see Discussions for EIP: Add DID related methods to the JSON-RPC ethereum/EIPs#2845 (comment)
  4. See 1, up to the wallet implementation.
  5. Not really, the dAPP does not state which did it wants to use, the wallet does, depending on the input of did_authentication. The paths format is not defined, maybe it could be terminated by an index that the dApp could increase to recycle key? The UX implication would need to be reviewed.
  6. Not yet, the EIP is a proposal to extend Web3 wallet API.
  7. Yes, the EIP is specially designed to re-use mature concepts (JOSE, W3C DID standard).

Preliminary Conclusion

While this API does not perfectly fit our use case (see 3.), it is very close.
It proposes standard formats to generate identities, sign and decrypt payload in a generic manner.

It does not dictates key management for the DIDs which may still need standardization.

Moving Forward

(B) seems to be the best way forward in short-mid term for several reasons:

  1. It fulfills all desired property, only makes 1 harder to implement that if the keys were somehow deterministically derived from the Ethereum Account
  2. The need for a key generation method that is unrelated to an Ethereum account is likely to be raised if Waku is used outside of a Blockchain environment.
  3. It can be done now.
  4. The recovery/backup mechanism may not be necessary for the first use cases we have in mind (trollbox).

Long term, we need to investigate D/EIP-1775 F/EIP-2844, better understand the reasons why it is not adopted and help its adoption/design.

Preference of F/EIP-2844 over D/EIP-1775 is simply because the former let the wallet handle the private keys, instead of the dApp.

Other solutions to consider

References

@D4nte D4nte created this issue from a note in js-waku (Backlog) Apr 28, 2021
@D4nte D4nte added this to the Developer Ready milestone Apr 28, 2021
@D4nte D4nte moved this from Backlog to Icebox in js-waku Apr 28, 2021
@D4nte D4nte moved this from Icebox to Backlog in js-waku Aug 27, 2021
@D4nte D4nte changed the title Keys persisting in storage Solve Key Management Aug 27, 2021
@D4nte D4nte moved this from Backlog to In Progress in js-waku Sep 7, 2021
@D4nte
Copy link
Contributor Author

D4nte commented Sep 9, 2021

In response to https://ethereum-magicians.org/t/non-wallet-usage-of-keys-derived-from-bip-32-trees/1817/6 :

(copied here because I am not allowed as a new user to put more than 2 links in a response).

The current proposed API in EIP1775:

const appKey = await provider.send({
  method: 'wallet_getAppKeyForAccount',
  params: [address1]
});

Implies that access to a dApp specific private key is given to the dApp. I believe this is not ideal as it means the dApp now needs to properly handle the private key.

I agree with you (@3esmit) that it'd be ideal if the dApp could instead request signing/decrypting messages to the wallet, using the dedicated dApp key. Potentially using a permission based design such as EIP-2255.

However, the challenge is that the decryption/signature method provided by a wallet may not fit the dApp needs.
In regards of the signature scheme, EIP-712 could be a one-fit-all candidate.

However, in terms of decryption, we can see that various schemes are used in the ecosystem and it may be difficult to pick one:

Another solution would be to provide a generic API that supports several encryption. An idea would be to use CryptoSubtle as the API reference and assume that in the Browser world, some of the encryption supported by Crypto Subtle should be supported by the Wallet API.

@D4nte

This comment has been minimized.

@D4nte

This comment has been minimized.

@D4nte
Copy link
Contributor Author

D4nte commented Sep 13, 2021

  • Look into what IPFS does.

@kdenhartog
Copy link

I got pinged from your recent comment on EIP-2844. I'm glad to see your looking at using EIP-2844.

Reading above, I think there's a few ways we could get to your end goal of being able to allow encrypted/signed messages to be usable without needing authorization requests each time but I'd like to drill into your requirements a bit more before I make a recommendation about using EIP-2844 (or we come up with a way to re-adjust it). Is the end goal here to be able to send and receive messages without performing authorization requests each time?

From what I'm seeing this is the ideal requirements you need for some other work:

Ideal solution

For an ideal UX, the following properties need to be satisfied:

1. Ability to backup and then recover the Waku keypair after device loss.

2. Ability to access the Waku private key or an API for decryption purposes in a friction-less and programmatic manner.

3. Ability to access the Waku private key or an API for signature purposes in a friction-less and programmatic manner.

4. Unlinkability of Waku keypair with Ethereum account (if Ethereum keys are used to facilitate property 1.)

5. Ability to generate new Waku keypair if needed, conserving properties 1-4 and unlinkability between the Waku keypairs.

6. Usable with the standard/common Web3 API (e.g.: Status wallet, MetaMask, geth, Wallet Connect), if a Web3 wallet is at all needed.

7. Secure and cryptographically sound, using industry standards such as [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), [EIP-1581](https://eips.ethereum.org/EIPS/eip-1581)

It seems like there's a few intended goals here which could be broken down in a variety of different ways to achieve the intended outcome. However, some of my assumptions are coming from a DID based background that I'm not sure if they hold for your use case if I twist and rejig things a bit to align for you. The main reason I'm asking is to try and keep the APIs in EIP-2844 as generalized as possible so that it can be applied across a variety of use cases while still making sure it addresses your needs.

1. Ability to backup and then recover the Waku keypair after device loss.

Are you utilizing the key pair as an identifier of sorts here? The heart of my question here is to try to figure out what's driving the need to be able to recover the keypair later. I'm thinking it may be possible to utilize the DID as the identifier so that the key management solution can be decoupled from the identifier persistence.

2 and 3 I presume are about trying to reduce consent request fatigue. Is this correct?

4. Unlinkability of Waku keypair with Ethereum account (if Ethereum keys are used to facilitate property 1.)

This goes back to trying to figure out the purpose of the keypair and see if it's being used only for cryptographic operations or if it's behaving as an identifier of sorts as well. I presume based on this assumption that there's a need for greater privacy guarantees. Am I off basis here?

5. Ability to generate new Waku keypair if needed, conserving properties 1-4 and unlinkability between the Waku keypairs.

Is there a need to ever re-correlate these keypairs down the road (e.g. two messaging groups are merged later on) or are they being treated more like pairwise interactions that MUST NOT interact at any point in their lifecycle?

@D4nte
Copy link
Contributor Author

D4nte commented Sep 15, 2021

@D4nte
Copy link
Contributor Author

D4nte commented Sep 15, 2021

I got pinged from your recent comment on EIP-2844. I'm glad to see your looking at using EIP-2844.

Reading above, I think there's a few ways we could get to your end goal of being able to allow encrypted/signed messages to be usable without needing authorization requests each time but I'd like to drill into your requirements a bit more before I make a recommendation about using EIP-2844 (or we come up with a way to re-adjust it). Is the end goal here to be able to send and receive messages without performing authorization requests each time?

Yes, correct, the goal is to be able to:

  • sign messages that are being sent, without requesting authorization every time
  • decrypt messages that are being received, without requesting authorization every time

I believe that the user should still grant authorization at some point. I do not know what the best UX would be but once per session would make sense at first (ie, when the dApp connects to the wallet).
Or similarly to what is done with the authorization of viewing the account address which is "forever" per domain name.

It seems like there's a few intended goals here which could be broken down in a variety of different ways to achieve the intended outcome. However, some of my assumptions are coming from a DID based background that I'm not sure if they hold for your use case if I twist and rejig things a bit to align for you. The main reason I'm asking is to try and keep the APIs in EIP-2844 as generalized as possible so that it can be applied across a variety of use cases while still making sure it addresses your needs.

Yes, thank you for helping me clarifying the use case.
The intents are coming from what is currently done in the Status app, that has access to the private key as it is both a wallet and chat app, and I am attempting to translate them to a browser domain with only access to a Web3 Wallet API.

1. Ability to backup and then recover the Waku keypair after device loss.

Are you utilizing the key pair as an identifier of sorts here? The heart of my question here is to try to figure out what's driving the need to be able to recover the keypair later. I'm thinking it may be possible to utilize the DID as the identifier so that the key management solution can be decoupled from the identifier persistence.

Yes, the keypair is used as an identifier for chat purposes. It is the chat identity of the user.

2 and 3 I presume are about trying to reduce consent request fatigue. Is this correct?

Yes, correct, maybe "programmatic" is not the best qualifier for it. We cannot expect the user to approve the decryption of every incoming message and the signature of every out going message.

Signature and decryption MUST be somehow tied to the chat identity above.

Noting that regarding encryption, we use double ratchet protocol. I realize that I haven't looked into/expressed the actually need for that. The dApp may after all need access to a decryption private key. I need to review this point.

4. Unlinkability of Waku keypair with Ethereum account (if Ethereum keys are used to facilitate property 1.)

This goes back to trying to figure out the purpose of the keypair and see if it's being used only for cryptographic operations or if it's behaving as an identifier of sorts as well. I presume based on this assumption that there's a need for greater privacy guarantees. Am I off basis here?

You are absolutely right, the user MAY NOT want to reveal their Ethereum account when revealing their "chat" identity.

5. Ability to generate new Waku keypair if needed, conserving properties 1-4 and unlinkability between the Waku keypairs.

Is there a need to ever re-correlate these keypairs down the road (e.g. two messaging groups are merged later on) or are they being treated more like pairwise interactions that MUST NOT interact at any point in their lifecycle?

I don't believe there would be a need to ever re-correlate these key pairs.

The use case I have in mind is that a user may hold tokens ABC and XYZ in their Ethereum account.

They want to participate to discussion in both ABC and XYZ communities however, do not wish to link their identity across the forums.

if we restrict the design to "1 Ethereum account = 1 chat identity" then it means the user has to move their asset to enable the unlinkability between the chat identity which is not ideal.

@D4nte
Copy link
Contributor Author

D4nte commented Sep 15, 2021

  • Check needs for double ratchet protocol and X3DH bundles.

@kdenhartog
Copy link

kdenhartog commented Sep 16, 2021

Yes, correct, the goal is to be able to:

* sign messages that are being sent, without requesting authorization every time

* decrypt messages that are being received, without requesting authorization every time

I believe that the user should still grant authorization at some point. I do not know what the best UX would be but once per session would make sense at first (ie, when the dApp connects to the wallet).
Or similarly to what is done with the authorization of viewing the account address which is "forever" per domain name.

Yeah, my thinking was similar to what's done with the authz of viewing an account address per domain name.

Yes, thank you for helping me clarifying the use case.
The intents are coming from what is currently done in the Status app, that has access to the private key as it is both a wallet and chat app, and I am attempting to translate them to a browser domain with only access to a Web3 Wallet API.

Sounds good, I've heard of status' app, but have not played around with it yet. I'll give it a go to get a better understanding of your needs.

Yes, the keypair is used as an identifier for chat purposes. It is the chat identity of the user.

Interesting, so with EIP-2844 the idea is that the identifier is abstracted to the DID layer and the public keys become what are known as "verification methods" in the did documents which to date have always been public keys. I'm thinking there's some value in decoupling this identifier layer from the cryptographic material so that a common identifier can be used without needing to do key recovery on different devices to maintain chats. Rather you can just add a new key to the DID Document. This is one of the key value props of DIDs. Is that something that would make sense for your team to do (I'm thinking it may lead to changes in how you handle key management in the app as well) at this point or does fall outside the scope of the goals of this work?

2 and 3 I presume are about trying to reduce consent request fatigue. Is this correct?

Yes, correct, maybe "programmatic" is not the best qualifier for it. We cannot expect the user to approve the decryption of every incoming message and the signature of every out going message.

Signature and decryption MUST be somehow tied to the chat identity above.

That makes sense - what's interesting here is it seems like the browser is only being used for ingress communications. Do you plan to perform things like encryption and signing from the browser as well or is it mainly being used for reading messages?

Noting that regarding encryption, we use double ratchet protocol. I realize that I haven't looked into/expressed the actually need for that. The dApp may after all need access to a decryption private key. I need to review this point.

This will make things a bit more complex, but not outside the realm of possibility. We've looked at how the X3DH algorithm could be built into the JOSE stack and believe it's possible, but no one has gone and defined a method to achieve it yet. This definitely introduces a few additional complexities into play now because from the sounds of it the waku keypair is actually the long term identity keypair in the X3DH algorithm. The implications here are that by utilizing the same waku keypair on multiple devices a compromise of a single device I believe compromises the entire communication channel. Things like Sesame protocol and Message layer security have been the latest improvements in the space to make it possible for multi-device communication and group communication in order to handle these new complexities. I'm curious is limiting the affects of a single device compromise a concern here or would the user be expected to set up a new communication channel if one device was compromised?

You are absolutely right, the user MAY NOT want to reveal their Ethereum account when revealing their "chat" identity.

Ok, thanks that makes sense now and should make it easier to keep things decoupled better.

I don't believe there would be a need to ever re-correlate these key pairs.

The use case I have in mind is that a user may hold tokens ABC and XYZ in their Ethereum account.

They want to participate to discussion in both ABC and XYZ communities however, do not wish to link their identity across the forums.

if we restrict the design to "1 Ethereum account = 1 chat identity" then it means the user has to move their asset to enable the unlinkability between the chat identity which is not ideal.

Good to know, and I agree with the design choice. One thing worth considering is that when decoupling the identifier layer from the crypto material with DIDs, it does become possible to do this recorrelation with a bit of advanced usage of DID Documents. I'd leave this out of scope though for now, since it's really a separate feature of sorts in my mind.

Thanks for answering these things. What I'm gathering here is that there's two recommendations I'd make

  1. Using DIDs would benefit in being able to separate out the layers and reduce compromise of a single device by creating separate waku keypairs for different devices. The tradeoff here is that bringing DIDs in to do this would introduce architectural impact on the status app which could be too large of scope creep at this time.

  2. Utilizing JOSE stack and by extension EIP-2844 is going to create some complexities around needing to combine X3DH with JWEs for decryption. Right now, ECDH-1PU and ECDH-ES are the default methods used for EIP-2844 which aren't direct fits in terms of cryptographic security guarauntees. The two main ones being that with ECDH-1PU you degrade from perfect forward secrecy in X3DH to weak perfect forward secrecy and with ECDH-ES you lose sender authenticity, but maintain PFS. Looking all at the options above I'm not seeing any of them other than option B which will allow you to maintain all of the security requirements you have today while also being able to support multiple devices. The tradeoff here is the device compromise aspect and from an security architecture perspective you're getting to a point where you're likely to start reaching the boundaries of the architecture without needing to make large changes. However, it is by far the simplest and fastest way to deliver the feature I'd guess.

@D4nte
Copy link
Contributor Author

D4nte commented Oct 13, 2021

There are mainly two scenarios to be considered:

  1. General topic: How dApps using Waku should manage encryption and signature keys used for messages exchanged over the Waku network.
  2. More specific to DappConnect Chat SDK: How can a Status app user's identity be ported to the browser, including the ability to send and receive messages.

There are hopefully synergy between both scenarios, however the outcome may differ because in the case of (2), the user has access to the Status app that facilitates the backup and management of the chat key, used for signature and encryption purposes. The Status app can act as a secure vault for the main "account" of the user.

In the case of (1) the may not be such secure/main account as a given dApp may be exclusively access via the browser with a generic Ethereum Wallet being the secure enclave for keys.

(2) as discussed with @cammellos: https://discord.com/channels/864066763682218004/892839110073520128/892883232318697524 @D4nte to provide more information about this discussion.

The discussion was mainly focused around compatibility between Status app and the Chat SDK.
How do we enable the user to log in a browser dApp and receive the same messages than they have in their Status app and being able to send messages.
We also discussed how sync is planned to be implemented between the Status Desktop and Status Mobile apps. Both apps integrate an Ethereum Wallet and hence have access to the chat private key. Thus the conditions are different than for syncing a Status mobile app and Browser dApp.

Here are some conclusions we can extract:

  1. The chat key is critical to the identity of the user. Hence, the key should never be handed to a browser dApp. Status apps derive the chat key from the Ethereum account. We do not want Ethereum wallet to provide an API to allow the same derivation.

  2. A possible design could be similar to "old Whatsapp/Signal" scenario where a secure channel is created between the secure client (Status Desktop or Mobile app) and the browser dApp. The Browser dApp would received and send message over the secure channel and the secure client would handle decryption and signing of messages. This is not great UX as it means the secure client needs to be open and connected at all time (probably why whatsapp and Signal moved away from it).

to be continued.

@D4nte D4nte moved this from In Progress to Backlog in js-waku Jan 7, 2022
@D4nte
Copy link
Contributor Author

D4nte commented Jan 14, 2022

After further review, it seems that currently, the most used method is C: generate a private key from an Ethereum account by signing data and using the (hash of) the resulting signature as private key.
This has of course drawbacks are previously listed.

A potential vector of attack is a website impersonation where a user is directed to scammywebsite.com and asked to sign with their wallet to generate a private chat key.
If the website included "legitimatechatapp.com" in the data signature and the user does not notice it then scammywebsite.com can steal the user's chat key and access the user's data and act as the user on legitimatechatapp.com.

In github.com/status-im/dappconnect-chat-sdk we are mitigating the drawback by using EIP-712 and including the apps' domain name as part of the data to sign (onlySignOn field, wip), to prevent the same key to be generated on two different websites.

We also intend to ask the user to check said field.

Yet, this still involves the user's attention to verify that the domain in the signature matches the domain website.

Ideally, this domain check should be done programmatically. Option D: Use EIP-1775 would help on this matter.

Another proposal is to let the user specify a password-like custom text to be added to the data to be signed.
This could be helpful if the user has the discipline to use a different password for each webapp.
However:

  • it does not help if he is redirected to a domain that has a similar domain name on purpose. e.g foo.com and f00.com, f00.com trying to steal the chat keys of foo.com users
  • it is added information for the user to remember, If they loose this information, they irreversibly loose access to their chat account.

@D4nte D4nte moved this from Backlog to In Progress in js-waku Jan 14, 2022
@serhanwbahar
Copy link

First of all, I believe this a decent work. It seems you thought of all the details.

As far as I understand, the security matter here is scamming, phishing via the website or spear phishing. Also, there are some attacks like DNS poisoning that usually requires being MiTM. (If you need more information, please check here: https://www.kaspersky.com/resource-center/definitions/dns)

Your security measures are enough for current security best practices. But you can think like we are selling a knife or a weapon for a specific purpose. We can tell our customers not to kill themselves with a knife or weapon, but we can't stop them from doing it. I don't think there will be a magical solution to stop scamming, impersonation or phishing soon but what we can do here is to teach our users not to click or be bait on them.

There are some considerations for preventing fake websites, but they require a centralized solution that must be permission-based or controlled based. Therefore, it is not suitable for Status' soul. Even you create centralized automation that can verify Dapps before signing with your wallet. Still, lots of people can be deceived.

The solution is always to design the process as simple as possible not to confuse users' minds. The UX itself should show users what is not secure, which you are already planning to do it.

PS: "Ideally, this domain check should be done programmatically. Option D: Use EIP-1775 would help on this matter." This is a perfect solution.

The best way to see the attacks is to do a threat modeling and create an attack tree and a threat/attack traceability matrix to ensure the attack surface. If you want, we can work on it together (You, me, plus Fred) @OxFred @D4nte

@kdenhartog
Copy link

kdenhartog commented Jan 18, 2022

I agree largely with the sentiment that @serhanwbahar has expressed. Solving for the phishing problem is going to be hard and isn't current security best practices of today. Obviously if we can it would be best to solve this, but I don't believe that the solution proposed by @D4nte with phishing problems left out of scope couldn't be extended later when a more decentralized solution is available to solve the phishing problem.

Today, the most common way I've seen to solve this is a DMARC record which relies on DNS in order to establish trust hierarchies. As @serhanwbahar pointed out this will centralize the solution in a way that goes against the ethos of your team (and the ethos of the ecosystem).

I've looked at ways in which things like a DAO or TCR could be used to decentralize the trust hierarchies, but solving this seems to be a yak shaving exercise which isn't fundamentally assisting with the overall focus of the problem originally described.

For that reason, I think it makes sense to leave the phishing issue out of scope as well. Additionally, while I do have a preference towards the utilization of DIDs and seeing that ecosystem expand further into the ethereum ecosystem; I also understand the desire to remain aligned with the account based approach. It's likely to be the solution which will align most closely to other people working in the ethereum ecosystem and so is likely "good enough" to go forward with.

@D4nte
Copy link
Contributor Author

D4nte commented Jan 18, 2022

Moving this to icebox as we have a current solution.

We can review in a year's time to see if the ecosystem has evolved or changed security practices. Especially regarding EIP-1775.

Regarding the threat/attack traceability matrix. We can do that once any of the SDK/project that uses the method proposed above is confirmed market fit and we decide to document this practice as best practice in the usage of js-waku.

@D4nte D4nte moved this from In Progress to Icebox in js-waku Jan 18, 2022
@D4nte D4nte removed this from the Developer Ready milestone Feb 11, 2022
@fryorcraken
Copy link
Collaborator

Out of scope for Waku at this point in time. Would be good to see what https://github.com/status-im/status-web does

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
js-waku
Icebox
Development

No branches or pull requests

4 participants