Title: EIP_5630__Encryption_and_Decryption
Category: EIPs

Author: firnprotocol
Date: 2022-09-08T23:22:22.808Z

Opening the discussion for EIP-5630; see edit: link to the EIP: ERC-5630: New approach for encryption / decryption

Author: darcys22
Date: 2022-09-10T06:34:33.714Z

I love this idea, a pretty big thing i wanted for ERC5570 was to encrypt the receipts so they were private. So wanted a way for a business to encrypt the metadata of an nft against the owners address.
This implementation seems to separate the decryption key, this is great because it would mean you could provide the decrypting key to an external financial system without giving it the ability to sign transactions and send fund.

Author: firnprotocol
Date: 2022-09-10T12:18:30.793Z

exactly! and yes, you’re correct that the decryption key is separated. appreciate the feedback.

Author: SamWilsn
Date: 2022-09-19T14:41:42.921Z

Is retrieving a recipient’s public key out of scope for this EIP? If so, would you be open to working on a standard for doing that as well? I’ve been toying with the idea of publishing PGP keys to ENS. Perhaps something like that would work.

Author: firnprotocol
Date: 2022-09-19T15:52:01.767Z

good question. retrieving the public key is very much in scope, and is in fact spec’d out in the EIP. edit what’s spec’d is a local RPC routine to retrieve your own public key. what you then do with that—e.g., whether you publish it to ENS, or something else—is not (currently) in scope. perhaps there should be a separate EIP to dictate how exactly that key gets serialized and published to ENS?
I’m pretty sure PGP keys are RSA; we are opting to use secp256k1 keys instead. this is essentially for cryptographic and compatibility reasons. but other than that—yes, publishing these to ENS would be absolutely a good idea! let me know if you have questions.

Author: Pandapip1
Date: 2022-09-19T16:20:43.341Z

firnprotocol:

I’m pretty sure PGP keys are RSA;


If you want to use GPG keys instead, those support many more schemes - including ECDSA

Author: firnprotocol
Date: 2022-09-19T16:40:00.274Z

hmm. it would be intriguing to make our decrypt spec exactly match what GPG does. if possible. GPG says that they support “ECDH” over secp256k1. (this is confusing, since, ECDH is a key agreement scheme, not an encryption scheme. so I assume they actually mean ECIES?)

Author: firnprotocol
Date: 2022-09-19T16:56:17.114Z

update: as far as I can tell, GPG doesn’t support full-on ECIES, only ECDH. so drop-in replacement might not be viable. moreover, it appears that their ECDH spec makes some weird choices, including a KDF which differs from [SEC 1, § 3.1.6] (in particular, they put the 4 counter bytes on the left of the message, instead of on the right). so not sure how fruitful this direction is. note that implementing SEC 1-compliant ECIES “from scratch” is not difficult; we’ve already built a reference implementation at GitHub - firnprotocol/eth-sig-util at encryption (using a very good existing library).
so, to put it simply, i think the idea is absolutely the right one, but whether we “formally” can agree with GPG is hard to say. in any case, you can get the same functionality regardless.

Author: kdenhartog
Date: 2022-09-19T20:47:58.243Z

ECDH is being used to setup a symmetrical encryption key rather than using asymmetric encryption (ECDH) since asymmetric is notoriously slow in comparison when encrypting large messages and hits other cryptographic limitations that aren’t traditionally faced.
I still don’t believe the current design here is a good fit as it’s only a one way encryption scheme meant only to encrypt messages from the dApp to the wallet.

Author: kdenhartog
Date: 2022-09-19T20:48:57.300Z

When you say a “recipient’s key” who would be playing the role of a recipient?

Author: kdenhartog
Date: 2022-09-19T20:50:11.043Z

Can we take a step back here and align on what use case we’re trying to solve and what’s the threat model we’re trying to address? I don’t think we’ve got alignment on that yet.

Author: firnprotocol
Date: 2022-09-19T21:07:14.110Z

kdenhartog:

I still don’t believe the current design here is a good fit as it’s only a one way encryption scheme meant only to encrypt messages from the dApp to the wallet.


I’m truly at a loss to understand your objection, to be honest. All public-key encryption schemes are “one-way”, by definition. And no, encryption from dApp to wallet is not the only intended use here.

Author: SamWilsn
Date: 2022-09-19T21:16:02.752Z

kdenhartog:

I still don’t believe the current design here is a good fit as it’s only a one way encryption scheme meant only to encrypt messages from the dApp to the wallet.


Ah, I see. So this EIP is more about creating a secure keystore than it is about general purpose encrypted messaging. The note about e2e encrypted messaging threw me off.



 kdenhartog:

When you say a “recipient’s key” who would be playing the role of a recipient?


I’m imagining the scenario where you want to send me an encrypted message without having communicated beforehand. I would be the recipient.
In light of my new understanding above, I guess the pattern would be to:

Create a new public/private key pair.
Publish the public key using some other EIP (maybe using ENS.)
Request an encryption key using eth_getEncryptionPublicKey.
Encrypt the private key created in (1) using the the key from (3).
Publish the encrypted private key using some other EIP.

Then anyone wanting to message me could retrieve my public key from ENS, and send the message. I could read the message by fetching my encrypted private key, decrypting using eth_decrypt, and then decrypting the message.

Author: firnprotocol
Date: 2022-09-19T21:23:34.996Z

SamWilsn:

Ah, I see. So this EIP is more about creating a secure keystore than it is about general purpose encrypted messaging. The note about e2e encrypted messaging threw me off.


That is not the intention—we do want to be able to support e2e messaging here.



 SamWilsn:

In light of my new understanding above, I guess the pattern would be to:

Create a new public/private key pair.
Publish the public key using some other EIP (maybe using ENS.)
Request an encryption key using eth_getEncryptionPublicKey.
Encrypt the private key created in (1) using the the key from (3).
Publish the encrypted private key using some other EIP.

Then anyone wanting to message me could retrieve my public key from ENS, and send the message. I could read the message by fetching my encrypted private key, decrypting using eth_decrypt , and then decrypting the message.


I think this is more complicated than you need! here would be the flow:

locally call eth_getEncryptionPublicKey; obtain a public encryption key.
post that key to your ENS.

then whenever anyone wants to encrypt to you, they retrieve the public key from your ENS, encrypt locally, and then send the ciphertext to you. you decrypt using eth_decrypt. no need to generate a separate keypair, and encrypt its secret key.

Author: kdenhartog
Date: 2022-09-19T21:24:03.161Z

And no , encryption from dApp to wallet is not the only intended use here.

Cool let’s start by listing off the ones that we’re working for here because in my experience building 2 versions of an asynchronous messaging protocol (DIDComm V1 and V2) we’re going to go around and around in circles on this if we don’t define this first.

Author: firnprotocol
Date: 2022-09-19T21:35:33.523Z

sure. i think our preliminary list of target use cases can be:

encrypt/decrypt from a dApp to a user’s wallet.
end-to-end encrypted messaging.

(1) we’ve already discussed—but I think we’re also fully equipped to support (2) in this EIP too (if you think otherwise, let me know why). namely, the flow would be as suggested above:



 firnprotocol:


locally call eth_getEncryptionPublicKey; obtain a public encryption key.
post that key to your ENS.

then whenever anyone wants to encrypt to you, they retrieve the public key from your ENS, encrypt locally, and then send the ciphertext to you. you decrypt using eth_decrypt.


let me know your thoughts.

Author: firnprotocol
Date: 2022-09-19T21:42:41.709Z

firnprotocol:

then send the ciphertext to you


as far as the details of how to “send”: though it’s probably out of scope for this EIP (and might be worth a separate EIP), one way to do it would be to create a simple contract (or extend ENS) with a mapping (address => bytes[]), essentially associating to each address / ENS name an arbitrary-length, append-only list of ciphertexts. anybody could freely append a ciphertext, i.e. a bytes, to this list—it’d be the “inbox” for that ENS. then the user can trivially go through this list and locally eth_decrypt each new message it gets.
there could even be a fun extension where you have to pay someone to send them a message.

Author: kdenhartog
Date: 2022-09-20T02:02:48.421Z

encrypt/decrypt from a dApp to a user’s wallet.
end-to-end encrypted messaging.


Some other cases to consider:
For end-to-end encrypted messaging or are we doing 1 to 1 messaging only or group messaging and what size groups are we thinking here?
Are we expecting both parties to be online (synchronous communication) or are we planning for some parties to be offline (async communication)?
Ok, now just taking these two uses cases let’s start to build a threat model for this.
Some things to consider:
Is dApp to wallet communication bi-directional (any party can encrypt a message from one to another) or uni-directional (e.g. only one party can encrypt a message for another)? Follow up discussion for this:

How do we handle key discovery for these parties whether bi-directional or uni-directional?
How does key rotation occur? With signing crypto operations limits of keys are much larger if there are any to the point they can largely be ignored. With ECIES though we’re limited based on the cipher chosen.
How are nonces being coordinated to prevent nonce reuse attacks if AES-CTR or AES-GCM is used?
How are we transporting these ciphertexts and what sort of adversarial actors are we looking to avoid here?
Are we attempting to achieve perfect forward secrecy, weak perfect forward secrecy, or post compromise security?
What integrity guarantees are we looking to achieve?
What’s the average size of a message we’re expecting? 100KB/10MB/1GB

Are we wanting to store these messages as well?

If so are we planning to re-encrypt the message once received or are we going to store it as received?
Are we planning to publish them to the chain?
Doesn’t that introduce gas fees?
What if a user doesn’t pick the message up by the time the block gets pruned?
What if a key is broken or an implementation vulnerability is discovered later so that the ciphertext is able to be decrypted later?

What’s our adversarial privacy threat model look like since we want to provide confidentiality guarantees?

How are we linking the controller of a key to the subject of the ethereum account (do we even care who the subject is?) to know that the identity is trusted and someone we want to share information with?
What time frame are we trying to keep the plaintext message confidential?

These are just some of the questions we should be aligning on first before we start working on a solution here because each of these is going to lead to a different type of solution. Furthermore the more use cases we try to address at once the more likely we’re going to end up with a far more complex solution.
For example, take a look at Message Layer Security (MLS) to see how complex group messaging can become.

Author: kdenhartog
Date: 2022-09-20T02:07:32.524Z

Even with DIDComm V2 we ended up with a lot of optionality that’s pretty hard to parse through and that decided to exclude group messaging beyond the scope of a single DID.
Additionally, given walletconnect is looking to address the E2E messaging case, would it make sense for us to remain focused on just dApp to wallet communication?

