EIP-5630: Encryption and Decryption

@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.

2 Likes

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.

3 Likes

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.

1 Like

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).

1 Like

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.

@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.

1 Like

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.

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.

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.

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.

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.

1 Like

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.

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.

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.

1 Like

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.

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

1 Like

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.

1 Like

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.

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)

  1. How would we expose to the user the encrypt API for the message flowing from the user to the dApp?
  2. 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.
  3. Do we leave message migration (even between wallets maintained by the same company such as Metamask mobile and metamask extension) out of scope?
1 Like

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.

@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

2 Likes

fascinating. i agree completely!

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

thus I think our proposals are very much complementary and glad to see you have done this :slight_smile:

(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.