Skip to main content

Stealth Address AA Plugin

Β· 11 min read
Justin Zen

Stealth Address AA Plugin is a smart account plugin built on top of modular smart account provider including ZeroDev Kernel and Biconomy.

πŸ’‘ If you're well-versed in Account Abstraction and stealth addresses, please skip to Section III.

I. What is Account Abstraction (AA) Plugin​

a. Account Abstraction​

Account Abstraction (ERC-4337) changes how you interact with your crypto wallet. To better understand this, let's use a real-world analogy: think of your crypto wallet as your house, a secure place where you store all your digital assets.

In the pre-AA era, entering this 'house' to manage your assets required a singular, specific 'key'β€”your private key. You'd need this one and only key to both access your assets and perform transactions.

However, Account Abstraction significantly expands your options. Now, instead of relying solely on that traditional private key, you can also gain entry through various other means of identification like fingerprint scans, voice recognition, or any other form of proof that establishes your identity.

Beyond that, you can add custom rules and logic to your smart account. For instance, you could implement a daily transaction limit for added security, or automate a small contribution to the developers behind Account Abstraction each time you access your wallet, as a way to express gratitude for their groundbreaking work.

The wallet with account abstraction is called smart wallet or smart account compared to external owned account (EOA).

b. Modular Smart Contract Account and Plugin​

As smart accounts evolve, gaining new capabilities for enhanced security and user experience, the question arises: What if we want to adapt our smart accounts to different scenarios or upgrade them just like we update software on smartphones? The traditional method of asset migration between smart accounts designed for different use cases has been cumbersome, to say the least.

Enter ERC-6900: Modular Smart Contract Account and Plugin, which addresses these challenges head-on. Extending our 'house' analogy, with ERC-6900, you no longer have to build your digital house from scratch. You can now start with a robust foundational structure and customize it with your choice of 'furniture,' such as specific gates, modules, or plugins, to fit your unique needs.

Platforms like ZeroDev Kernel and Biconomy have already implemented this modular approach and make it remarkably straightforward to create these modular plugins or modules for your smart account.

For those interested in diving deeper into the realms of Account Abstraction and its modular extension, we recommend checking out our previous article Account Abstraction Lego. Additional comprehensive guides can be found here, here and here.

II. What is Stealth Address​

While the transparency of blockchain technology brings numerous benefits, it also has its downsidesβ€”particularly when it comes to privacy. For instance, if you're paying your employee's salary or buying a cup of coffee, the transactions are publicly visible. This means anyone can trace the addresses involved and discern financial details like salary amounts or a cafΓ©'s monthly earnings.

A workaround might be to create a new address each time you receive tokens. However, this strategy makes managing assets across multiple addresses a complicated and cumbersome task.

To address this privacy concern, the concept of stealth addresses was introduced for Bitcoin back in 2014, and has since been refined (improved, dual-key). It's now available for Ethereum as ERC-5564.

caption
Workflow from Vitalik's Post

With a stealth address, you don't send tokens directly to the receiver's public address. Instead, a stealth address is generated using an ephemeral key combined with the receiver's public address. Only the sender and receiver are privy to who actually owns this stealth address. Furthermore, only the receiver has the ability to withdraw tokens sent to the stealth address, ensuring both privacy and security.

For those eager to delve into the finer details of stealth addresses, we highly recommend reading An incomplete guide to stealth addresses post by Vitalik, as well as this insightful post that provides an excellent introduction to the subject.

III. Why Stealth Address AA Plugin​

In this section, we will delve into the dual motivations behind our Stealth Address Account Abstraction (AA) Plugin, looking at it through the lenses of both Account Abstraction and stealth addresses:

  1. Account Abstraction: privacy-preserving plugin
  2. Stealth address: transition from EOA to smart contract account

a. Account Abstraction: privacy-preserving plugin​

We believe that privacy should be an inherent property of blockchain technology, not just an optional add-on.

While Account Abstraction (AA) has been instrumental in providing flexible verification logic beyond the traditional ECDSA signature, there remains the need to confirm your identity and prove ownership of the wallet. Whether it's a private key, an enclave-based key, or even biometric data, some form of identification is essential.

At MoonChute, we've created Unified Smart Account Managers that associates an individual's EOA address with their respective smart accounts. From the feedback we've gathered, this utility has been instrumental in simplifying the management of multiple smart accounts. However, we believe that users should also have the freedom to choose how much privacy they want to maintain.

caption
Unified Smart Account Manager

To strike a balance between the utility of Account Abstraction and the need for privacy, stealth addresses serve as an ideal solution. They fulfill our aim of enhancing user privacy without sacrificing the flexibility and user experience that smart accounts offer.

b. Stealth address: transition from EOA to SCA​

If we are going to allow existing EOAs to upgrade to contract , why not make stealth address a contract account?