Author: firnprotocol
Date: 2022-09-20T19:24:03.161Z

thank you for the questions. i want to please ask that we limit the scope of this discussion to this EIP, which specifies a way to do simple encryption and decryption. while most of your questions are legitimate, they are concerns for the builders of applications, and lie beyond the scope of this EIP.



 kdenhartog:

How do we handle key discovery for these parties whether bi-directional or uni-directional?


though it’s out of scope, one way would be to use ENS (by adding a “public key” field), or something like it.



 kdenhartog:

How does key rotation occur? With signing crypto operations limits of keys are much larger if there are any to the point they can largely be ignored. With ECIES though we’re limited based on the cipher chosen.


the message length limitation is only per message, and has nothing to do with encrypting many different messages under the same key. moreover, CBC mode appears to have no length limit. if you want to adopt a key rotation strategy, that’s up to you—same as in the case of signing.



 kdenhartog:

How are nonces being coordinated to prevent nonce reuse attacks if AES-CTR or AES-GCM is used?


note that we propose CBC mode. the determination of IV is fully specified by the spec; as for the generation of random ephemeral keys, this is handled by the spec and by the implementation.



 kdenhartog:

How are we transporting these ciphertexts and what sort of adversarial actors are we looking to avoid here?


transport of ciphertexts is out of scope (though could optionally be done on-chain; see my comments above). the adversarial model is the standard one: indistinguishable multiple encryptions under chosen ciphertext attack. ECIES satisfies this.



 kdenhartog:

Are we attempting to achieve perfect forward secrecy, weak perfect forward secrecy, or post compromise security?


these could be optionally achieved by building on top of this EIP, but they’re out of scope—this EIP only provides simple encryption.



 kdenhartog:

What integrity guarantees are we looking to achieve?


the same ones ECIES guarantees: CCA-security.



 kdenhartog:

What’s the average size of a message we’re expecting? 100KB/10MB/1GB


up to the user.



 kdenhartog:

If so are we planning to re-encrypt the message once received or are we going to store it as received?


up to the client to do whatever it wants with its messages.



 kdenhartog:

Are we planning to publish them to the chain?


up to the users.



 kdenhartog:

Doesn’t that introduce gas fees?


if you choose to publish your messages on chain, then yes; otherwise, no.



 kdenhartog:

What if a user doesn’t pick the message up by the time the block gets pruned?


i have to say that I don’t find to be a legitimate question. Ethereum state doesn’t get “pruned”. perhaps if you only post it to calldata, but not anywhere in contract storage, then this could be an issue; if some user were to choose to operate in that way, then that user would need access to a full (archive) node.



 kdenhartog:

How are we linking the controller of a key to the subject of the ethereum account (do we even care who the subject is?) to know that the identity is trusted and someone we want to share information with?


it’s up to the consumer of this API to do this however it wants. one way would be to publish your public encryption key to your own ENS, or elsewhere on-chain that links the public key to your known Ethereum address.



 kdenhartog:

Additionally, given walletconnect is looking to address the E2E messaging case, would it make sense for us to remain focused on just dApp to wallet communication?


I don’t see a rationale for narrowing the scope, since that project appears tied to a specific product, and not Ethereum-wide.

Author: friedtrout
Date: 2022-09-20T20:11:27.583Z

@kdenhartog Thanks for your questions.
I think it’s worth reiterating the actual point of this EIP: We want to create a simple generic way of leveraging Ethereum keys to securely encrypt and decrypt generic bytes. Importantly, this EIP avoids being prescriptive of how this functionality can be used, e.g. off-chain or on-chain. The key is that the capability of encryption/decryption is a natural fit for Ethereum.
The core components of this EIP are the encryption spec used and how the encryption/decryption keys are derived. We should consider which questions are relevant to the EIP itself, versus design decisions for products or tooling that could leverage this EIP.

Author: TJKoury
Date: 2022-09-20T20:29:07.147Z

Throwing my support behind @firnprotocol here.  This proposed standard is necessary to begin exploring integrating encryption into Ethereum apps by describing an implementation agnostic, isomorphic algorithm.  Any other consideration including key exchange / discovery, message transport / storage, identity management, et al. is far beyond scope.
@kdenhartog While I applaud your attempts to consider all facets of this issue, the main problem being addressed here is the lack of a standardized way to encrypt and decrypt messages.
In my opinion @firnprotocol has sufficiently documented a method by which entropy is deterministically generated for the key material using widely available and well-tested algorithms, and specified how to use secp256k1 key pairs with the ECIES algorithm.
Let’s keep the comments to discussing key generation and encryption algorithms.

Author: kdenhartog
Date: 2022-09-20T20:58:07.628Z

the main problem being addressed here is the lack of a standardized way to encrypt and decrypt messages

This has existed for nearly 3 years before MM decided to deprecate it. Even today, this API is still available and usable. My point is these APIs are hardly used and we should utilize this hindsight to inform the design. Compare the usage of eth_getEncryptionPublicKey to eth_sign.
Has anyone looked at this at all or any other wallet API call insights to consider this?
I think at this point we’re talking past each other because I’m trying to look at the forest and assess the landscape where as it seems others are focused on a specific tree. That’s ok, if all you want to ship is a small patch to improve this that works and I’ve said as such in the PR. Fundamentally I think the necessary changes, no matter how small they are, aren’t worth shipping in any wallet because they’ll be a wasted effort in dev time given the current adoption seen so far.
I’ll leave it at that.

Author: firnprotocol
Date: 2022-09-20T21:35:04.173Z

kdenhartog:

My point is these APIs are hardly used and we should utilize this hindsight to inform the design.


just a factual clarification / point of order: I think this not quite accuate. Tornado uses it, and has large usership.
and—to the extent they’re not used much—it might be because of lack of support. only non-mobile MetaMask used to support it (and now no one does).

Author: kdenhartog
Date: 2022-09-20T23:47:47.872Z

only non-mobile MetaMask used to support it

What I’m gathering from this is it was (and still is) available on millions of wallets which didn’t attract enough dApp support to get other wallets interested in supporting it? I get that you’re processing these facts in a different way, but even if I’m wrong and you’re correct that it didn’t get supported because wallets didn’t implement we have to look objectively at what is clear. Wallets don’t consider this work a priority to implement after 3 years of roadmap planning. So how do we need to change that to make it a larger priority? Changing cryptographic algorithms won’t do that. We need to deliver additional value.
AFAICT you’re only further supporting the point that this was a bad design from the outset. It can’t even support one of the use cases you’ve pointed out so far: end-to-end encrypted messaging. As currently speced wallets cannot encrypt messages. They can only decrypt them.
Why are you so adamant on keeping this? It genuinely doesn’t make sense to me.

Author: friedtrout
Date: 2022-09-21T03:05:46.212Z

@kdenhartog
You’re completely right that it is important to understand what the priority is for wallets. We absolutely will be having discussions with these wallets to understand what is valuable for them, and why they may have discontinued support for the original encryption scheme. There’s no point to an EIP that won’t be used by the community.
That being said, this EIP is simply the core component that can be used to create many interesting protocols, tools, services. What we should be looking at is if there’s something irreversible in our proposal that could negatively impact potential future use-cases. We can always look into and define key discovery protocols or standards for storing/ sending ciphertexts in the future (for e2e encrypted messaging), but these questions can be discussed further down the road.
You’re correct about needing to deliver additional value. As mentioned in the proposal, the improvements are two fold: The EIP provides a sound encryption scheme that leverages only a single curve (the previous implementation juggled two), it also separates out the functionality of signing and encryption keys.

Author: kdenhartog
Date: 2022-09-21T06:43:31.095Z

We absolutely will be having discussions with these wallets to understand what is valuable for them

Please note, I work for Brave on our security team and I’ve been syncing with our wallet team on this. I’ve also briefly discussed this with Metamask because I’m the person who originally reported the issue of key reuse to them when I was auditing our implementation and realized this wasn’t ideal so reported it to them.
My views represent at least a single wallet here. Additionally, from my brief chats with Metamask during the reporting process my impression was they have similar views to me here. My take away from it was they don’t consider this functionality a massive priority, but are still interested in supporting it if they can justify the effort for the change. I don’t speak for them and could also be misinterpreting their views though, so I’ll let them comment here if they wish.
I’ve also notified the Ethereum Wallets discord server of this topic to get their opinion on this topic (only 3 days ago) and so far no one has taken an interest other than @SamWilsn. I’m trying to provide legitimate feedback here, but I feel like I’m not getting anywhere and I’ve got 3 people who are digging their feet in every time I try and contribute. Right now, it seems it would be a better use of my time to cut my losses and work on a separate EIP. I don’t want to do this, since I’d rather be working with dApp developers who want to use these APIs, but I’m getting no where by doing this.

The EIP provides a sound encryption scheme that leverages only a single curve (the previous implementation juggled two)

Huh, I’m confused here, who only has to use a single curve? The dApp only needs to use a single curve whether it’s Ed25519 or secp256k1. The wallet needs to use multiple curves… sure, but that’s not that big of a deal from our perspective. In fact, we’ve already implemented it as such because we support Solana as well as EVM networks. Similarly, it seems like more wallets are already considering supporting multiple chains as they consider becoming multichain so I don’t think this is that big of a concern.
Originally, the security concern here that I reported to metamask was the reuse of key material for different operations that didn’t have a security proof. It’s not directly vulnerable, but it’s also not a crypto best practice and given millions if not billions of dollars depend on these wallets erroring on the side of caution was the same bet. I appreciate metamask taking the stance they have. With that in mind, this could easily be solved with just using a different salt with the KDF function. This would achieve the domain separation as defined in the papers I originally linked and is a smaller change than what @firnprotocol has proposed.

it also separates out the functionality of signing and encryption keys.

Can you be a bit more detailed in what you mean here? You’ve confused me here with this point because it seems like this contradicts the previous point that a single curve can now be used. The original design meets this requirement as well by supporting signing and encryption but not in a way that’s provably secure because the KDF digest is reused. That’s why I’m confused by this.

Author: friedtrout
Date: 2022-09-21T21:53:30.975Z

kdenhartog:

Huh, I’m confused here, who only has to use a single curve? The dApp only needs to use a single curve whether it’s Ed25519 or secp256k1.


Note that this is an EIP, using just secp256k1 leverages the fact that Ethereum already supports secp256k1 crypto operations, and prevents any bloat of adding a second curve.



 kdenhartog:

With that in mind, this could easily be solved with just using a different salt with the KDF function.


