Hybrid post-quantum e2ee messaging over EVM event logs

Hi all

I have been working on a predraft for a post-quantum resistant encrypted messaging over EVM event logs and I wanted to share it early for feedback, for example whether this needs a standardization at all.

ERC pre-draft

The goal is to standardize a small transport and wire format surface that independent clients can actually interoperate on, but not to standardize indexing, notifications, storage, spam control or inbox behavior. Those concerns are left to frontend applications.

Related work

First of all, this is not the first attempt in this area:

  • ERC 7627 explores secure messaging with more emphasis on onchain key registration and flexible conversation metadata.

  • ERC 7970 is probably the closest proposal in spirit, although it keeps the cryptographic behavior and wire format somewhat unspecified.

  • ERC 8180 (somewhat adjacent to ERC-3722) is also relevant, but to me it sits next to this work rather than on top of the same exact problem, since it is about authenticated messaging over blobs and decoder discovery.

My impression is that the design space still has not converged, and I think there is room for a more opinionated interoperable approach here. This post also comes from an implementation first perspective, since I have been already exploring and testing these ideas in a public SDK and a simple demo.

What I am proposing

  1. A small transport contract with methods sendMessage, initiateHandshake and respondToHandshake
  2. Correspondingly, three events for handshake initiation, handshake response and post-handshake message delivery
  3. Versioned long-term public keys for identity binding and message authentication, with session establishment and messaging using ephemeral keys
  4. Wallet-bound identity proofs that bind those keys to an EVM account
  5. Hybrid post-quantum key exchange so that recorded traffic is not vulnerable to harvest-now-decrypt-later
  6. Handshake-response tags that are not publicly linkable to the initiating handshake
  7. Ratcheted message topics that rotate across epochs rather than behaving like stable conversation identifiers

High level flow

This is the simplified lifecycle I have been experimenting with:

Alice                                                      Bob

1. Gen ephemeral X25519 key
2. Gen ML-KEM 768 keypair
3. Build wallet bound identity proof

Handshake event  ------------------------------------------>
  recipientHash selector
  sender longterm pubkeys
  initiator ephemeral X25519 + ML-KEM pubkey
  identity proof + optional pt note

                                                          4. Read handshake
                                                          5. Verify identity proof
                                                          6. Gen response tag keypair
                                                          7. Gen first ratchet keypair
                                                          8. Encapsulate to Alice ML-KEM pubkey
                                                          9. Derive hybrid response tag

HandshakeResponse event  <---------------------------------
  inResponseTo derived from classical + PQ secret material
  public response tag key
  encrypted payload carrying
    responder longterm pubkeys
    first ratchet public key
    ML-KEM ciphertext
    responder identity proof

10. Decrypt response
11. Recompute and verify inResponseTo
12. Derive the same hybrid root key
13. Initialize ratchet session

Session established

MessageSent event  ---------------------------------------->
  signed ratcheted payload on current topic

MessageSent event  <----------------------------------------
  signed ratcheted payload on current topic

Each new DH epoch rotates the topic, so past topics cannot be used to link future messages to the same conversation.

Why non-repudiation matters

Non-repudiation is an unusual property for a e2ee messaging protocol, and I think it is worth considering it more closely, as it allows for some interesting applications.

Since every delivered ciphertext is also an onchain tx, any third party can verify the block, the tx hash, the emitting contract and the account that published it. Attribution is direct if the sender is an EOA, less so if it’s smart account (i.e. still it reduces to owner signatures in calldata or a UserOp signature). Either way, that means the chain already proves the important fact that a specific account authorized the publication of a specific ciphertext at a specific time (i.e. without any transcript disclosure at all). If plaintext is later disclosed, the wallet bound identity proof and the signed ratcheted payload can connect that disclosed content to the messaging identity used in the session.

This is quite different from systems in the Signal family which are designed so that a saved transcript does not become a portable proof for outsiders (i.e. messages are verified with symmetric MAC keys that both parties share, so either side could plausibly have forged any message).

What I propose here is also different from offchain systems like XMTP but in a more specific way. I think that XMTP can support verifiable attribution through exported protocol artifacts and its identity layer, but that proof is not normally a publicly witnessed chain event. It depends on disclosing offchain transcript material and relating installation level keys to an inbox identity and then to a wallet or other identifier.

Thoughts on possible future extensions