IV. How Stealth Address AA Plugin works​

a. ECDSA validator plugin​

Within the ZeroDev Kernel's ECDSA Validator, a user operation (userop) is validated based on whether the signature comes from the owner address specified in the validator contract. As the validator facilitates a seamless transition from to smart accounts, there's an opportunity to boost privacy. Specifically, we can break the direct link between the smart account and its owner.

struct ECDSAValidatorStorage {
address owner;
}

function validateUserOp(UserOperation calldata _userOp, bytes32 _userOpHash, uint256)
external
payable
override
returns (ValidationData validationData)
{
address owner = ecdsaValidatorStorage[_userOp.sender].owner;
bytes32 hash = ECDSA.toEthSignedMessageHash(_userOpHash);
if (owner == ECDSA.recover(hash, _userOp.signature)) {
return ValidationData.wrap(0);
}
if (owner != ECDSA.recover(_userOpHash, _userOp.signature)) {
return SIG_VALIDATION_FAILED;
}
}

b. Stealth address​

For simplicity, let's focus on the basic version of stealth addresses. The objective here is for a sender to transfer tokens to a receiver in a way that masks the identity of the receiver, while also ensuring that only the receiver can access and spend the tokens.

First, the sender obtains the public key of the receiver and randomly generates an ephemeral key pair. The sender then publishes the ephemeral public key. Both parties can now compute a shared secret via the Diffie-Hellman key exchange, which is established between the receiver's public key and the ephemeral key, followed by hashing.

The stealth address is formulated by combining the receiver's public key and the public key of the shared secret. The corresponding stealth private key can only be calculated by the receiver, as it combines the shared secret and the receiver's private key.

caption

c. Stealth address validator plugin​

The Stealth Address Validator Plugin are employed to mask the identity of smart account owners. This results in the decoupling of the visible link between smart account owners and their respective smart accounts, thereby ensuring a higher degree of privacy.

struct StealthValidatorStorage {
address stealthAddress;
}

function validateUserOp(UserOperation calldata _userOp, bytes32 _userOpHash, uint256)
external
payable
override
returns (ValidationData validationData)
{
address stealthAddress = stealthValidatorStorage[_userOp.sender].stealthAddress;
bytes32 hash = ECDSA.toEthSignedMessageHash(_userOpHash);
if (stealthAddress == ECDSA.recover(hash, _userOp.signature)) {
return ValidationData.wrap(0);
}
if (stealthAddress != ECDSA.recover(_userOpHash, _userOp.signature)) {
return SIG_VALIDATION_FAILED;
}
}

d. Aggregate signature​

Stealth addresses offer an elegant solution to preserve user privacy. However, the practical limitations of generating shared secrets and corresponding private keys within existing wallet UIs present a challenge. To overcome this, we propose using aggregate signatures that can be verified by the contract.

1. Shared secret​

The shared secret, denoted by ss, can be generated using the ephemeral public key and the user's private key, or vice versa:

privshared=Hash(bR)=Hash(rB)priv_{shared}=Hash(bR)=Hash(rB)

In standard stealth address implementations, this usually requires manual management of private keys by users. However, ephemeral private keys could be stored when creating the smart account, simplifying shared secret retrieval within existing wallet UIs.

2. Private key of stealth address​

The private key of the stealth address, denoted as privstealthpriv_{stealth}, is calculated as:

privstealth=privshared+bpriv_{stealth}=priv_{shared}+b, where ss is the shared secret and bb is the private key of the owner.

The challenge we face is that we're unable to alter the private key within the wallet's user interface. Nevertheless, we do have the latitude to make subtle adjustments in the way signatures are generated and verified, which could provide us with a viable path forward.

Here's original ECDSA siging

ECDSA Signing​

Given a private key: privKeyprivKey, and a message: mm

  1. Calculate the message hash: h=hash(m)h=hash(m)
  2. Generate a random number kk
  3. Calculate R=kβˆ—GR=k*G and take its x-coordinate r=R.xr=R.x
  4. Calculate s=kβˆ’1βˆ—(h+rβˆ—privKey)mod  ns=k^{-1}*(h+r*privKey)\mod n
  5. The signature is (r,s)(r,s)

ECDSA Verifying​

  1. Calculate the inverse of signature s: s1=sβˆ’1mod  ns_1=s^{-1}\mod n
  2. Calculate Rβ€²=(hβˆ—s1)βˆ—G+(rβˆ—s1)βˆ—pubkeyR'=(h*s_1)*G+(r*s_1)*pubkey, and take its x-coordinate r'=R'.x
  3. The result is r==rβ€²r==r'

We propose an adjustment to the signing and verification steps to facilitate stealth address usage:

Aggregate ECDSA Signing​