Yeah, I think we’re in agreement here! Our proposal uses a KDF to derive an encryption/decryption key pair to be used for encryption/decryption functionality.



 kdenhartog:

Can you be a bit more detailed in what you mean here? You’ve confused me here with this point because it seems like this contradicts the previous point that a single curve can now be used.


Absolutely. While we use the same curve for signing vs encryption, the proposal derives an encryption/decryption keypair which is distinct from the signing/verifying keypair, as mentioned above.

Author: kdenhartog
Date: 2022-09-22T00:54:20.525Z

Yeah, I think we’re in agreement here! Our proposal uses a KDF to derive an encryption/decryption key pair to be used for encryption/decryption functionality.

There’s a nuance here that’s important. If we use different curves we need to use different deterministic salts with the KDF to achieve domain separation.
Instead, with the ECIES/ECDSA re-usage we’re relying on the soundness of a different security proof here.

Author: kdenhartog
Date: 2022-09-22T00:55:35.734Z

encryption/decryption keypair which is distinct from the signing/verifying keypair

This isn’t correct to my understanding. The same keypair would be used, but since there’s been a security proof to show this isn’t a concern we would consider it acceptable.

Author: kdenhartog
Date: 2022-09-22T01:00:35.786Z

Note that this is an EIP, using just secp256k1 leverages the fact that Ethereum already supports secp256k1 crypto operations, and prevents any bloat of adding a second curve.

Ethereum also supports many other curves (Pairing based crypto is needed for rollups and BLS Signatures were added when The beacon chain HF occured to support The merge HF) and never was intended to be locked to a single curve implementation. Please take a look at the motivations of EIP-86 and the further related efforts under account abstraction.
In fact, I’m pretty sure @firnprotocol would have to be using pairing based crypto to achieve the onchain protocol that they’re implementing, but it’s not obvious to me which curve is in use based on their code.

Author: friedtrout
Date: 2022-09-22T01:57:53.242Z

kdenhartog:

This isn’t correct to my understanding. The same keypair would be used, but since there’s been a security proof to show this isn’t a concern we would consider it acceptable.


Your latter statement is correct! By Degabriele et al., it is secure to use the same key for ECDSA and ECIES in the generic group model. Given this, we decided to take a slightly more conservative and hygienic approach by deriving a separate enc/dec keypair from the signing key. Degrabriele et al. proves that this could be done using the same keypair, but we leverage a KDF to additionally establish distinct decryption vs signing keys, just as a low-cost, conservative measure.

Author: AustinZhu
Date: 2022-09-29T17:14:03.000Z

This is awesome!
Currently I’m developing an SBT protocol for managing credentials and memberships. We have an extension in our contract for managing the visibility of a token, so people can make their SBT private. To protect the owner’s privacy we also need to make sure that the off-chain data gets encrypted. I’ve thought about something like PGP encryption for emails.
Now if this gets supported by wallets it will be easier to encrypt/decrypt the metadata!
BTW: We have submitted our EIP draft and if you guys are interested please check.
https://github.com/ethereum/EIPs/pull/5727

Author: firnprotocol
Date: 2022-09-30T00:49:15.922Z

awesome! i’ll take a look; glad to have you interested in this EIP and on board.

Author: rekmarks
Date: 2022-10-03T20:45:41.025Z

Speaking as a maintainer of MetaMask, we want to support an encryption / decryption feature, and are grateful for the work everyone here is putting into creating a new standard.
I want to note that we have strong reservations about supporting encryption and decryption using secp256k1 due the concerns outlined here: blog/secp256k1_twist_attacks.md at master · christianlundkvist/blog · GitHub
In my understanding, secp256k1 is rarely if ever used for encryption / decryption. The only justification I’ve seen for it in this thread is that it’s convenient for the Ethereum ecosystem, and that strikes me as a weak argument. Using e.g. curve25519 as @chrislundkvist suggests in the above blog post would be our preference, and doing so would make us more likely to implement this standard, not less.

Author: firnprotocol
Date: 2022-10-03T20:59:59.576Z

hi @rekmarks. many thanks for the response and good to hear from you.
i want to first be clear about a few conceptual matters before we proceed. as i understand, this is an attack on ECDH, and ECIES is completely unaffected. indeed, it can only take place when the victim exponentiates an attacker-supplied point by a sensitive scalar, and then sends the result back to the attacker. but this pattern only happens in ECDH, and never in ECIES. since, in ECIES, the only sensitive Diffie–Hellman operation happens during decryption, but in this case the victim—who would be the decryptor—will never send the resulting DH point back to the attacker (and will only use it to attempt an AES decryption). keep in mind that ECIES has an asymmetry which ECDH doesn’t.
(there is a further Diffie–Hellman operation which happens during encryption; indeed, the encryptor exponentiates the decryptor’s public key by an ephemeral scalar. here too the attack would be useless, since there’s nothing to learn—the exponent here is ephemeral, not persistent.)
separately—even in the ECDH case—this sort of attack is only possible when using uncompressed points (we use compressed), and is moreover only possible when the implementation fails to check whether a point is on the curve.
before we discuss further merits of using secp256k1 vs. curve25519 i want to make sure we are in agreement on the above first? look forward to continuing the discussion.

Author: kdenhartog
Date: 2022-10-03T21:00:58.701Z

It’s worth jumping in here to highlight what I’m thinking with regards to a storage solution further here.
I’m in favor of an inbox style approach where it’s more like wallet_store(message: JSON) call. It’s still encrypted message, and by starting with storage we can build messaging primitives upwards from this design that lead to an async messaging protocol able to be built on top. E.g. think of encrypted email with an inbox style endpoint that can be managed by the wallet.
Wayne Change from Spruce does a good job describing the concept briefly in this talk: Ethereum's Identity Layer - Impact of Ethereum Presentation
Spitballing here as to what this might look like wallet_store() could just expose something like a decentralized web node. This way we’re able to reuse a lot of the design.
With that said, I’ll note that we’ve got a second dApp here interested in using this API, so my theory may be invalid that this is too low level to be useful. So let me add some questions if we were going to take this encrypt/decrypt API approach and run with it. (and then work on storage separately)

How would we expose to the user the encrypt API for the message flowing from the user to the dApp?
What use cases would we expect to address here and more importantly what use cases are we leaving on the table by picking this design? The more specific we can be here the better.
Do we leave message migration (even between wallets maintained by the same company such as Metamask mobile and metamask extension) out of scope?

Author: firnprotocol
Date: 2022-10-06T15:38:56.518Z

rekmarks:

In my understanding, secp256k1 is rarely if ever used for encryption / decryption.


btw, while I think this is technically true, note that P256 is often used for encryption / decryption, and the P256 and secp256k1 curves are extremely similar in spirit. In particular, both are Weierstrass curves, and are equally vulnerable to this “attack” (though as argued above, it appears the attack doesn’t apply to ECIES). in particular, ECIES with P256 is supported by many hardware enclaves, e.g. iOS’s.

Author: xinbenlv
Date: 2022-10-06T16:57:56.405Z

@firnprotocol thanks for proposing. Very interesting EIP. I look forward to it!
I am thinking this encryption and decryption can also be leveraged by EIP-5437: Security Contact Interface

Author: firnprotocol
Date: 2022-10-06T17:15:26.182Z

fascinating. i agree completely!
in fact, your proposal looks almost exactly like the “inbox” idea we discussed above. see this quote e.g.:



 firnprotocol:

as far as the details of how to “send”: though it’s probably out of scope for this EIP (and might be worth a separate EIP), one way to do it would be to create a simple contract (or extend ENS) with a mapping (address => bytes[]), essentially associating to each address / ENS name an arbitrary-length, append-only list of ciphertexts. anybody could freely append a ciphertext, i.e. a bytes, to this list—it’d be the “inbox” for that ENS. then the user can trivially go through this list and locally eth_decrypt each new message it gets.
there could even be a fun extension where you have to pay someone to send them a message.


thus I think our proposals are very much complementary and glad to see you have done this 
(the only difference appears to be using GPG w/ RSA vs. ECIES. though the former is somewhat more standard, the latter has smaller key sizes and ciphertexts. but it seems that your proposal is ultimately agnostic to the encryption scheme used.)
really appreciate you sharing, and look forward to continuing the discussion.

Author: kdenhartog
Date: 2022-10-08T11:13:44.102Z

EIP-5630 + EIP-5437 sounds cost prohibitive for a generic inbox style messaging system. It also sounds like it would discourage reporting bugs. If this is done it’s going to be limited in scope of usage to only high value messages. Gas fees already can touch $5+ for a transaction on L1 at peek capacity and the incentives don’t align for security researchers to report vulnerabilities if there’s an additional cost to submit a bug report.
This seems like it would be recreating the economics of email spam protection mechanisms that were never widely used. I don’t think this would be useful. Can someone explain the usefulness of this from the security researcher’s perspective that would justify why this is better than a H1 bug bounty program?

Author: cjpais
Date: 2022-10-25T16:31:47.907Z

I am interested in this EIP and curious to help push it forward in whatever form. I think there are a large variety of use cases.
I am most interested in building an encrypted filesystem primitive. The file is a well established pattern and will help bring the EVM up a level of abstraction to more users. This primitive alone enables many new use cases.
A filesystem/namespace could generally looks like Upspin to start. In terms of cryptography and access control Upspin chooses to implement something very similar to what is suggested by @SamWilsn. That is: using asymmetric keys for encrypting a symmetric passcode which then encrypts a file. This method could reasonably be used to share files and do access control.



 SamWilsn:

In light of my new understanding above, I guess the pattern would be to:

Create a new public/private key pair.
Publish the public key using some other EIP (maybe using ENS.)
Request an encryption key using eth_getEncryptionPublicKey.
Encrypt the private key created in (1) using the the key from (3).
Publish the encrypted private key using some other EIP.



I’ve built a proto-version of this using the deprecated eth_encrypt and eth_decrypt provided by MetaMask, and it would be nice to have an EIP which is well supported across many wallet implementations. I have no preference for curves, so whatever seems most cryptographically secure seems to make sense. I think it seems like this would be curve25519 instead of secp256k1.
On top of such a filesystem primitive many applications could be built. Messaging. Encrypted File Sharing. Encrypted Group Photo Albums. Encrypted GPS data. Helping to give people better ownership and control over their data using ETH address as an identifier. This may not ultimately be enough to solve UX problems, but may get us closer to revealing what is possible through mainstream adoption of asymmetric public key cryptography by the way of a decentralized system at the user level.
@rekmarks in terms of supporting a new standard from MetaMask’s perspective, what would be the key functionality or difference from the original EIP-1024’s specification you’d be looking for?
Also curious from @kdenhartog, what would be required for adoption of a fairly generic encryption/decryption EIP? What is left for something like this to have approval? Choice of curve? More specific methodology? Anything else?