One possible extension is hidden delegation, where a relay publishes the ciphertext while the principal identity remains inside the encrypted envelope (i.e. unlike now that it’s in the clear). In that case, accountability does become disclosure dependent: once the recipient reveals the hidden identity proof, a third party can verify both the onchain relay publication and the principal attribution carried in the disclosed proof.

As for deniability, my current view is that full transport level deniability is not compatible with public event logs. A narrower form of deniability inside the ratchet transcript may still be worth exploring, and I would be interested in feedback on whether that is meaningful.

How to deal with metadata privacy

Assuming full e2ee with forward secrecy and post-compromise security, the attainable goal is not to eliminate all metadata, but to eliminate any efficiently verifiable linkage and leave observers with only statistical inference whose quality depends on traffic volume and side information.

Put differently, once deterministic recipient discovery (ie. recipientHash) is removed from the transport, or recipient filtering happens client-side rather than at the RPC layer, an observer falls back to heuristics. A simple intuition is: let C(e') be the set of earlier events that are not cryptographically ruled out as possible predecessors of a target event e'. Then

Pr[e ↔ e' | view] = w(e, e') / Σx∈C(e') w(x, e')

where w(e, e') is a heuristic weight derived from timing, visible sender activity and any other side information available to the observer. So what should disappear is any public rule that makes one candidate pair dominate the distribution with near certainty. This, of course, matters differently at the public chain observer level and at the RPC or indexer level, since the latter also see client queries.

Mitigation options

I think this proposal should explicitly separate mitigations for public-observer recipient privacy from mitigations for query privacy against RPCs or indexers (the latter can do anything that former can but not vice-versa). Therefore, the main mitigation choices and their tradeoffs should be weighted compared to the current status quo (see the above diagram):

  • Keep recipientHash, but avoid server-side recipient filtering. Clients discover inbound handshakes by scanning Handshake logs locally instead of querying recipientHash specific filters. This removes the first identity leak during handshake discovery, but it does not hide attempted first contact from public observers, since recipientHash remains dictionary-matchable. If later MessageSent retrieval still uses topic specific server-side filters, the RPC can still observe anonymous reading patterns and interest in messages from visible senders. What disappears is the direct network client → recipient bootstrap, not all query leakage. So the most private version of this approach would be full local scanning of all events, with O(N) cost over the scanned range.

  • Remove recipientHash from the public handshake selector. Instead of publishing a deterministic recipient selector, the sender encrypts recipient-targeting material under recipient specific public material and recipients keep only the handshake events they can decrypt. This removes the public dictionary attack on first contact and also removes the initial linking step that lets a malicious RPC connect a querying client, for example via IP address or TLS fingerprint, to a recipient address. Later topic queries are still visible to the RPC, but only as anonymous interest in topics emitted by visible senders. So the RPC no longer has a direct way to conclude that two addresses are talking and is pushed back to the kinds of heuristics above. This is a better privacy starting point, although it is still not full private retrieval. It also still requires linear client side scanning at least for handshake discovery (i.e. O(N) where N now is just the number of handshake requests, which can be orders of magnitude smaller than total message traffic). It also needs some way to publish recipient encryption material, like an onchain registry or another public key distribution mechanism.

  • Use private signaling with a TEE-assisted indexer. Another option is to hide recipient interest from the indexing service, following the private-signaling direction explored in this paper: the sender posts a public mailbox entry while recipient-targeting material is processed inside a TEE and only the intended recipient learns the match. The tradeoff is extra infrastructure, hardware assumptions and scalability limits that are very different from the other approaches.

My current view is that the ERC should probably avoid over-standardizing this layer, but it would still be useful to be explicit about which privacy model it assumes and related reccommendations (e.g. to avoid using the same provider for both tx submission and read queries, since that gives a single party a stronger vantage point for correlation).

Resistance to HNDL

Message content confidentiality should not face the threat of harvest now decrypt later. A future attacker should not be able to record traffic today and later use stronger capabilities to recover message contents, link handshake responses to later traffic, or link later ratcheted topics from stored traces alone.

The current construction tries to enforce that with a hybrid bootstrap based on X25519 + ML-KEM 768, a handshake response tag derived from both classical and PQ secret material and topic derivation salted by a hybrid root key. My intent is that the PQ story should cover both confidentiality and linkage resistance, not only message decryption.

What I would most like feedback on

  1. Is this the right layer to standardize or is it still too application-specific to benefit from an ERC?
  2. Is the privacy model coherent?
  3. Of the mitigation options above, which one feels realistic for an interoperable standard, if any?
  4. Does the non-repudiation property feel useful here or is it more likely to be a reason not to pursue this design?
  5. Is the current scope narrow enough, or am I still standardizing too much of the messaging stack?

I would especially value pushback on the privacy and security model. For more details on the contract the sdk, you can find some work in progress docs here.

Thanks

1 Like

Hello. I have been working on these issues for the past three years, with a break over the past ten months or so due to other work obligations. However, I was just gearing up to dive back in, so I’m glad I saw your post.

I am the author of ERC 7970. I have worked on a couple of different versions of an app for iOS/macOS that uses this protocol (or something similar), along with some other ideas.

I will respond in more detail to the substance of your post, but you are welcome to message me directly if you’re interested in discussing this.

Scott

Thanks for the quick feedback Scott.

I was mainly interested in understanding how the dev/research community sees this design space and whether standardising something along these lines actually makes sense at all.

On my side, I’ve open sourced a full ts sdk around the idea, with the goal of making the transport abstract enough to support very different kinds of apps (e.g in-app messaging, like certified-email clients, private agent communication etc), all on top of the same deployed smart contract.

What I’m still unsure about is whether a shared standard is really the right end state or whether future applications will always want slightly different guarantees and therefore end up deploying their own variants of a minimal event-emitting contract anyway.

Part of what I find interesting is why onchain messaging never seemed to gain much traction alongside p2p approaches (e.g. whisper later superseded by waku). That makes me wonder whether this design space has simply been underexplored, or whether private onchain messaging has generally been perceived as too costly or too niche.

My suspicion is that metadata exposure is a big part of the reason, which is also what motivated this post. That may also be the part that is hardest to standardise at the ERC level, since the real difficulty seems to shift toward reading and infrastructure challenges on Ethereum, potentially pushing implementations toward expensive approaches such as oblivious retrieval, PIR-like schemes etc.

So I’d be very interested to hear your and other devs thoughts on those questions.

P.s. I’ve also moved beyond the PoC stage so I’d be happy to compare notes and discuss details

-M

1 Like

M –

Your core question, as I understand it, appears to be:

What, if anything, should be standardized in a smart contract that drives an encrypted messaging system on EVM-compatible blockchains?

My initial thought is that it depends on the application. “Messaging” is a broad concept that requires different levels of security and different tradeoffs in different settings. That suggests that a truly universal standard, if it exists, should probably be as simple as possible at the contract layer. Additionally, I would guess that if blockchain-based encrypted messaging ever catches on, there is room for more than one commonly-used protocol suitable for different use cases.

As for protocols that are eventually viewed as standards, my intuition is that this will be driven primarily by application adoption rather than optimal protocol design. In other words, a standard may emerge because a successful app uses a protocol, even if it is not the best general-purpose design.

The approach described in your post and ERC pre-draft suggests a particular type of messaging system, with specific assumptions about privacy and attribution. For example, the careful treatment of metadata and the inclusion of non-repudiation as a feature suggests that verifiable communication tied to on-chain activity is a higher priority than, for example, casual communication of a more general nature. If you could elaborate on the specific messaging environments you are aiming to support, that would help clarify how broadly you intend this to apply.

With that in mind, here are some initial reactions to your questions:

1. Is this the right layer to standardize or is it still too application-specific to benefit from an ERC?

I suspect this may be too much to standardize at the ERC layer, at least at this stage. Some form of minimal transport may make sense, but once you move into handshake design, identity, and session behavior, it starts to look more like a full protocol for a specific subset of messaging activities rather than a shared interface for messaging more broadly.

2. Is the privacy model coherent?

Yes, conceptually. But it may be more complex than necessary for some applications. For example, a general-purpose messaging app might accept some degree of metadata exposure in exchange for simplicity, lower cost, and easier implementation.

3. Of the mitigation options above, which one feels realistic for an interoperable standard, if any?

I am still forming a view on this, but my intuition is that anything requiring significant additional infrastructure (e.g., TEEs or specialized indexing) may be difficult to standardize at the ERC level. Simpler approaches, even if imperfect, may be more realistic in practice.

4. Does the non-repudiation property feel useful here or is it more likely to be a reason not to pursue this design?

It seems useful for certain applications, particularly where attribution or auditability is important. At the same time, it is likely to be undesirable in more general messaging contexts, so it feels like a tradeoff rather than a universal advantage.

5. Is the current scope narrow enough, or am I still standardizing too much of the messaging stack?

My instinct is that this is still a fairly broad scope for an ERC standard. Whether that is “too much” probably depends on whether you are aiming for a general-purpose standard or something tailored to a narrower class of applications.

Now, to address some of your points in your response.

What I’m still unsure about is whether a shared standard is really the right end state or whether future applications will always want slightly different guarantees and therefore end up deploying their own variants of a minimal event-emitting contract anyway.

On whether all blockchain-based messaging systems will converge on one standard or not, my guess is probably not. There might be some shared baseline, but beyond that I would expect different apps to end up with their own variations.

Part of what I find interesting is why onchain messaging never seemed to gain much traction alongside p2p approaches (e.g. whisper later superseded by waku). That makes me wonder whether this design space has simply been underexplored, or whether private onchain messaging has generally been perceived as too costly or too niche.

Personally, I think it has been underexplored, which is why I am exploring it. I have often heard cost cited as a barrier, but the least expensive chains now make messaging practical from a cost standpoint. As for it being too niche, this is why my efforts in app development have focused on making adoption easy, especially for people with no experience using blockchain technology, and who do not want to deal with exchanges or financial transactions.

My suspicion is that metadata exposure is a big part of the reason, which is also what motivated this post.

That seems plausible for messaging that requires a high degree of privacy. For more casual messaging, though, metadata exposure may be an acceptable tradeoff for censorship resistance. There are also ways to reduce metadata leakage after a connection is established, for example by using encrypted channels to switch between multiple addresses and chains.

Final thoughts, for now.

For my own thinking about this, it would be helpful to better understand what this protocol would be used for, specifically, and how functional it would be in practice. For example, what would be the cost per message byte on different chains? In my experience, an ultra-simple contract on the least expensive chains can support thousands of messages with a few hundred characters for one dollar or less. On the other hand, the same messaging on Ethereum is prohibitively expensive. If the goal is to link encrypted messages to transactions on popular chains that are actually used for financial purposes, the cost might be a significant barrier, unless you can find a way to make sufficient identity and message-origin guarantees in a cross-chain environment.

A few more questions.

  1. How many on-chain transactions are typically needed to establish a session and then send messages?
  2. Roughly how large are the handshake and message payloads?
  3. Am I right that the hard part is not detecting events, but doing so without leaking too much through the RPC call?
  4. If you had to narrow it down, which parts do you see as essential to standardize, and which are just implementation choices?

Reading through @sewing848’s reply, I think the scoping question he raises is the right one to sit with before going further on the cryptographic details.

My own instinct leans with him on “too much to standardize at the ERC layer, at least at this stage” — not because the cryptographic design is wrong, but because a full PQ e2ee messaging protocol (handshake + session + ratchet + identity + privacy model) is a vertical stack where most layers are genuinely application-specific. Different apps will want different trust models on the ratchet, different privacy budgets against RPCs, different attribution semantics.

What might be worth extracting from this predraft into separately-standardizable pieces:

1. The PQ key registry surface. Your Option 2 mitigation depends on a public key distribution mechanism. This is infrastructure, not messaging. A PQ key registry standardizing hybrid Kyber + Dilithium public key publication (with versioning and wallet binding) is genuinely reusable — messaging, encrypted tokens, encrypted voting, any PQ-aware contract needs it. There’s a draft ERC in this direction on ethereum/ERCs (happy to link if useful).

2. The wallet-bound identity proof format. Binding a PQ identity to an EVM account is a pattern that’ll come up repeatedly. If this predraft defines it well, that piece alone might deserve to live as a separate small ERC that messaging, DIDs, and other identity-adjacent standards can reference.

3. Leave the full protocol as a reference implementation, not a standard. Ship the SDK and demo you mentioned, let other messaging apps adopt or fork, and see what converges naturally. The Signal / Olm / MLS path in the non-blockchain world is instructive — MLS only emerged as an IETF standard after years of implementation experience, not before.

On @sewing848’s practical questions about cost and transaction count — genuinely curious too what your benchmarks look like on cheap chains vs mainnet. The economics end up constraining the design space more than the cryptography does.

On the non-repudiation point: I think it’s a legitimate slot in the design space (different from Signal/XMTP in a useful way), but sewing848 is right that it’s a feature for a class of apps, not all messaging. That reinforces the case for not over-standardizing.

1 Like