Given private key of owner: privownerpriv_{owner}, shared secret key: privsharedpriv_{shared} and message: mm

  1. Perform step 1 - 4 as in ECDSA signing using privownerpriv_{owner}
  2. Calculate the aggregate signature sβ€²=s(h+rβˆ—privshared)mod  ns'=s(h+r*priv_{shared})\mod n
  3. The aggregate signature is (r,sβ€²)(r,s')

Aggregate ECDSA Verifying​

The aggregated signature

sβ€²=s(h+rβˆ—privshared)=kβˆ’1(h+rβˆ—privowner)(h+rβˆ—privshared)=kβˆ’1[h2+hrβˆ—(privowner+privshared)+r2βˆ—privownerβˆ—privshared]\begin{equation} \begin{split} s' &=s(h+r*priv_{shared}) \\ &=k^{-1}(h+r*priv_{owner})(h+r*priv_{shared}) \\ &=k^{-1}[h^2+hr*(priv_{owner}+priv_{shared})+r^2*priv_{owner}*priv_{shared}] \end{split} \end{equation}

We notice that:

pubstealth=Gβˆ—(privowner+privshared)dhowner_shared=Gβˆ—privownerβˆ—privsharedpub_{stealth}=G*(priv_{owner}+priv_{shared})\\ dh_{owner\_shared}=G*{priv_{owner}*priv_{shared}}

We can thus verify the aggregate signature by:

  1. Calculate the inverse of aggregate signature s1=sβ€²βˆ’1mod  ns_1=s'^{-1}\mod n
  2. Calculate Rβ€²R' and take its x-coordinate rβ€²=Rβ€².xr'=R'.xRβ€²=(h2βˆ—s1)βˆ—G+(hβˆ—rβˆ—s1)βˆ—pubkeystealth+(r2βˆ—s)βˆ—dhowner_sharedR'=(h^2*s_1)*G+(h*r*s_1)*pubkey_{stealth}+(r^2*s)*dh_{owner\_shared}
  3. The result is r==rβ€²r==r'

V. Workflow​

In this section, we outline the complete workflow for creating a smart account with the Stealth Address Account Abstraction (AA) Plugin.

a. Create stealth smart account​

  1. Generate Ephemeral Key Pair: Start by generating a random ephemeral key rr
  2. Compute Shared Secret: Use the random ephemeral private key rr and the owner's public key BB to compute the Diffie-Hellman shared secret, ss, through hashing: s=Hash(rB)s=Hash(rB)
  3. Compute Stealth Public Key and Address: Calculate the stealth public key by adding the public keys of the owner and the shared secret: pubstealth=pubowner+pubsharedpub_{stealth}=pub_{owner}+pub_{shared} Then calculate the stealth address: addrstealth=bytes20(keccak256(pubstealth)addr_{stealth}=bytes20(keccak256(pub_{stealth})
  4. Compute Diffie-Hellman Key: Now calculate the Diffie-Hellman key between the owner and the shared secret: dhowner_shared=pubownerβˆ—sdh_{owner\_shared}=pub_{owner}*s
  5. Call CreateAccount: Finally, call the createAccount function in the Smart Account Factory Contract.
caption
Workflow from Vitalik's Post

Within the framework of our validator, we'll securely store the stealth address, stealth public key, and the Diffie-Hellman key. Importantly, to bolster user privacy, the owner's address will not be stored in the validator. This design ensures that there is no explicit connection between the smart account and its respective owner.

struct StealthAddressValidatorStorage {
uint256 stealthPubkey;
uint256 dhkey;
address stealthAddress;
uint8 stealthPubkeyPrefix;
uint8 dhkeyPrefix;
}

b. Verify signature​

The signature in the userOp is constructed with the signature or aggregated signature generated by stealth smart account owner with the 1 Byte prefix mode.

Mode 0: ECDSA Verification If the mode is set to 0, the signature will be verified using standard ECDSA verification logic that matches the stealth address's private key. In other words, the signature is considered valid if it can be mathematically confirmed to have been generated by the stealth address's private key.

Mode 1: Aggregated Signature Verification If the mode is different from 0, the signature will undergo aggregated signature verification as detailed in the previously discussed procedure for Aggregate ECDSA Verifying.

caption
Signature of stealth smart account

VI. What's next​

ERC-5564 Compatibility and Stealth Address Scanning

While our stealth smart accounts are self-created, eliminating the need for separate viewing and spending keys used in standard stealth address implementations, our aim is to ensure compatibility with ERC-5564. This will enable senders to transfer tokens to recipients while maintaining the recipient's anonymity.

One of the issues widely discussed with stealth addresses is stealth address scanning overhead. It's worth exploring an efficient solution to minimize the cost in the realm of smart account.

Enhancing privacy through Account Abstraction Since the stealth smart accounts are essentially smart contract wallets, they offer a greater degree of flexibility. For example, we could use a paymaster to sponsor userOps in such a way that the link between the stealth smart account and its owner remains concealed.