Eth-DM learnings and what is next

Eth-DM

Continuing the work on js-waku, the latest objective was to build and spec an end-to-end encrypted messaging dApp: Eth-DM, standing for Ethereum Direct Message.

You can find:

Features

It is very rudimentary, the aim was to ship a first PoC and then build on it. The current PoC allows you to:

  • Generate an Eth-DM key-pair, used for encryption and decryption of messages. Your Ethereum wallet (e.g. Status, Metamask) is used to generate the keys meaning you do not need to back them up; Eth-DM keys can be recovered using your Ethereum account.
  • Publish your Eth-DM public key to the network to allow others to find it using your Ethereum address.
  • Send encrypted messages to another peer.
  • Received said encrypted messages from other peers.

Learnings

The standard Web3/Metamask/Status API does not permit much around key access and encryption.

It is not possible to ask your Ethereum wallet to derive child keys from your Ethereum private key. There is no standard way to use EIP-1581 without controlling the wallet implementation.

Some wallet such as Metamask supports methods for encryption. However, it is restricted and not broadly available. Having EIP-2844 commonly available would be another way to more easily implement Eth-DM like dApps.

To work around these restrictions, Eth-DM uses the signature of a salt message as the encryption private key.
I find it to be a clunky way to work around these restrictions, without the EIPs cited above, another solution would be to simply generate fresh new keys for encryption. In this case, the user would need to properly backup said keys to not loose messages.

What’s next

Eth-DM

It is evident from the feedback we got at 0xHack that encrypting and signing messages is a feature that dApp builders are likely to implement in projects using js-waku.
Currently, signatures and encryption are considered an application level concern: Waku v2 does not enforce or restrict the payload dApp includes in Waku Messages. If this payload needs to be signed or encrypted, the dApp is free to do so by including the necessary data in the Waku Message payload field.
This is why I want to provide a number of examples on how to sign and encrypt messages sent over Waku. Eth-DM provides a good use case to do so, the next step is to allow user to sign their messages to prove their authenticity.

Furthermore, Eth-DM only uses Light Push: messages and public key are not retrieved from Store nodes. This means that for two peers to communicate, they have to have the dApp opened at the same time. I will include Store in a subsequent release and probably smooth out the recipient selection UX too.

Tutorial

As part of the Developer Ready Epic I aim to provide tutorials that give a more detailed explanation of the js-waku API than the current examples.

One of the objective is to show how js-waku can be integrated with web3.

The current integration done with Eth-DM to offer message encryption is somewhat clunky so I will aim to showcase message signature instead. I expect message signature using web3 to be much smoother as etherjs and web3js both provide a simple API for it.
Moreover, I am keen to provide a simple module that automatically sign messages sent over Waku v2. It may be interesting at this point to review whether we should have a new signature or metadata field on WakuMessage to allow complete freedom on the application payload while having a generic way to include signatures of said payload. An idea already proposed by bgits.

1 Like

Neat experiment, the approach has a few key issues though that ideally would be resolved before this becomes an actual spec - or they need to be documented more clearly in the spec document such that the proposal doesn’t get used in contexts where it’s not appropriate.

Crypto

The suggested key derivation algorithm, as acknowledged in the draft, has several issues - potentially some of them could be worked around simply by using a library for cryptography in the browser, for those contexts where the API doesn’t have them - ie it’s entirely possible to extend what for example Status itself offers in its API, and if Metamask is doing something similar, use that - this establishes a practice that in turn can lead to standardization - secp256k1 - npm looks like a low hanging fruit to patch up anything that’s missing - Iack of standard web3 API shouldn’t be reason to compromise on security.

There are also details in the spec that look a bit odd - ie why is the signature doubled before passing it to the hashing algo?

Privacy

Ethereum addresses are usually a long-term commitment that are hard to change - using them directly to derive keys without at the same time implementing forward secrecy is quite a significant regression compared to the state of the art today.

The other significant issue is that private keys of individual addresses are often less protected than the root of the BIP key derivation - a lot of the security infrastructure is built up around keeping seed phrases safe, but not necessarily individual private keys (because they need to be more “user-friendly”), adding importance to forward secrecy being the lowest acceptable bar for any example involving addresses.

Standards like SubtleCrypto - Web APIs | MDN are available to implement many of these things, also in a browser context.

Payload

Generally, waku is not a very efficient protocol - it trades efficiency to gain privacy and decentralisation - at the very minimum, it would make sense to use a payload that is not as wasteful, as json is - ie either compressed json or preferably protobuf that has widespread usage in protocols already, including that of status itself.

1 Like

Thank you for the input!

Your post makes me realize that by trying to design and build example dApps that use Waku, such as Eth-DM, there is a risk to go down the rabbit hole and end-up re-inventing years of work that Status has done to build the current chat protocol that includes privacy, encryption, etc,

