How Ethereum Stealth Addresses Work | Technical Deep Dive

If you’re building on Ethereum or exploring how to handle private transactions on-chain, this post is for you. We’ll walk through how stealth addresses work, the cryptography behind them, the implementation standards, protocols building with them.
Make sure to follow us on X to stay updated on our upcoming technical deep dives on protocol design and architecture 🌚
Why Privacy Matters on Ethereum
Ethereum is built to be public. Every transaction, contract call, and balance change can be seen and verified by anyone. This transparency sounds like the core feature of any blockchain, but context matters.
Over time, Ethereum activity has expanded beyond simple token transfers. Today, interacting with the ecosystem often exposes sensitive information:
- DID
- ENS names linked to addresses
- NFTs and POAPs
- Soulbound tokens
- Protocol usage, staking patterns, and other on-chain identifiers
This means users are not only revealing financial information but also personal activity. A wallet can become part of someone’s public identity. Once an address is linked to a person, anyone can see which assets they own, which protocols they interact with, and how frequently they move funds.
As Vitalik Buterin notes in his essays, privacy remains one of the largest challenges in Ethereum. Most privacy solutions today focus on token transfers, but the ecosystem increasingly involves revealing personal data and interactions. Similarly, emerging identity projects make tracking on-chain behavior even easier, increasing the exposure of sensitive information.
From a technical perspective, privacy matters because control over data implies control over users. Centralized collection of public blockchain data can enable profiling, targeted attacks, or unwanted surveillance.
There are different ways to approach privacy on Ethereum. Today, we’re going to talk about stealth addresses.
Stealth addresses provide one approach. They allow assets to be received without exposing the recipient’s main address. This protects sensitive information while remaining fully compatible with Ethereum’s infrastructure.
So, What Are Stealth Addresses?
Stealth addresses are a way to receive funds on Ethereum without letting observers map payments back to a single wallet. Normally, once an address is known, every transfer connected to it becomes part of a permanent public trace. Stealth addresses change this by introducing a mechanism where each incoming payment lands on a fresh, unrelated address. This happens without any direct interaction between the sender and the recipient. They do not coordinate or communicate on-chain.
Here’s the idea in simple terms: instead of sharing a wallet that becomes tied to your on-chain identity, you expose a key that lets others generate unique one time destination addresses on your behalf. Those addresses are derived in a way that only you can find them and spend from these addresses, but onchain they look like completely separate accounts.
This breaks the linkability problem of Ethereum’s account model while keeping the sending process straightforward — one piece of information is enough to route a payment, even though the actual destination is different every time.
Stealth addresses already have established standards: ERC-5564 and ERC-6538, with ERC-6538 adding some extra functionality. We’ll walk through what stealth addresses are and how these standards define them a bit later in this post.
Core concepts of Ethereum Stealth Addresses
- Private transactions on Ethereum
Let's start with the goal. What should a stealth address system do, and what conditions should it meet?
To understand this, let’s take a step back and look at how normal transfers work today. You have an address or an ENS name. You share it, and someone can send funds. That’s it. Stealth addresses add privacy to this flow. Nobody watching the chain should be able to tell who actually received the funds, while the transfer process stays the same. The sender still only needs some identifier to send funds to.
The goal of stealth addresses on Ethereum is to add privacy for the recipient so that no one can tell who received the funds, while keeping the transfer process unchanged.
- Elliptic curve basics for stealth addresses
Next, we need a quick refresher on elliptic curve cryptography. Don’t worry, to understand how stealth addresses work, we only need a couple of core concepts: the generator point G and scalar multiplication on elliptic curves. That’s enough to follow the rest of the mechanics.
The generator point is the base point from which all other points in the group are derived by repeatedly adding the point to itself — this is scalar multiplication. The points on the curve correspond to public keys. Each public key is calculated by multiplying a private key (a large random number) by the generator point:
M = m * G
Where:
- m is the private key (scalar)
- M is the public key (point on the curve)
- G is the generator point
At the same time, the system stays secure because of the nature of elliptic curves, as there is almost no way to determine m knowing M and G as a consequence of the elliptic curve discrete logarithm problem.
How Stealth Addresses on Ethereum Work Step-by-Step Workflow
Let’s walk through a simple scenario: Alice wants to send funds to Bob’ stealth address. We’ll cover exactly what each side does, why, and how the cryptography works behind the scenes.
Step 1: Bob Generates a Spending Key
Bob wants to receive funds on stealth addresses (addresses in plural because it eventually is a set of addresses, sorry for a spoiler).
To do this, he generates a private key m. In our process, it’s called a spending key. This key will later allow Bob to spend funds from any stealth address derived from it.
At this stage, Bob does not need to sign anything. He only keeps m private key in secret.
Step 2: Derive the meta‑stealth address M
Next, the spending key m is used to get the meta‑stealth public key M by the formula we already know:
M = m * G
At this stage, we consider the meta‑stealth address to be the public key for our spending key.
Step 3: Registering the Meta‑stealth Address
The next step is making the meta‑stealth address discoverable for the sender. Bob registers his meta‑stealth address in a special contract defined by ERC‑6538. This contract acts as a registry of all meta‑stealth addresses.
Users who want to receive funds on stealth addresses link their meta‑stealth address to their main Ethereum address in the registry. This way, senders can look up Bob’s meta‑stealth address before sending funds.
This way, if Alice knows Bob’s regular Ethereum address or his ENS name, she can look up his meta‑stealth address in the ERC‑6538 registry. This is the address she will use to generate a one-time stealth address for sending funds to Bob.
Step 5: Alice generates an ephemeral key
Let’s assume she found Bob’s meta‑stealth address. Next, Alice needs to generate a one-time private key r, which will be used in generating Bob’s one-time stealth address. In our process, it is called an ephemeral key (R):
R = r * G
And again, Alice needs to publish the ephemeral public key. The question is the same: how and where to publish the ephemeral public key? ERC‑5564 provides the answer, as it standardizes this entire process. But first, we’ll finish describing the process and then return to the standard.
Step 6: Computing the Shared Secret
Once Alice has published her ephemeral public key (R), she needs to compute the shared secret using Bob’s meta-stealth public key (M) and her one-time private key (r):
S = r * M
It’s called a shared secret because Bob can also compute the same value but from his side, using a different formula.
Instead of multiplying Alice’s meta-key, he is going to use his own private key (m) and Alice’s ephemeral public key (R):
S = m * R
Why this works:
S = r * M = r * (m * G) = m * (r * G) = m * R
So both sides can independently arrive at the same shared secret without revealing their private keys.
Step 7: Generate the Stealth Address
We now have all the pieces:
- Bob's meta-stealth address (M)
- Alice's ephemeral public key (R)
- The shared secret (S)
Alice can generate Bob’s one-time stealth address using this formula:
P = M + G * hash(S)
The Purpose of the Hash Function
The values M, R, and S are points on the elliptic curve. The formula G * hash(S) requires a scalar number, not a point. The hash(S)operation converts the point S into that necessary number.
How the Stealth Address Relates to Bob's Meta-Address
Looking at the formula, the stealth address P is Bob's original meta-address M, offset on the curve by the public key G * hash(S).
Alice uses a random factor to shift Bob's public identifier to a new, unique address. She sends funds to this one-time stealth address. Only Bob, who can compute the same offset, can access the funds.
Step 8: Spending funds from the stealth address
The final step answers the question: how does Bob access the funds in this stealth address?
Bob needs the private key for the stealth address. The formula is:
p = m + hash(S)
Private Key Structure
The private key for any stealth address is an offset of the meta-address private key by the hash of the shared secret. Only Bob can compute this private key because he is the only one who knows the private key for his meta-address.
The process we;ve just covered above was the core idea of stealth addresses Vitalik Buterin laid out. Now let’s look into one of the key requirements that makes this whole system work – non-interactivity and the standard that addresses this requirement.
How Stealth Address Discovery Works with ERC-5564
As we already know, one of the key requirements for private transactions on Ethereum via stealth addresses is avoiding direct interaction between sender and recipient. We've covered how Alice finds where to send funds by looking up Bob's stealth meta-address in a unified registry.
Basically, when you register your meta-address, you reveal that you can receive funds on stealth addresses, but no one except you knows the exact one. Of course, the sender knows it too, but only for the specific case when he or she generates this address for a particular transaction.
But how does Bob know which stealth address received funds? With infinite possible addresses, how does he find the right one?
We know that Bob needs the shared secret to compute the stealth address, and to get the secret he needs Alice's ephemeral public key, which she publishes somewhere. This discovery problem is solved by ERC-5564, which creates a standardized way for senders to announce transactions without revealing the recipient.
The ERC-5564 Announcement Method
ERC-5564 specifies a contract with a single announce method, which is used for publishing ephemeral one-time keys and the stealth addresses derived from them. Senders call this method, provide the data, and the method emits an event with these parameters. This way, we now have a single place where all stealth address creation events are published.
The Computational Workload
Now to Bob, our receiver. There’s a single place to look for stealth addresses creation events, but no one knows which event is intended for which recipient. They're anonymous. And that's the whole point because the initial goal was to add privacy.
At this point to access funds, Bob has to compute the shared secret using his private key for each announce event, derive a potential stealth address, and check for funds. If he finds a match, he needs then derive the private key to access them.
It sounds like a lot of work and we need a better way to handle it.
Delegating the Work with Viewing Keys
The obvious fix is to offload computations to a service. However, for a service to do all the work, you would have to give it your private key. And that it sounds like a bad idea.
ERC-5564 stealth addresses specification offers a solution.
It introduces a model where the meta-address is no longer a single key, but a combination of two: a spending key and a viewing key.
Originally, the meta-address represented only the spending key.
Now, it includes both:
M = (K, V)
Where:
- M is the meta-address,
- K is the public spending key
- V is the public viewing key (with corresponding private keys k and v).
How the Viewing Key Changes Stealth Address Discovery
The viewing key shifts how the shared secret is computed.
With the two‑key model, the shared secret comes from the viewing key:
S = V * r = v * R
The stealth address itself relies on the spending key.
The public key is derived as:
P = K + G * hash(S)
And the matching private key is:
p = k + hash(S)
This way, users can receive funds on stealth addresses without handling the addresses discovery workload themselves.
A service can take over all the computations using the private viewing key. It can find every stealth address linked to that user, yet it cannot move any funds from it. Only the owner of the spending key can access them.
So, we delegated all the stealth‑address discovery work to an external service. But the workload didn’t get any smaller. It still needs to be reduced and this is what we’re gonna go through in the next section.
Reducing Computational Workload with View Tags
ERC‑5564 introduces the concept of a view tag, which is the first byte of the hash of the shared secret. When scanning through all the anonymized Announce events, you only need to compute the shared secret once per event, extract the first byte, and compare it to the event’s view tag.
If the bytes don’t match, you know the event isn’t for you and can skip it. If they match, you proceed with the rest of the calculations. Using view tags dramatically reduces the computational workload for discovering stealth addresses on Ethereum.
Beyond just computation, there’s another challenge in stealth addresses workflow.
Handling Gas for Stealth Addresses
When a stealth address receives tokens or anything other than native ETH, it has no balance to pay for gas. That means the funds are stuck until the address gets topped up. Sending funds to cover gas from an existing wallet ruins the entire purpose of stealth addresses — it links transactions back to you and breaks privacy.
There are several ways to approach this, but in the context of building an application that manages and interacts with stealth addresses, one practical direction is to use account abstraction with a paymaster.
When Alice generates a stealth address, she can call a view function on the account factory. The factory maps any address to its future smart account — even if that smart account doesn’t exist yet, the address is already predetermined. Alice can send the funds directly to that smart account.
If Bob later wants to interact with those funds, he can do it through a paymaster. This is one viable way to solve the gas problem for stealth addresses.
Examples of Stealth Address Implementations in projects
To wrap up, let’s briefly look at projects that implement the stealth address concept we’ve discussed. Two notable examples are Fluidkey and Umbra.
Although both follow the same EIP, their implementations naturally differ in approach and technical details.
Fluidkey Stealth Address Implementation Overview
Let’s take a closer look at Fluidkey and how they implement Ethereum stealth addresses. They offer both web and mobile versions of their wallet application. On GitHub, their fluidkey-stealth-account-kit contains the main logic for the calculations we discussed earlier: generating meta-addresses, ephemeral addresses, and stealth addresses. It also includes example scripts showing the proper order for using the kit’s methods.
Let’s look at what stands out in their implementation.
Notable Features of Fluidkey Stealth Address Implementation
1. Deterministic Key Generation
The first time you open Fluidkey and connect your wallet, the app asks you to create a PIN code, which you will use for all future logins. Once you set the PIN, the kit method generateFluidkeyMessage is called. This method takes your wallet address and the newly created PIN, concatenates them, hashes the result, and generates a message in your wallet that prompts: “please sign this hash.”
Once you sign the hash, the kit method generateKeysFromSignature is called, taking your signature as input. Inside the function, the signature is split in half: the first half becomes the spending key, and the second half becomes the viewing key.
This approach means Fluidkey never needs to store your keys. Every time, the keys can be deterministically regenerated from your wallet address and PIN. On top of that, if anything happens to the app, the code is open-source—so you can recreate your keys and access your funds independently.
2. Handling Zero-Balance Stealth Addresses
As to the issue with zero-balance on a freshly created stealth address we’ve discussed before, Fluidkey addresses it by using Gnosis Safe accounts.
3. Mapping User Meta-Addresses via Domains
Fluidkey doesn’t use a global registry to determine users’ meta-addresses, as the standard suggests. Instead, the team decided to handle this through domains. They registered their own subdomain, fkey.eth. When you first log in, an account like username.fkey.eth is created (the username can be changed later).
We won’t go into ENS mechanics here, but the key idea is that Fluidkey uses an OffchainResolver contract, following EIP-3668, to provide data for compatible wallets and explorers such as Etherscan.
The displayed data is a URL like https://username.fkey.id. You can scan it with a QR code or connect your wallet to send funds to the stealth address associated with that subdomain. Page refreshes rotate addresses automatically, maintaining privacy, just as expected on Etherscan.
4. User Experience in Stealth addresses implementation
From the user’s perspective, Fluidkey looks like a normal wallet. The user doesn’t see hundreds or thousands of separate addresses
When you initiate a transfer, Fluidkey looks for a stealth address that has enough funds to cover the amount. If none of the addresses has sufficient balance on its own, the app searches for the best way to combine multiple stealth addresses. All of this is executed in a single transaction, so the user never deals with the complexity happening underneath.
That was a high-level overview of Fluidkey. Now let’s talk about Umbra.
Umbra Stealth Address Implementation Overview
Umbra has been around much longer than Fluidkey and sits right at the roots of the EIP-5564 standard. Its team includes the authors listed in the standard itself, and Fluidkey even mentions that some of its code is based on Umbra. Basically, they were the early movers in this space, which explains why their implementation sticks closer to the standard.
Key Features of Umbra’s Implementation
- Meta-Address Registry: Umbra created its own contract to register user meta-addresses.
- Stealth Address Announcements with Transfers: Umbra also implemented a second contract, which is used to announce the creation of stealth addresses. Beyond publishing the Announce event, the contract performs the fund transfer in the same call. It means that to send funds to a user, you create a stealth address and send the funds through the Umbra contract. That same transaction emits the Announce event, publishing both the stealth address and the associated ephemeral key.
- Separate Methods for ETH and Tokens: ETH is sent directly to the stealth address. Tokens, on the other hand, are held in the Umbra contract until the recipient calls withdraw from the stealth address to claim them.
- Funding Zero Balance Wallets: Umbra gives options for handling empty stealth addresses. You can pre-fund the address, or let the recipient cover transaction fees from the funds they receive. So, it’s clear that low-value or spam tokens can’t be used to cover fees, and the balance must be sufficient. Therefore, there’s a minimum transfer threshold, and only a limited set of tokens is accepted for sending.
- Spam Prevention: It’s also worth noting that Umbra may require a fee from the sender to prevent spam. On networks with low transaction costs, it’s easy to flood the system with small transfers. Since the system continuously scans transactions, the sending fee acts as a safeguard against abuse.
All in all, Umbra provides a solid, standard-compliant approach, showing a different way to handle stealth addresses compared to Fluidkey.
Key takeaways
Core Idea
- Stealth addresses let users receive assets on Ethereum without exposing their main wallet.
- Each transfer generates a one-time address that only the recipient can detect and spend from.
Why This Matters
- Ethereum’s transparency leaks personal and behavioral data (ENS, DIDs, NFTs, staking patterns).
- Once an address is tied to a person, their entire history becomes public.
- Stealth addresses break linkability while staying compatible with the existing Ethereum stack.
How do stealth addresses work on Ethereum?
Stealth addresses work by generating a unique one-time address for every incoming transfer. A sender uses the recipient’s meta-stealth address, derives a shared secret with an ephemeral public key, and computes a fresh destination address. The recipient scans for announcements, reconstructs the shared secret with their view key, and uses their spend key to control the one-time address.
Quick steps:
- Sender retrieves the meta-stealth address.
- Sender generates an ephemeral key pair.
- Both sides derive the same shared secret.
- Sender computes a one-time destination address.
- Recipient discovers and spends from that address.
Standards to Know
- ERC-5564 — stealth address announcements, view tags, and discovery logic.
- ERC-6538 — registry for meta-stealth addresses (sender lookup).
What is EIP-5564?
EIP-5564 defines a standard mechanism for stealth address announcements on Ethereum. It specifies how senders publish ephemeral public keys, how recipients discover transfers using view tags, and how wallets should derive one-time addresses from a shared secret.
EIP-5564 includes:
- Announcement event format
- Ephemeral key requirements
- View tag structure
- Expected client-side scanning behavior
Real World Examples
- Fluidkey:
- Deterministic key derivation, Gnosis Safe accounts, ENS domain mapping, UX that hides the complexity.
- Umbra:
- Early implementation aligned with standards, custom registry, on-chain announcements + transfers, spam-resistant design.
How does Umbra implement stealth addresses?
Umbra implements stealth addresses by combining on-chain announcements with off-chain key derivation. A sender publishes an ephemeral public key in an Umbra contract, while the recipient scans these announcements, derives the one-time private key, and retrieves the funds.
Umbra’s design includes:
- A custom announcement registry
- Ephemeral key + shared secret derivation
- Off-chain scanning using a view key
- A relay for gas abstraction
When You Should Consider Using Stealth Addresses
- Wallets requiring private inbound transfers.
- Applications working with identity-linked accounts (ENS, SBTs, DID).
- Use cases where linkability compromises user autonomy or safety.
- Any product where on-chain receipts shouldn’t expose a user’s main address.
Can Ethereum addresses be private?
Ethereum addresses are not private by default—every transaction is publicly visible. Privacy is only achievable through additional techniques such as stealth addresses, mixers, shielded pools, or rollup-level privacy. Stealth addresses focus on breaking address linkability without modifying Ethereum’s base protocol.
Privacy tools on Ethereum:
- Stealth addresses (EIP-5564 / ERC-6538)
- Zero-knowledge systems (zkSync, Aztec)
- Mixers or batching systems
- Intent-based private mempools
About Rock’n’Block
Rock’n’Block is a Web3-native development studio building blockchain infrastructure and decentralized applications. We help founders deliver high-performance protocols, privacy-preserving features, and user-focused tooling that scale across Ethereum and other chains.
What we do:
- Build Layer-1 chains, DeFi protocols, and decentralized applications.
- Develop privacy and identity-preserving solutions for smart contracts and transactions.
- Create blockchain data streaming and analytics tools for real-time and historical insights.
- Implement chain-agnostic financial tooling for developers and users.
With nearly a decade of hands-on blockchain experience, our team has supported products used by 71M+ DeFi users, reaching $2.5B in market cap, and helped partners raise $167M.
About Rock’n’Block
Rock’n’Block is a Web3-native dev studio building DeFi protocols, wallets, and blockchain infrastructure. We help founders ship high-performance products faster, scale UX to millions of users, and integrate privacy-aware and on-chain financial tooling.
Follow us on X for more deep dives.
What we do:
- Build custom Layer-1 chains, DeFi protocols, and decentralized exchanges.
- Develop wallets and DeFi platforms with privacy and transaction flow optimizations.
- Stream blockchain data for real-time and historical insights.
- Implement chain-agnostic payment solutions and tooling for DeFi users and protocols.
With almost a decade in Web3, our team has supported products used by 71M+ DeFi users, hit $2.5B in market cap, and helped partners raise $167M.
We ♥️ Development