Author: firnprotocol
Date: 2022-10-25T17:37:16.599Z

hi @cjpais, thanks for the message, and glad to have you on board! i absolutely agree with the applications you proposed.



 cjpais:

I have no preference for curves, so whatever seems most cryptographically secure seems to make sense. I think it seems like this would be curve25519 instead of secp256k1.


regarding the matter of curves, i have already weighed in above: see the message beginning



 firnprotocol:

i want to first be clear about a few conceptual matters before we proceed.


as well as the subsequent one. as I’ve already “made my case” on this front, I will defer from further comment at this time, and let the community come to an agreement on this one (though if further input is wanted from me, I’m happy to give it).



 cjpais:

@rekmarks in terms of supporting a new standard from MetaMask’s perspective, what would be the key functionality or difference from the original EIP-1024’s specification you’d be looking for?


my best stab at answering this question would be, “avoid the reuse of the same secret key in two different curves”. thus, something like our use of a KDF is perhaps what’s wanted. (others have taken issue with the fact that we additionally use secp256k1 for the encryption curve, though, as I’ve made clear above, I emphatically maintain that this is not a security concern.) happy to advocate for this with you, as well as discuss any questions you have.

Author: ronaldmannak
Date: 2022-10-26T23:28:29.911Z

I’m very excited to see a follow up to EIP-1024. I’m one of the developers of Moonfish, basically a GPG-like solution for email using Ethereum keys.
If the decision to use a single curve was made to make the life of wallet developers easy, I have to agree with @kdenhartog. Using two curves shouldn’t be an issue. I’d suggest to use proven models, unless there is a good reason not to (there might be one that I missed, feel free to correct me).
As I understand the proposal, the intention is to encrypt the message itself asymmetrically. While this works, I do see two possible issues:


I am not sure if it’s still an issue on modern devices, but asymmetric encryption is slower than symmetric encryption. If you want to scale the solution for use with large attachments or files (as mentioned in one comment), you might run into performance issues on low-end devices. Then again, maybe it’s not an issue, but I would certainly benchmark it.


The current proposal doesn’t seem to support multiple recipients, a common scenario in messaging and email.


Have you considered using the GPG model where the message itself is encrypted with a one-time symmetrical session key, and the session key itself is encrypted with the recipient’s public key? This would scale for multiple recipients.
Another things worth considering is adding metadata to the standard, such as chainID and the public keys/addresses of the sender and all recipients to simplify replying to an encrypted message.

Author: ronaldmannak
Date: 2022-10-26T23:29:06.854Z

Have you considered extending Age?

Author: Weiji
Date: 2022-10-31T08:36:03.146Z

friedtrout:

Your latter statement is correct! By Degabriele et al. , it is secure to use the same key for ECDSA and ECIES in the generic group model. Given this, we decided to take a slightly more conservative and hygienic approach by deriving a separate enc/dec keypair from the signing key. Degrabriele et al. proves that this could be done using the same keypair, but we leverage a KDF to additionally establish distinct decryption vs signing keys, just as a low-cost, conservative measure.


I’d like to point out the implications of this to a MPC/TSS controlled wallet. It seems to me very difficult if not infeasible to derive a new key pair if the underlying secret key is controlled by multiple parties through some TSS scheme, like GG18/GG20 or some other similar ones.
Also, if we keep using the same key pair, then the public key is available if the account had signed any messages on-chain: ECDSA allows public key recovery from signature. This will save lots of troubles of key discovery.

Author: Weiji
Date: 2022-11-01T02:31:37.532Z

Also as Ethereum accounts are migrating to Account Abstraction / ERC-4337 contracts, maybe it makes sense to allow contracts to have an API to expose its public key for encryption purposes.

Author: firnprotocol
Date: 2022-11-06T14:36:49.095Z

Weiji:

Also, if we keep using the same key pair, then the public key is available if the account had signed any messages on-chain: ECDSA allows public key recovery from signature. This will save lots of troubles of key discovery.


this is an interesting point about key discovery. i am actually perfectly open to using literally the same secp256k1 keypair for both signing and decryption. as remarked above, this scheme is proven secure in the generic group model, and is probably the best from a simplicitly standpoint. cc. @kdenhartog.



 Weiji:

I’d like to point out the implications of this to a MPC/TSS controlled wallet. It seems to me very difficult if not infeasible to derive a new key pair if the underlying secret key is controlled by multiple parties through some TSS scheme


you’re absolutely right. FWIW, it is possible to do HKDF through MPC, or, at least, 2PC, and even to do it relatively efficiently (say, using garbled circuits), but it is very difficult implementation-wise. so I agree that this would be essentially prohibitive.

Author: kdenhartog
Date: 2022-11-06T22:07:24.325Z

Also curious from @kdenhartog, what would be required for adoption of a fairly generic encryption/decryption EIP? What is left for something like this to have approval? Choice of curve? More specific methodology? Anything else?

First off, support should be added for both encryption and decryption in a bilateral direction. It seems everyone here wants to focus on the bikeshed of which cryptographic primitives to use, without considering there’s no widely deployed solution for a dApp to have a public key so we’ll still be stuck with every request to the dApp being sent over TLS, but all the responses are encrypted to the ethereum account.
This is effectively like building TLS where the browser only sends HTTP requests and the server only responds with HTTPS responses.

Author: firnprotocol
Date: 2022-11-07T01:15:55.120Z

let’s keep the tone respectful, please.

Author: kdenhartog
Date: 2022-11-07T01:47:15.781Z

Happy to edit my comment since it’s tone has come off in a way other than intended. Which parts would you like changed?

Author: Weiji
Date: 2022-11-07T02:10:29.417Z

kdenhartog:

support should be added for both encryption and decryption in a bilateral direction … there’s no widely deployed solution for a dApp to have a public key


Could you please elaborate why this is so important or even a prerequisite? What are the use cases besides a TLS connection?

Author: kdenhartog
Date: 2022-11-07T02:41:42.766Z

Sure, the user wishes to send a confidential transaction to the mixer dApp in order to submit a private transaction where the only party they’re willing to reveal the amount to is the dApp.
Today, these confidentiality guarantees to send a request to a dApp is handled by the TLS session which is good enough for most people. If we believe TLS is good enough for the request then I don’t see the reason it’s not good enough for the response.
If we don’t believe TLS is good enough for the response from the dApp and therefore believe we need an additional message layer security in order to provide better confidentiality then we should also provide the same guarantees for the request.
Put another way as a question, which API defined in this EIP do I as a wallet developer call in order to enable my user to send an encrypted message to firn protocol’s dApp?

Author: Weiji
Date: 2022-11-07T02:45:20.995Z

Thanks. This is a fair point. Maybe we need to clarify what exactly is the “user → dApp” use case and why TLS not enough for some cases.

Author: kdenhartog
Date: 2022-11-07T02:49:16.145Z

Finally, someone else sees what I’m try to convey. This is what I’ve been trying to convince others of for awhile and I must just not be conveying the problem clearly enough if it’s only now just clicking for people.

Author: firnprotocol
Date: 2022-11-07T13:32:23.508Z

to be honest, i still don’t see the problem. it’s easy to securely associate a public key to your Ethereum account:

if you’re an EOA, post it as an entry in some contract, exactly like how ENS does.
if you’re a contract, just expose a public pure function returning the key.

this completely bypasses the need for “TLS”, since we’re assuming that the user/client already knows your ethereum address, and has reliable access to a node. so relevant the TLS happens between the user and the node, not between the user and the dapp. meanwhile, the authenticity of the public key comes from the fact that it was posted by someone with control over that ethereum account.

Author: firnprotocol
Date: 2022-11-07T13:34:38.678Z

kdenhartog:

Put another way as a question, which API defined in this EIP do I as a wallet developer call in order to enable my user to send an encrypted message to firn protocol’s dApp?


i’m sorry, but this doesn’t compute. you would call some “get public key” function exposed by the dapp. the dapp would deliver the public key. you would locally encrypt under that key. you would then send the ciphertext to the dapp. what’s wrong with this?
actually this is a much less difficult case, since the public key depends only on the dapp, not the user. so it could even be hardcoded in the static front-end. if you wanted to authenticate the public key, you would use the technique in the post above.

Author: firnprotocol
Date: 2022-11-07T13:59:30.703Z

i think there may be some serious misunderstandings here, so i want to step back and address these. in the cases relevant to this EIP, the “dapp” is a purely static front-end, containing some javascript UI / recipes which allow a user to more easily interact with some on-chain contracts, together with these contracts themselves. so there is no meaningful “TLS” engaged in between the user and the dapp. (rather, the TLS happens between the user and whoever serves the static content, say the IPFS gateway.) in fact, that’s arguably the whole point of this EIP: if you want to send something confidentially to the “dapp”, where do you send it? the “dapp” doesn’t exist as something that can live on the other end of a TLS channel; it consists entirely of contracts and static front-end code, which you can’t “send” things to. so what do you do?
essentially the only thing you can do is to obtain a public key from the front-end—which you can certifiably attest is controlled by the dapp—encrypt under that key, and then post the ciphertext somewhere the dapp can see it, say, on-chain. the arguably more interesting case is where a user wants to encrypt to another user. here, you can imagine a sort of “on-chain encrypted email” Dapp. here, the encryption doesn’t go to the dapp, but from one user to another. the dapp would retrieve the recipient’s public key from a registry (something like ENS), obtain the message, facilitate its encryption by user to the recipient key, and then post the ciphertext for the user somewhere the recipient can find it (say, an inbox contract).



 kdenhartog:

Sure, the user wishes to send a confidential transaction to the mixer dApp in order to submit a private transaction where the only party they’re willing to reveal the amount to is the dApp.


in this example, the mixer would require a non-static backend server. in this case, you probably don’t need this EIP; you can just use TLS.
let me know if this clarifies things; apologies for the misunderstandings.

Author: kdenhartog
Date: 2022-11-07T22:12:58.571Z

To be honest, i still don’t see the problem. it’s easy to securely associate a public key to your Ethereum account:

if you’re an EOA, post it as an entry in some contract, exactly like how ENS does.
if you’re a contract, just expose a public pure function returning the key.