I am keen to address the weaknesses you highlighted in the protocol. However, I am now wondering if instead I should just rename the protocol as “TOY-ETH-DM” (tracked with #407) , fix some of the most obvious security faults (see below) and leave it be.

There is a fine balance between providing examples that make sense and demonstrate good software engineering, security and privacy practice and building actual production ready dApps and Eth-DM is not there yet.

Please find below a more detail answered to the concern you highlighted:

Crypto

The suggested key derivation algorithm, as acknowledged in the draft, has several issues - potentially some of them could be worked around simply by using a library for cryptography in the browser, for those contexts where the API doesn’t have them - ie it’s entirely possible to extend what for example Status itself offers in its API, and if Metamask is doing something similar, use that - this establishes a practice that in turn can lead to standardization - secp256k1 - npm looks like a low hanging fruit to patch up anything that’s missing - Iack of standard web3 API shouldn’t be reason to compromise on security.

As you stated, the current derivation scheme is due to web3 API limitation and the will to keep the dApp easy to use and not ask the user to backup their Eth-DM key. However, as this is an app example thus I agree that we should demonstrate good security standard and leave the back up part as “something that a prod dApp should tackle”. Tracking here: [examples/eth-dm] Remove derivation for signature · Issue #213 · status-im/js-waku · GitHub

There are also details in the spec that look a bit odd - ie why is the signature doubled before passing it to the hashing algo?

I will remove that with #213 this is due to a limitation on eth-crypto side.

Privacy

Ethereum addresses are usually a long-term commitment that are hard to change - using them directly to derive keys without at the same time implementing forward secrecy is quite a significant regression compared to the state of the art today.

The other significant issue is that private keys of individual addresses are often less protected than the root of the BIP key derivation - a lot of the security infrastructure is built up around keeping seed phrases safe, but not necessarily individual private keys (because they need to be more “user-friendly”), adding importance to forward secrecy being the lowest acceptable bar for any example involving addresses.

Standards like SubtleCrypto - Web APIs | MDN are available to implement many of these things, also in a browser context.

If I understand correctly, you are suggesting to use SubleCrypto over eth-crypto. Point taken, added to #213.

Payload

Generally, waku is not a very efficient protocol - it trades efficiency to gain privacy and decentralisation - at the very minimum, it would make sense to use a payload that is not as wasteful, as json is - ie either compressed json or preferably protobuf that has widespread usage in protocols already, including that of status itself.

I think it’s important to provide valid examples of payload encoding that we expect dApp developers to use. Waku is clearly open to support several encoding as the recommendation for both pubsub and content topic is to affix the encoding format so I think it is valuable to provide another codec example than protobuf.

Point taken that JSON is not the most efficient format, I will change it to compressed JSON.

1 Like

Lol, yeah, there’s a feeling of deja-vu for some reason :slight_smile:

TOY-ETH-DM

Agree, this might be the best thing to do here - we could also point people to the status protocol as a more developed example that covers more of the best practices today - as an experiment and example, it’s of course a great resource, but we need to be very clear that there are some known risks with this kind of setup that can quickly turn into real issues should it get used in the wrong context.

One thing that would alleviate some of these problems would be if there was an easy way to introduce the concept of short-lived sessions, such that keys were valid for a short exchange (for example a chat window) and then thrown away - even a simple DHE exchange would get us pretty far, but that would depend on the scope, really.

I missed that eth-crypto was involved - my main point was that even in a toy example, we can recommend good practices by using a few libraries to work around shortcomings in web3 without having to “fix the standard” - I believe this should still be within bounds for a getting-started-example - I’m not too familiar with eth-crypto vs SubtleCrypto, the latter popped up as a fairly widespread cross-browser alternative in a quick search for what’s available to do “standard” AES encryption in-browser after a session key has been established, but if eth-crypto has algorithms that are better aligned with what’s “commonly” used in eth, all the better.

Agree, this would be useful as an example, along with privacy rationale re PII and Ethereum pubkeys. Then point to 5/SECURE-TRANSPORT - Status Specification more fully featured usage.

I spent some time playing around with Crypto.subtle and one of the limitation I found is that Elliptic Curve can only be used for signing and verification purposes [1].
Meaning that for encryption and decryption, one can either use AES or RSA.

  • AES: I don’t believe symmetrical cryptography to useful for Eth-DM use case, Alice wants to encrypt the message for Bob. Bob does not know in the first place that Alice is the one that wants to contact him so there is on easy way to exchange the AES key. Also, we don’t really want Alice to be able to read all messages for Bob.
  • RSA: Bob can share the public key similarly to what is done but RSA is generally viewed less secure than ECDSA or even ED21559 due to potential vulnerability based on the source randomness.

In conclusion, it seems that eth-crypto is a better choice for Eth-DM use case.

References

FYI Do not derive encryption key from signature by D4nte · Pull Request #216 · status-im/js-waku · GitHub

I ended up using Crypto Subtle for the local storage of the Eth-DM key.