Post-Quantum Ethereum Wallets via Hidden Public Keys and EIP-7702 Delegation
Thanks to @gnosed for his contributions.
Any Ethereum EOA that has transacted once has its secp256k1 public key permanently on-chain, making it extractable by a quantum computer via Shor’s algorithm. We show how to retrofit any existing EOA to post-quantum security in a single EIP-7702 transaction, with no address change, no asset migration, and no consensus change. The EOA delegates execution to a GatedWallet contract that accepts only ZK proofs of ECDSA knowledge under a hidden public key. That key never appears on-chain.
Working implementation: longfellow-zk-hiddenpk.
Benchmarks: 87 ms prove / 65 ms verify / 226 KB proof on Apple M1.
This extends the 2022 post Quantum Proof Keypairs with ECDSA-ZK, which identified the right goal but left the delegation and verification flow open.
Why existing approaches fall short
| Approach | Address stable | No asset migration | No consensus change | PK never in mempool |
|---|---|---|---|---|
| Migrate to PQ address | No | No | No | Yes (pq-secure) |
| Ephemeral key rotation [1] | Yes | Yes | Yes | No |
| New PQ smart wallet | No | No | Yes | Yes |
| This work | Yes | Yes | Yes | Yes |
Ephemeral key rotation is the closest prior construction. Each rotation transaction broadcasts the current public key in the mempool, leaving a window where a CRQC can extract the private key. That window does not exist here.
Why not just switch to post-quantum signatures
Falcon, Dilithium (ML-DSA), and SPHINCS+ are the correct long-term answer. They are unavailable to most Ethereum wallets today.
The bottleneck is the infrastructure layer below the wallet software. Most institutional wallets run on HSMs or MPC protocols. Current-generation HSMs support ECDSA, RSA, and EdDSA only. The hardware refresh cycle runs two to five years. MPC wallets face the same problem: threshold ECDSA has audited production protocols (GG18, CGGMP21); threshold ML-DSA does not. On top of that, a PQ migration requires new address schemes, consensus changes, and a renegotiation of calldata economics for larger signatures (ML-DSA is 2.4-3.3 KB vs 65 bytes for ECDSA).
The hidden-PK construction does not replace ECDSA. It wraps it. The HSM or MPC layer continues running ECDSA internally. The ZK proof layer sits above it, in wallet software, and the on-chain verifier only sees a proof that ECDSA signing happened under a committed key. This is the fastest available path to quantum safety for MPC and HSM wallets in production today.
Construction
Setup. The user’s EOA A signs one EIP-7702 SetCode authorization pointing at a GatedWallet contract. This is the last time sk_A is used. The contract stores one value: pkHash_B = H(pkx_B || pky_B), where pk_B is the user’s new hidden keypair, generated off-chain and never broadcast.
(Note: the current implementation uses SHA-256 for pkHash_B because Longfellow-ZK does not yet support Keccak inside circuits. Adding Keccak to align with Ethereum’s address scheme is in progress.)
Steady state. For every subsequent transaction, the user’s wallet generates a ZK proof \pi on-device:
\exists\,(pk_B, r, s) \;\text{ s.t. }\; \mathrm{ECDSA.verify}(pk_B,\,(r,s),\,e) = 1 \;\wedge\; H(pk_B) = pkHash_B
where e = H(\mathtt{userOpHash} \;|\!|\; \mathtt{chainid} \;|\!|\; \mathtt{nonce}) binds the proof to this specific action. The proof goes into the ERC-4337 UserOperation signature field and is forwarded by a public bundler. GatedWallet.execute verifies and, on success, executes the action against addr_A’s assets.
contract GatedWallet {
bytes32 public immutable pkHash;
IZKVerifier public immutable zkVerifier;
uint256 public nonce;
function execute(
address to, uint256 value, bytes calldata data, bytes calldata proof
) external {
require(msg.sender == address(this), "self only"); // EIP-7702 idiom
bytes32 e = keccak256(abi.encode(keccak256(data), block.chainid, nonce));
require(zkVerifier.verify(proof, pkHash, e), "bad proof");
nonce++;
(bool ok,) = to.call{value: value}(data);
require(ok);
}
}
The msg.sender == address(this) guard is the standard EIP-7702 pattern: the EOA’s own signed transaction enters execute with msg.sender = addr_A = address(this). Any direct external call is rejected before reaching the ZK check.
Hybrid transition: dual-signature safety net
During an initial deployment period, a soundness bug in the circuit would be a critical risk. The GatedWallet can require both signatures simultaneously:
\text{authorize} \iff \underbrace{\mathrm{ECDSA.verify}(pk_1,\,sig_1,\,e)}_{\text{classical guard, } pk_1 \text{ exposed}} \;\wedge\; \underbrace{\mathrm{ZK.verify}(\pi,\,pkHash_2,\,e)}_{\text{hidden-key guard, PQ-safe}}
This gives independent protection against two failure modes. A quantum attacker who extracts sk_1 via Shor’s algorithm still cannot spend because pk_2 is hidden and Shor cannot be applied to it. A ZK soundness bug lets an attacker forge a proof, but they cannot produce a valid sig_1 without sk_1. Either guard defeats either failure.
After years of deployment and independent auditing, the ecrecover check is removed by a fresh EIP-7702 SetCode transaction pointing at a GatedWallet without the classical guard.
Proof system: why Ligero and not Groth16
Groth16 and KZG-PLONK rely on discrete log hardness of a structured reference string. They are not post-quantum sound. Ligero and WHIR reduce soundness to hash collision resistance and require no trusted setup. The current implementation uses Longfellow-ZK (C++, Google), a Ligero variant using CRT-based Reed-Solomon to handle secp256k1’s FFT-unfriendly field (v_2(p^2-1) = 5). An independent Rust port is at zk-cred-longfellow.
PSE’s zkID project is solving the same circuit primitives from the identity angle: ECDSA-ZK credentials for privacy-preserving identity on Ethereum. Their Circom circuits, on-chain verifiers, and mobile proving libraries are directly reusable for the hidden-PK wallet pattern. The maturity of that stack is a large part of why this construction is deployable today.
Designated-prover ECDSA optimization
Standard ECDSA verification requires:
R = u_1 \cdot G + u_2 \cdot pk, \quad u_1 = e \cdot s^{-1}, \quad u_2 = r \cdot s^{-1}
Two variable-base scalar multiplications, approximately 70% of current circuit constraints.
Because the prover generated the signature and holds sk and the nonce k, they can prove the signing equations directly:
pk = sk \cdot G, \qquad r = (k \cdot G).x, \qquad s = k^{-1}(e + r \cdot sk) \bmod n
Two fixed-base scalar multiplications instead (the base point G is constant, so precomputed tables cut constraint count by 4-8x), plus cheap modular arithmetic. Estimated 3-5x overall constraint reduction, bringing proof size from ~226 KB to ~50-80 KB and gas from ~3 M to ~800 K without any protocol changes.
One important point: dropping ECDSA entirely and proving only pk = sk \cdot G does not work. That statement has no binding to any transaction. ECDSA is the transaction integrity mechanism: (r, s) commits to e = H(\mathtt{userOpHash} \;|\!|\; \mathtt{chainid} \;|\!|\; \mathtt{nonce}), making each proof valid for exactly one action. The designated-prover optimization changes only the circuit path; it preserves the transaction binding.
Benchmarks
Measured on Apple M1, single core, release build, kLigeroRate = 7, kLigeroNreq = 132.
| Metric | Value |
|---|---|
| Circuit inputs | 7,694 |
| Public inputs | 258 |
| Total prove time | ~87 ms |
| Verification time | ~65 ms |
| Proof size | 226 KB |
| On-chain gas | ~3 M |
Proof size breakdown: 32 B Merkle root, 17.6 KB sumcheck, 213.9 KB RS column openings (132 columns). On L2s with calldata compression, gas drops 10-50x. With the designated-prover optimization, ~800 K without any protocol change.
Open questions
- Keccak in-circuit. Adding Keccak to Longfellow removes the SHA-256 / Keccak mismatch with Ethereum’s address scheme.
- Designated-prover circuit implementation. The constraint reduction estimate needs an actual constraint count for fixed-base MSM under CRT-Reed-Solomon.
- WHIR backend. WHIR offers better proof sizes at equivalent security. Benchmarking the ECDSA circuit with WHIR is a direct next step.
- Proof aggregation. Multiple users spending in the same block could share amortized calldata overhead. Ligero’s linear structure supports batch verification.
References
- mvicari et al., Achieving Quantum Safety Through Ephemeral Key Pairs and Account Abstraction, ethresear.ch, 2026.
- Quantum Proof Keypairs with ECDSA-ZK, ethresear.ch, 2022.
- Frigo and Shelat, Anonymous Credentials from ECDSA, IACR ePrint 2024/2010.
- Gaborit et al., WHIR: Reed-Solomon Proximity Testing with Super-Fast Verification, IACR ePrint 2024/1586.
- EIP-7702: Set EOA Account Code
- ERC-4337: Account Abstraction Using Alt Mempool
- PSE zkID
- longfellow-zk-hiddenpk (this work)
- Longfellow-ZK C++ reference
- Longfellow-ZK Rust port (independent)