Where is this defined in the EIP? Sure, there’s numerous ways to do this but our wallet team can’t  implement against any of this as none of this is defined.

i’m sorry, but this doesn’t compute. you would call some “get public key” function exposed by the dapp. the dapp would deliver the public key. you would locally encrypt under that key. you would then send the ciphertext to the dapp. what’s wrong with this?
actually this is a much less difficult case, since the public key depends only on the dapp, not the user. so it could even be hardcoded in the static front-end. if you wanted to authenticate the public key, you would use the technique in the post above.

If the dApp is a SPA running locally in my browser with only static front end code, how is the private key loaded in? Also, why do I need to encrypt a message to a dApp in that case? Who’s the adversarially actor I’m trying to maintain confidentiality from in that case? This architecture you’ve described with a completely stateless front end and a public backend (the ETH blockchain) doesn’t need confidentiality via encryption. I guess this is why I’m confused is I never saw this as a usecase where this was necessary.

and then post the ciphertext somewhere the dapp can see it, say, on-chain

If the dApp is not ran in a server and is ran entirely via smart contracts for backend logic and static code for front end logic where is the dApp’s private key kept?

the arguably more interesting case is where a user wants to encrypt to another user . here, you can imagine a sort of “on-chain encrypted email” Dapp.

I’ve eliminated this use case from practicality because of the inherent cost of gas fees. storing messages on chain is impractical. Assuming only SMS style messages were used with a 160 character limit and 4.1 trillion messages sent (numbers pulled from this link MMS vs SMS - Difference and Comparison | Diffen) this equates to a max bound of 656 terabytes of storage required (per year) if we were to entirely replace SMS with this. Now, I can presume the counter argument to this would be “we don’t want to replace SMS it would just be used for limited use cases of X,Y,Z”. So let’s downscale this to say that 1 billion messages are sent per year at 160 character limit. Practically speaking this means 1/8th of the world gets to send only 1 message per year of 160 characters. That still comes out to 160GB of storage (per year) and doesn’t even account for the additional demand for the mempool. Putting all this together just makes this an infeasible architecture in my eyes. I’d rather handle this off chain (there’s additional security/privacy benefits to this I’ve highlighted above) and make the chain a mechanism for discovery on how to find another persons off chain inbox server.
Hopefully, this illuminates my perspective a bit more clearly on this. This is why I was trying to get us to detail out the use cases more clearly above. I knew we’d end up talking past each other if we didn’t align on that first. This is just inherently how standards conversations go by the very nature of the way standards get built from what I’ve learned. If I knew a faster, more fluid way to do this I’d certainly jump to use it, but I don’t have one so I resort to the method I’ve found to build consensus and ship running code.

Author: firnprotocol
Date: 2022-11-07T23:32:59.647Z

I have to ask you to please stop replying in this thread. I find your input to be unconstructive, and best suited for a different setting. Thank you.

Author: firnprotocol
Date: 2022-11-07T23:46:41.811Z

hello @ronaldmannak, apologies, I missed your message when you first posted it. thanks for your contribution and glad to have you on board.



 ronaldmannak:

Have you considered using the GPG model where the message itself is encrypted with a one-time symmetrical session key, and the session key itself is encrypted with the recipient’s public key? This would scale for multiple recipients.


actually, this is an almost exact description of how ECIES works, and is actually the only way to use asymmetric encryption for long messages. indeed, “true” asymmetric encryption only works for short messages—say, on the order of 32 bytes. everything longer than that, you’ll use the “hybrid” style of encryption you described above, which is what both GPG and ECIES use.



 ronaldmannak:

I’d suggest to use proven models, unless there is a good reason not to (there might be one that I missed, feel free to correct me).


the model we propose is proven (and in fact this is true regardless of whether you use the HKDF to go from signing key ⟶ decryption key or not). the only model which is not proven secure is that of EIP-1024, in which the same secret key is used for both signing on the secp curve and simultaneously for decryption on curve25519.

Author: Weiji
Date: 2022-11-08T03:21:36.852Z

I’d like to mention the " Deterministic Encryption and Storage via Snap/IPFS" project as one of the use cases that this EIP could apply to. It is the ETH Lisbon hackathon winner #1.
It is not messaging. Not sure if it falls into “dApp → user” category or “dApp → dApp”: the private key should be controlled by the same user all the time. In this case, there is no server behind the dApp.

Author: kdenhartog
Date: 2022-11-08T09:42:43.330Z

Weiji:

I’d like to mention the " Deterministic Encryption and Storage via Snap/IPFS " project as one of the use cases that this EIP could apply to. It is the ETH Lisbon hackathon winner #1 .
It is not messaging. Not sure if it falls into “dApp → user” category or “dApp → dApp”: the private key should be controlled by the same user all the time. In this case, there is no server behind the dApp.


Ahh fascinating! Thank you for this link. It appears to be achieving something quite useful which is like an encrypted personal data store pattern. Nice work @skgbafa! This is effectively what I was trying to describe in this comment but this achieves it in a way that requires less wallet code, so I’m in favor of this pattern. We’ll probably want to standardize a few more things to make it a bit more interoperable, but I’m willing to help out on that. Others want to leave that out of scope for this EIP so probably worth defining it separately and building on this one separately.
That helps me answer a ton of the questions I’ve been trying to understand albeit only for the “user to themselves” use case (maybe  “user → user” category although I think people mean different people normally here). Up until this point, I’ve not found any code for a dApp that was using these APIs (including in firn’s dApp and tornado cash - I can see from the UX flow that it is being used in tornado.cash but can’t find the code on GH) so I was genuinely confused how this was achieving anything.
I’m still a bit confused about “user → dApp” category or “dApp → dApp” categories particularly because  I think it depends on the deployment model of the dApp as well so they can decrypt the messages they’re receiving. Anyone got a code example of how that might work? Right now it seems like the way the code might work would be:
fetch(url, {
    method: 'POST',
    mode: 'cors', 
    cache: 'no-cache', 
    credentials: 'same-origin', 
    headers: {
      'Content-Type': 'application/json'
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: "my message to the dApp" 
  });
...

// time to decrypt response

window.ethereum.request({
  method: 'eth_decrypt',
  params: [{
    version: 'secp256k1-sha512kdf-aes256cbc-hmacsha256',
    ciphertext
  }, myEthAccount],
})

window.ethereum.request({
  method: 'eth_getEncryptionPublicKey',
  params: [myEthAccount],
})

window.ethereum.request({
  method: 'eth_decrypt',
  params: [{
    version: 'secp256k1-sha512kdf-aes256cbc-hmacsha256',
    ciphertext
  }, myEthAccount],
})

If we did it the opposite way where it was the dApp that initiated the message I believe the order here would just be flipped around. If we wanted to replace that fetch call with an encrypted message then we’d need to define how to retrieve the dApp public key and how to post the message to it. If we don’t want to define this, then I’m back to my original point of why send messages to the dApp unencrypted by receive messages from the dApp encrypted?

Author: firnprotocol
Date: 2022-11-08T13:47:51.311Z

Weiji:

as one of the use cases that this EIP could apply to.


it looks like they actually invoke our EIP  (presumably as a mock at this stage.) plus additional logic for storage and retrieval. nice find.

Author: cjpais
Date: 2022-11-08T15:24:06.358Z

This is awesome work. It lends itself nicely to extension as well. One such way would be to use a contract as a public key registry. This effectively enables decentralized private file sharing. I was doing previous work on this here, with the former EIP-1024.
I think this EIP has the potential to open up a bunch of use cases based on work like this. I think the “person → person” or “person → people” categories are easily opened up as well. Again using an extension to this methodology through a contract. The same code shared above has a methodology to share a encrypted file to a group of people. I think the use case for people to communicate over encrypted channels itself is very compelling and important. Not to mention in the current form it fits nicely into permissionless building.

Author: Weiji
Date: 2022-11-09T02:21:11.999Z

For the key discovery or public key registry, I think it is time to summarize:

Smart Contracts could expose a function to return a public key;
EOA: encrypt to the “direct” public key, that is, the one corresponding to the address. Usually this could be recovered from past signatures. We need a utility for this purpose.
EOA: encrypt to the “derived” public key as currently specified. We may need a registry, be it smart contract or ENS or something else. Fee may incur.

There are also security implications to the choice between “direct” or “derived” public key, mostly about key management.
I’d like to link this to my other proposal about private key encapsulation: that is, if we rely on this EIP for file encryption or end2end encrypted messaging, we don’t want to enter our seed to a messaging app. We could safely transport the needed private key (“direct” or derived) to the app without endangering the entire seed.

Author: firnprotocol
Date: 2022-11-09T16:52:54.867Z

hi @Weiji.



 Weiji:

if we rely on this EIP for file encryption or end2end encrypted messaging, we don’t want to enter our seed to a messaging app.


let’s back up—i don’t see why there would ever be a need to input your seed into a messaging app?
let’s take an example. in the case of e2e messaging, it’d work the following way. the “dapp”—which, i emphasize, is just some static javascript loaded into the browser—will perform the following steps to send a message:

it would acquire the recipient’s public key, either by doing an ECDSA recovery on an existing signature (“direct”) or retrieving it from a registry (“derived”).
it would solicit the desired plaintext message from the user, through some kind of input form.
it would run some local javascript code to encrypt this plaintext to the desired recipient’s key.
it would prompt the user to post this ciphertext on-chain, and to pay the gas for doing that.

to receive / decrypt a message, the dapp would do as follows:

it would retrieve the relevant ciphertext(s) from an on-chain source, e.g., the user’s “inbox” contract.
the (static) dapp code would issue an eth_decrypt request to the user’s wallet, with the ciphertext as argument. the user will be prompted to approve the decryption.
the plaintext will now be displayed by the dapp web interface.

there is never a need to expose the seed or any private material whatsoever to the dapp, or to any remote server.
hopefully this helps clarify things? thanks for your thoughts.

Author: Weiji
Date: 2022-11-10T02:16:04.549Z

firnprotocol:

it the (static) dapp code would issue an eth_decrypt request to the user’s wallet, with the ciphertext as argument. the user will be prompted to approve the decryption.


Consider if the user is keeping his or her seed or private keys in a hardware wallet, yet the dapp runs in a mobile device or browser extension for convenience. If we rely on the hardware wallet to decrypt, then literally user will have to approve the decryption for every incoming message. And if he or she leaves the hardware at home, there is no way to decrypt messages for the day.

Author: firnprotocol
Date: 2022-11-10T13:01:05.720Z

so yes, this is true. but usually we accept and even expect user approval for each sensitive action. but if you wanted to bypass this, you could use the following flow instead.
to log in / create an account:

the browser client generates a fresh random secret key for the user, say nk. it locally computes the corresponding public key, say mk.
the browser posts mk in a registry known to the dapp, so that other users can discover the key mk.
the browser separately issues an eth_getEncryptionPublicKey  request to the wallet, which the user is prompted for; it receives the resulting stable public encryption key, say ek.
it encrypts the secret nk to ek, and posts the resulting ciphertext to the blockchain somewhere belonging to the user, for recovery later.
to log back in later, the browser retrieves this ciphertext, and issues an eth_decrypt request on it to the user. after the user accepts the request, the browser obtains nk, which it can use to decrypt every message.

to send a message:

after inputting the desired recipient into the dapp, the dapp retrieves the dapp-specific public key mk corresponding to this receipient.
the dapp solicits the plaintext from the user, encrypts it to mk, and posts the ciphertext on-chain.

to receive a message:

once you’re logged in (see above) the browser has access to nk, using which it can automatically retrieve / decrypt every message.

in this case, you do provide the secret nk to the dapp. but this secret is completely unconnected to your seed phrase hierarchy, and is not used for any purpose other than the dapp. moreover, there is no need for TLS / Diffie–Hellman / key encapsulation / etc., since the dapp runs locally on the same machine as the wallet—nk is never transmitted to any external machine. thoughts?

Author: Weiji
Date: 2022-11-11T03:01:48.637Z

Hi @firnprotocol  Key management is a complicated issue and not a pure technical decision. Sometimes it involves uers. Let’s focus on this EIP here and redirect KEM related discussion to the other thread. Do you mind if quote your comments there?

Author: firnprotocol
Date: 2022-11-11T03:13:16.137Z

absolutely, go ahead.

Author: Weiji
Date: 2022-11-28T04:05:31.495Z

Weiji:

EOA: encrypt to the “direct” public key, that is, the one corresponding to the address. Usually this could be recovered from past signatures. We need a utility for this purpose.


@firnprotocol What do you think about this? Do you see a need to include it in 5630? It’d simplify public key discovery issues in some applications/scenarios.

Author: firnprotocol
Date: 2022-11-28T04:24:06.838Z

right, yes, i think it’s a great idea. i just think we need to first decide (i.e., as a community) whether we want to include the HKDF or not (i.e., whether we do 2 or 3 in the message you’re quoting from).

benefit of using HKDF: slightly stronger security (i.e., security argument doesn’t rely on the GGM).
benefit of not using HKDF: allow key discovery by performing ecrecover on existing signatures.

which benefit is more “worth it” first needs to be decided by us, on technical grounds.



 Weiji:

Do you see a need to include it in 5630?


i’m not quite sure what you mean. certainly the decision of whether to use the HKDF or not needs to be made in this EIP.
on the other hand—regardless whether or not we include the HKDF—my sense is that the mechanism for public key discovery is out-of-scope for this EIP. if we don’t use the HKDF, then there’s not much of a problem to solve, since it’s essentially trivial (at least for addresses which have signed before). If we do use the HKDF, then it becomes much less trivial, and we’d need something analogous to ENS. either way though, i think that would be the territory of a separate EIP. thoughts?

Author: Weiji
Date: 2022-11-28T06:24:53.553Z

I do think it is important for an EIP to be considered for its infrastructure dependencies. Public key discovery is non-trivial and subtle to manage right. And when such is lack we need to jump start this EIP.
Can we support both? Then users and community could choose either or both as they see fit. I do see applications without HKDF, when people can send each other encrypted messages as long as the peer had signed any txn/msgs before.

Author: firnprotocol
Date: 2022-11-28T13:14:04.455Z

hmm. perhaps we could support both, and use separate version tags for each. e.g., secp256k1-sha512kdf-aes256cbc-hmacsha256 and secp256k1-sha512kdf-aes256cbc-hmacsha256-nokdf. (these are getting fairly long…). i’d personally prefer that we pick one, just for simplicity, but maybe we can let community members weigh on on this.



 Weiji:

Public key discovery is non-trivial and subtle to manage right. And when such is lack we need to jump start this EIP.


while i agree with you that it’s important and subtle, I think I have to respectfully disagree that it should be included in this EIP. i would be happy to help & advise on a separate EIP treating the issue of public key distribution / advertising.

Author: Weiji
Date: 2022-11-28T16:56:58.549Z

firnprotocol:

secp256k1-sha512kdf-aes256cbc-hmacsha256-nokdf


Maybe simply secp256k1-aes256cbc-hmacsha256



 firnprotocol:

while i agree with you that it’s important and subtle, I think I have to respectfully disagree that it should be included in this EIP.


This has been going around a few times. I totally respect your decision here. Let’s close it here.

Author: Weiji
Date: 2022-11-30T11:21:08.250Z

Before I submit a new pull request, let’s do a little bit polling here.
Do you think we need to add a new version secp256k1-aes256cbc-hmacsha256?




Yes
No




0
voters




The purpose of this new version is that applications could choose to encrypt message to the original public key or one derived with sha512kdf. Please checkout earlier discussion for context. Thanks.

Author: firnprotocol
Date: 2022-12-01T02:23:48.950Z

in the interest of clarifying the poll…
do you intend that a “yes” vote entails that we do both? or that we only do the version without the KDF? if possible, please clarify that, and then i will vote.



 Weiji:

Maybe simply secp256k1-aes256cbc-hmacsha256


btw, to clarify, the sha512kdf in the original naming suggestion refers to the KDF done within ECIES (to conver the DDH secret into an AES + MAC secret key). it has nothing to do with the KDF relating sk → dk, which is separate. just so you know.

Author: Weiji
Date: 2022-12-01T04:22:32.590Z

firnprotocol:

do you intend that a “yes” vote entails that we do both? or that we only do the version without the KDF? if possible, please clarify that, and then i will vote.


both, sorry for the confusion

Author: Weiji
Date: 2022-12-01T04:39:59.151Z

firnprotocol:

btw, to clarify, the sha512kdf in the original naming suggestion refers to the KDF done within ECIES (to conver the DDH secret into an AES + MAC secret key). it has nothing to do with the KDF relating sk → dk, which is separate. just so you know.


Thanks for the clarification. I assumed the wrong way. Then maybe the suggested additional version could be: secp256k1-none-sha512kdf-aes256cbc-hmacsha256, with none following immediately after secp256k1 to indicate that no KDF is done to derive dk from sk. The original version could also be changed to sth like secp256k1-X963-sha512kdf-aes256cbc-hmacsha256. I’d also suggest that we trim the trailing cbc-hmacsha256 as there is no other option here. How do you think? @firnprotocol

Author: firnprotocol
Date: 2022-12-01T13:45:53.947Z

Weiji:

I’d also suggest that we trim the trailing cbc-hmacsha256 as there is no other option here. How do you think?


sure, I am happy to do this. the name is too long. good idea.



 Weiji:

both, sorry for the confusion


my opinion is that for simplicity, we should choose one approach for this EIP. i am not sure yet which it should be, but I think I have a preference against doing both. so I will have to vote “no” in the poll I think.
actually, personally, if I had to choose, I’d prefer not doing the KDF (as you suggested). it’s a question of whether the community will also agree—the security is (very) slightly weaker, since the best known proofs require the GGM.

Author: Weiji
Date: 2022-12-01T15:59:57.548Z

@firnprotocol how about a new poll with 3 options, that is: both, with-kdf, without?

Author: firnprotocol
Date: 2022-12-01T16:02:43.833Z

sure. (i’d prefer we exclude the option “both”, but let’s let the poll decide that ) thanks for putting this together.

Author: Weiji
Date: 2022-12-01T16:16:52.907Z

How do you think we should proceed? Please select one:




support only the original verision secp256k1(-X963)-sha512kdf-aes256(cbc-hmacsha256), a new key pair for encryption/decryption is derived from sk

support only the new verision secp256k1(-none)-sha512kdf-aes(256cbc-hmacsha256), just use sk and its corresponding public key
support both versions




0
voters

Author: Weiji
Date: 2022-12-06T07:52:42.152Z

Besides the vote, I’d like to bring up another use issue here. That is, after considering how the APIs will be use by various application, I came to realize that maybe some encrypted message will be too large to be decrypted inside a hardware wallet, especially if the wallet is air-gaped and requires optical scanning to exchange data. @Lixin @Aaron
Say, if this EIP becomes popular some day and people use it to encrypt large messages, for example, in several MBs, decrypting the message within a hardware wallet may not be desirable.
So I am proposing that we add another API to recover the symmetric key (and IV) instead of decrypting the whole message:
request({
  method: 'eth_recoverSymKey',
  params: [encryptionHeader, account],
})

We do not need to pass in the entire cipher text. Instead, we only need sender’s ephemeral public key. encryptionHeader is much similar to encryptedMessage in that it contains version and senderEphemeralPublicKey:
{
  version: 'secp256k1-sha512kdf-aes256cbc-hmacsha256',
  senderEphemeralPublicKey: '0x03ab54...',
}


Then the wallet managing the private key could derive the shared secret, sha512-kdf the shared secret to derive AES-256 key and IV, which it returns to caller, the caller may decrypt cipher text outside of the wallet. @firnprotocol how do you think?
Edit: by preventing arbitrary message from being decrypted and written to memory inside a wallet managing users’ seed / private keys, this new request also protects wallets from potential buffer overflow attack etc.

Author: TJKoury
Date: 2022-12-08T15:11:17.966Z

There’s a solution that solves this problem and is a more directive way of providing the encryption public key, or even changing it later if the original is compromised, separating the signing (identity) keypair from the encryption keypair.
The EIP should be updated to include requiring an encoded message that is published in the input/data field of a transaction, which would be a prefixed text input to include the public key encoded as base64 to save space, such as:
EIP5630::BDewu3qCiNOO1JpSS13JjP8+tcqCTJ+dwN/bPZzWAPKZpheZErdFHAmJbECY7KfOay5YMwZyeV6EfE1q9E4CQjA=
I know everyone wants the public key to be “discoverable” from the Ether address, however you can only recover it if there’s a signed transaction.  Might as well publish the public key in that transaction in a way that takes minimal gas and allows swapping keys.
If you agree @firnprotocol I can add a section to the EIP.

Author: vbuterin
Date: 2022-12-08T15:36:24.159Z

How would this work together with smart contract wallets?
IMO given that smart contract wallets are finally picking up, it’s important for something like this to have a path for encrypting to smart contract wallets.
The most natural approach that I can see is to have an EIP-1271 equivalent for signing, something like:
encryptToAccount(bytes memory plainText) public view returns (bytes cipherText)
This would be fully generic and support any algorithm that someone might want, including threshold encryption, post-quantum algorithms, etc.
Have people here thought about this?

Author: firnprotocol
Date: 2022-12-08T15:55:07.799Z

intriguing.
it seems plausible that an additional parameter—containing randomness/entropy—would need to be supplied to this method, no? since (public-key) encryption requires ingesting randomness.
a further note: this approach would essentially allow contracts to choose arbitrary encryption mechanisms—which, in general, may not be compatible with eth_decrypt (i.e., the RPC call we’re proposing here). this could be a bit confusing. but i guess that is a caveat emptor situation for the writer of the contract.
in general, i completely support this! very much appreciate your thoughts.

Author: vbuterin
Date: 2022-12-08T16:02:11.581Z

Ah yes, adding an entropy parameter would definitely be a good idea.
As for eth_decrypt, that would be up to the javascript part of smart contract wallets to implement correctly, right? So eg. Soul Wallet would give everyone ERC4337 accounts by default, and their javascript interface would implement eth_decrypt their own way based on how they know that the encryption algorithms they choose work.

Author: firnprotocol
Date: 2022-12-08T16:18:05.112Z

very interesting.
the issue is that, above, we have prescribed / suggested a specific way for eth_decrypt to operate (i.e., which algorithm / variant of ECIES etc.).
maybe what we need to do is actually remove the prescription—and let wallets do it however they want. there could be a “standard” / default choice, but also arbitrary choices, made on a per-wallet basis.

Author: TJKoury
Date: 2022-12-08T16:25:24.913Z

@vbuterin I’ve given this a fair bit of thought for my project.  Most immediate issue for me: have a revokable trust interface in the smart contract with assignable trust levels (like is used in PGP). That way you can set up trust rules (at least x of n keys trust this key as of block y).
For implementing something like a smart-wallet that does encryption (the results being unshareable/unknowable), having a queryable, stateful “reputation score” is essential.

Author: Weiji
Date: 2022-12-09T04:23:19.562Z

Let’s pull back the discussion a little bit. Unlike on-chain signature verification, both encryption and decryption must happen off-chain because both the key and the plaintext must be kept confidential.
That being said, we had considered smart contract uses before, which is to provide a function to return the public key for encryption. If multiple curves are supported or consider post-quantum security, return also the supported and/or preferred version. It could also return multiple choices.



 Weiji:

Smart Contracts could expose a function to return a public key;


We could make such an API part of either 5630 or 4337. I think that should address smart contract / ERC-4337.

Author: TJKoury
Date: 2022-12-09T06:22:27.385Z

Would the smart contract accept an Ethereum address as an argument and then return a public key assigned to that address?  If so, I imagine the contract would act like Active Directory.  In your model then, is there a method that allows a user update / revoke a public key?  Apologies if I’m misunderstanding your point.

Author: Weiji
Date: 2022-12-09T06:35:37.594Z

I don’t see the need for an argument. And yes to the second question, the contract owner should be able to update the public key in any way that she or he sees fit. Decryption will be carried out off-chain. Note that I am talking about a ERC-4337 style contract that is owned by individual entity, not some DAO style that could be “owned” collectively.

Author: TJKoury
Date: 2022-12-09T16:30:09.974Z

Sounds reasonable, and of course all encryption would occur off-chain, I don’t think anyone is arguing otherwise, or at all.
The feature I’m interested in is a formalized SC EIP that can enable a smart contract to act as a trust oracle, where users can revokably signal their trust of a particular contract / address.  To me this is necessary since the operation is done off-chain, and the results are private.  If someone has reason to believe a decryption key is compromised, they should be able to signal it, like an Ethereum analog for OCSP.

Author: TJKoury
Date: 2022-12-10T12:40:03.120Z

This is separate from my suggestion above about publishing the public key in the data field of a transaction, which I still think is a reasonable approach per my comments.

Author: firnprotocol
Date: 2022-12-29T16:45:03.031Z

hi all. happy to report that i’ve made some updates to the EIP. the new material includes:

a specification of how a contract should advertise—to the world—how encryptions to it should be constructed; this is important for account abstraction (cc. @vbuterin).
removed the HKDF between sk → dk; this allows on-chain public-key discovery essentially for free (cc. @Weiji).
added material on why twist attacks are not applicable to this EIP (cc. @rekmarks).

hugely appreciate the community effort on this! please let me know any thoughts and comments.

Author: firnprotocol
Date: 2022-12-29T16:47:12.229Z

btw, i thought of a cool idea. what if you want to encrypt to someone—and also be anonymous in the process; i.e., the recipient shouldn’t know who the sender was (kind of like an anonymous drop-box)?
you can do this with Firn—i.e., you just send the ciphertext to the recipient as data, in the usual way, except make the transaction as a private & gasless withdrawal from Firn. viola.

Author: TJKoury
Date: 2022-12-30T00:16:26.905Z

Thoughts on my suggestion above, sending a transaction that establishes the relationship between a public key and an address?  Can be useful to associate multiple keys with an address, revoke a key, etc.

Author: firnprotocol
Date: 2022-12-30T01:26:59.302Z

not sure i fully understand—in the quote



 TJKoury:

requiring an encoded message that is published in the input/data field of a transaction


it sounds like you’re suggesting that the structure of the basic transaction object be changed, i.e., a field added for public key? i assume this isn’t what you mean, since it’d require changing the base ethereum protocol, which seems off the table. do you mean that a specific transaction (i.e., to some given contract) be published, which contains this info? this could definitely be done, though might not be necessary—see below.
indeed, the problem of public key discovery seems essentially solved now that we’ve removed the HKDF, since you can always grab someone’s key from a transaction they’ve signed.



 TJKoury:

I know everyone wants the public key to be “discoverable” from the Ether address, however you can only recover it if there’s a signed transaction. Might as well publish the public key in that transaction in a way that takes minimal gas and allows swapping keys.


not sure I follow—recovering someone’s key doesn’t require gas; you only need read-access to a node. let me know your thoughts.

Author: Weiji
Date: 2022-12-30T02:18:30.176Z

Excellent! Good to see that we are moving on.
BTW, what do you think about the situation that cipher text might become very long and too long for some wallet to handle? My suggestion is for the wallet to only derive the symmetric key (and IV etc) necessary to decrypt the cipher.



 Weiji:

request({
  method: 'eth_recoverSymKey',
  params: [encryptionHeader, account],
})

Author: TJKoury
Date: 2022-12-30T03:02:43.092Z

I mean writing to the data field.  This could be a contract call or simply raw hex with an identifier followed by the public key, I’m open to suggestions.
Also, not implying that reading a transaction requires gas, simply stating that among the many ways to transmit metadata about a public key, this is probably the cheapest way to do it.
Thinking about this more since our last, the answer might be a new smart contract type that manages decentralized PKI.  What you have now is succinct and enforces separation of concerns.

Author: firnprotocol
Date: 2022-12-30T03:12:00.153Z

yes @Weiji, this is an intriguing suggestion. thank you. sorry for not getting to this earlier.



 Weiji:

I came to realize that maybe some encrypted message will be too large to be decrypted inside a hardware wallet, especially if the wallet is air-gaped and requires optical scanning to exchange data.





 Weiji:

this new request also protects wallets from potential buffer overflow attack etc.


i think in the vast majority of cases, the caller and callee of eth_decrypt will be on the same machine, or separated by a USB-C in the case of standard hardware wallets. in this kind of case, bandwidth / communication throughput will not be not a problem. regarding buffer overflows, i am simply not versed in enough in how hardware wallets work to know whether this is a problem. maybe we can find some experts to weigh in. likewise, as far as optical scanning, this is very new to me. it could be a problem, but seems like an unusual case.
overall though, i like this idea, since it really only gives us more flexibility. in particular, it allows the decryptor (and of course also the encryptor) to choose an arbitrary variant of ECIES, without re-implementing or changing what’s baked into the hardware wallet (this is very slow and difficult to do). instead, the hardware wallet only does the sensitive operation, and the rest is handled outside.
the only downside i see is that it makes it more complicated for implementers. it also is not compatible with the encryptTo smart contract method newly proposed, since that method requires the entire encryption to be computed, not just the ECDH.
so at this point it seems to me like a tradeoff between simplicity, on the one hand, and flexibility + bandwidth improvement on the other. i am still not sure where i stand exactly. we could also do both! but i also prefer to keep the EIP as simple as possible. let me think about this for a bit. thanks again for the suggestion.

Author: Pandapip1
Date: 2023-01-04T12:46:32.764Z

I am fully in support of the general case that doesn’t hardcode the ECIES variant, just because I prefer flexibility wherever it can be offered. I nonetheless accept that this is my opinion and that others’ may differ.
Note that if you choose this path, you should include validation of the elliptic curve in the spec, as there are attacks possible if it is not performed.

Author: firnprotocol
Date: 2023-01-05T01:48:32.825Z

good to know; thanks for your feedback. I will let this bake for some more time and then make a decision. (but leaning towards agreeing with you and @Weiji right now.)



 Pandapip1:

if you choose this path, you should include validation of the elliptic curve in the spec


right; i expect that i will use compressed representation in any case, so there’s not as much to validate. but indeed, i will definitely include validation that the 33-byte datum passed in actually represents a valid compressed point (essentially, you just need to verify that the first byte is 0x02 or 0x03, and that the remaining 32 bytes yield a quadratic residue under the RHS of the Weierstrass equation). edit but note that this validation is essentially just a sanity check; wrong curve / twist attacks are not possible in the compressed setting. indeed, if the (compressed) point is not valid, then it becomes literally nonsensical, and doesn’t make sense to proceed; it’s not something that could silently go undetected and lead to an attack.

Author: firnprotocol
Date: 2023-01-05T18:33:45.733Z

i have gone ahead and made the update to the EIP. thus, now, the wallet will only do ECDH, and the rest of ECIES is chosen / carried out by the application-level implementer. (this is actually much closer to how GPG does it, btw.)
big thanks to @Weiji for the idea (maybe we should add you as an author?  ) i stipulate that all checks during deserialization MUST be carried out by the wallet; cc. @Pandapip1.

Author: Weiji
Date: 2023-01-06T01:00:49.490Z

firnprotocol:

big thanks to @Weiji for the idea (maybe we should add you as an author?


Oh that is very nice and sweet. Please do, use Weiji Guo (@weijiguo). Or do I need to open a PR?

Author: firnprotocol
Date: 2023-01-08T20:09:29.420Z

done. welcome friend!

Author: firnprotocol
Date: 2023-03-22T00:35:25.686Z

intereting: Ronin Bridge Exploiter communicating with Euler Finance Exploiter using ECIES encryption on-chain. see https://twitter.com/TheDEFIac/status/1638243255941840896/photo/1
this is what we are trying to standardize. edit no endorsement of either party.

Author: Madhav
Date: 2023-03-23T07:29:14.426Z

hey love the proposal could you share a link to poc or the pull request unable to find it.

Author: firnprotocol
Date: 2023-03-23T14:38:23.216Z

hi. keep in mind this is an EIP; it is only a spec; it is not a code change or a PR. it is up to wallet maintainers to implement it. with that said, there was previously a reference implementation, but it has become out-of-date (see above changes to EIP) and was removed. all of the basic functionality described in this EIP can be implemented in a few lines of code using node’s crypto library.

Author: lightsing
Date: 2023-04-10T14:36:21.252Z

Over the past few months, I have conducted thorough research on encryption and decryption using Ethereum key pairs. My findings suggest that Hybrid Public Key Encryption (HPKE) is a more suitable solution for this purpose when compared to Elliptic Curve Integrated Encryption Scheme (ECIES), which is now considered outdated. I recommend adopting HPKE, as explained in this Cloudflare blog post.
Although the Internet Engineering Task Force (IETF) has not incorporated the secp256k1 curve into the HPKE cipher suite, the overall system is well-constructed and robust. For example, the hpke-js library effectively implements DHKEM (secp256k1, HKDF-SHA256), demonstrating the strength and adaptability of HPKE.

Author: yisiliu
Date: 2023-04-28T10:11:00.326Z

I was planning to create a similar EIP but not limited to encryption and decryption functionalities two years ago when hundreds of millions of dollars were lost in De-Fi hacks. My intention is to create an on-chain announcement system, that, any party can send a public/encrypted message to any wallet address since wallet is the most accessible and direct way to contact with users on any blockchain, especially when an attack is ongoing and projects need to notify their users to move their assets directly through a most native way, wallet, instead of through an email or a shout-out on twitter. We at Mask Network have been using secp256k1 to enable users to encrypt their messages and posts on social medias since 2019 and I believe we could definitely contribute with our past experience handling both encrypted DM and group messages. However, what I’d like to propose in addition to this is that we need to turn this into an announcement scheme with a standard message payload spec, including fields like sender, ephemeral_pub, signed_ephemeral_pub, hmac, nonce, message, etc. This will help standardize the effort any wallet need to take to integrate this kind of on-chain messages.

Author: firnprotocol
Date: 2023-04-28T11:53:23.250Z

hi, thanks for your contribution.



 yisiliu:

standard message payload spec, including fields like sender, ephemeral_pub, signed_ephemeral_pub, hmac, nonce, message


not sure i fully understand. keep in mind that our ciphertext already includes ephemeral_pub and hmac, by definition of ECIES. as for message, that doesn’t make sense, since it’s encrypted. signed_ephemeral_pub and nonce i don’t understand.
in any case, i am definitely open to spec’ing out more details around how messages should be sent onchain. in my opinion, the most urgently needed thing is some kind of onchain inbox infrastructure, some kind of smart contract to store received messages.
before changing the spec though, i think our first task should be to gain momentum and buy-in from wallet devs. that is our most urgent goal at this stage of the EIP i think, since we risk becoming stagnant if we don’t kick off some momentum among wallets.

Author: yisiliu
Date: 2023-04-28T12:26:38.447Z

signed_ephemeral_pub is how you verify the relationship between this ephemeral key and the message sender and nonce is just a factor to prove freshness of the message in a security perspective. Sorry about the confusion here since I didn’t want to include too much into the reply.
However, I don’t actually think these messages need to be stored in a smart contract. Instead, a standardized payload format is needed to be defined and we can easily include them in the data field of each transaction to minimize the gas cost. This could also make wallet implementation easier since all they need to do is to monitor one’s wallet(which is already being deployed) and decode the message for users to decrypt with their private key. Not sure about your opinion on this.

Author: firnprotocol
Date: 2023-04-28T12:59:07.608Z

hmm. if we don’t use a smart contract, we’d need some sort of addressing scheme in order to make the messages receivable.



 yisiliu:

signed_ephemeral_pub is how you verify the relationship between this ephemeral key and the message sender


as for this—i just assumed that authenticity would come from the sender posting the ciphertext to the onchain inbox using his Ethereum account. so authenticity would come for free. but yes, barring this, you could sign the ephemeral pubkey (or the whole thing).



 yisiliu:

Instead, a standardized payload format is needed to be defined


right, if we don’t use smart contracts, then yes—though again, we have the problem of delivering messages to their intended recipient. how do you plan to address that?
either way, as mentioned above, i think we need to synchronize with wallet devs to get them onboard, before we start making further design decisions.

Author: MantisClone
Date: 2023-04-30T12:36:15.311Z

I believe that Request Network is a potential use case for EIP-5630.
Details: I’m a dApp developer at Request Network. Request Network stores encrypted payment requests (often referred to as “Invoices”) in IPFS using the “hybrid” style of encryption mentioned in previous comments. The request data is encrypted using a one-time-use symmetric key and then copies of the symmetric key are encrypted using asymmetric keys, one for each stakeholder of the request. Request Network provides a client library that can be run in the dApp frontend. We’re looking into using EIP-1024 but would prefer to use EIP-5630 once an implementation exists.

Author: firnprotocol
Date: 2023-04-30T13:02:15.222Z

hi. sounds like a great use-case. thanks for reaching out.



 MantisClone:

We’re looking into using EIP-1024 but would prefer to use EIP-5630.


keep in mind, EIP-1024 (really, PR #1024, since it was never merged) has been implemented only by MetaMask, and is deprecated. so i don’t think it would be wise to deploy a production app based on it.
we are planning to begin a bit of wallet outreach soon. any help on this front would also be appreciated, if you have connections with wallets.



 MantisClone:

once an implementation exists


though there’s no public ref implementation right now, it’s almost trivial to implement using Node’s crypto library. if you want help with this i can.

Author: manizzle
Date: 2023-05-22T06:10:16.151Z

I working with a smaller wallet dev on this proposal. PM me for more details and for collaboration. (https://settle0x.com/)

Author: Oli-art
Date: 2023-06-18T03:21:09.778Z

Hi @yisiliu @firnprotocol, I’m drafting EIP-7017, a notifications protocol that standardizes one-to-one and one-to-many messages. Naturally, one-to-one messages must be encrypted and EIP-5630 seems like the way to go.
Receivers should not have to do any dedicated action on-chain like posting their public key on a ENS, as it would be a massive barrier for the protocol. I’m sure other usecases for this EIP feel the same way. Is it possible to get the key from a transaction signed by the receiver in the past?
If so, I would like to collaborate on an MVP to showcase both EIP-5630 and EIP-7017 so as to get wallets to implement them.

Author: firnprotocol
Date: 2023-06-18T12:43:39.214Z

Oli-art:

Receivers should not have to do any dedicated action on-chain like posting their public key on a ENS, as it would be a massive barrier for the protocol. I’m sure other usecases for this EIP feel the same way. Is it possible to get the key from a transaction signed by the receiver in the past?


yes, it is possible. this fact is made explicit in the latest version of the EIP; see the below direct quote:

On-chain public key discovery. Our proposal has an important feature whereby an encryption to some account can be constructed whenever that account has signed at least one transaction. Indeed, it is possible to recover an account’s secp256k1 public key directly from any signature on behalf of that account.




 Oli-art:

If so, I would like to collaborate on an MVP to showcase both EIP-5630 and EIP-7017 so as to get wallets to implement them.


cool, would be happy to collab.

Author: firnprotocol
Date: 2023-06-19T16:03:45.758Z

btw, upon reviewing @Oli-art’s EIP-7017, I think i can clarify its role, for the edification of this thread. cc. @friedtrout @Weiji
that EIP standardizes how the actual blockchain should be used as a distribution mechanism for messages, over and above how they actually get encrypted (that’s our job). specifically, it describes a way to pack encrypted messages into events, and signatures for these events, so that consumers can subscribe to them.
this very problem—i.e., on-chain distribution—has come up a few times in the above thread, so i am glad to see that @Oli-art has proposed a solution for it. In my view, our EIPs are very complementary, and we should put our full support behind EIP-7017.

Author: firnprotocol
Date: 2023-06-19T16:05:39.053Z

glad to hear it—let us know how we can help.

Author: firnprotocol
Date: 2023-06-19T16:08:49.389Z

yisiliu:

However, I don’t actually think these messages need to be stored in a smart contract. Instead, a standardized payload format is needed to be defined and we can easily include them in the data field of each transaction to minimize the gas cost.


btw, @yisiliu, it looks like i may have misunderstood your messages above. the idea of @Oli-art—and it seems your idea too—is to use a smart contract for delivery, but not for storage. i.e., the smart contract handles routing, mechanized using event subscriptions. but all the message info lives in calldata/event logs alone, and never in contract storage.
so my message above didn’t make sense; sorry. i agree with you that this is the right approach!

Author: jdbertron
Date: 2024-07-09T18:30:42.675Z

Can we please get an update on the status of this proposal ?  Like RequestNetwork, I’m also using the technique MantisClone spelled out to encrypt local cookies, but now that eth_getEncryptionPublicKey is deprecated, I’m not sure what to do. Even using the node crypto library, you would still need some way to encrypt using the wallet. The EIP page says it’s stagnant.

Author: firnprotocol
Date: 2024-07-10T01:23:32.450Z

@SamWilsn can you please advise on the “Stagnant” status? what is the proper way to get it out of that status? thanks in advance.
@jdbertron the main thing we need is for community members to apply pressure on wallets (e.g., MetaMask) to actually implement this… you are very welcome to raise an issue on any wallet.

Author: SamWilsn
Date: 2024-07-10T02:00:15.753Z

firnprotocol:

can you please advise on the “Stagnant” status? what is the proper way to get it out of that status? thanks in advance.


Open a pull request to change the status back to whatever it was previously.

Author: jdbertron
Date: 2024-07-10T02:22:36.475Z

Thanks. Done: MetaMask/core/issues/4509

Author: edyth933
Date: 2025-01-14T14:12:01.207Z

Which wallet providers have already implemented this?