Skip to content

Add Keccak-256 to sha3 module and experimental hidden_pk circuit#152

Open
Mahdi171 wants to merge 6 commits intogoogle:mainfrom
SoundnessLabs:hiddenpk-clean
Open

Add Keccak-256 to sha3 module and experimental hidden_pk circuit#152
Mahdi171 wants to merge 6 commits intogoogle:mainfrom
SoundnessLabs:hiddenpk-clean

Conversation

@Mahdi171
Copy link
Copy Markdown

@Mahdi171 Mahdi171 commented May 4, 2026

This PR adds Keccak-256 support to the sha3 module and a new experimental hidden_pk circuit under circuits/hidden_pk/. Both pieces are independent of the existing mdoc and anoncred circuits.

Motivation

The hidden_pk circuit is the proving step for a quantum-resistant Ethereum wallet construction ([ethresear.ch link]): an existing Ethereum EOA delegates via EIP-7702 to a contract that authorizes transactions only against a ZK proof under a hidden public key, so the public key never appears onchain in steady state. Hash preimage resistance survives quantum attacks, so the account stays quantum-safe regardless of how many transactions it processes. There is live demo here.
The circuit is also reusable for any ECDSA-ZK application that needs the public key kept private and an Ethereum-address-shaped public input. The Keccak-256 addition is independent and useful on its own for any libzk caller working with Ethereum hashes.

Keccak-256

Ethereum uses Keccak-256 for address derivation and the keccak EVM opcode. It differs from SHA3-256 only in the padding byte (0x01 vs 0x06); the underlying Keccak-f[1600] permutation is identical. The existing SHA3 machinery already handles the permutation in reference, witness, and circuit form, so this addition is small:

  • sha3_reference.{h,cc}: keccak256Hash (32-byte output, 0x01 padding)
  • sha3_witness.{h,cc}: compute_witness_keccak256 for block witnesses
  • sha3_circuit.h: assert_keccak256 circuit method
  • sha3_reference_test.cc: known vectors for keccak256(""), keccak256("abc"), and an Ethereum address derivation sanity check
  • sha3_circuit_test.cc: AssertKeccak256EthereumAddress end-to-end test

hidden_pk circuit

The circuit proves the relation:

R = { (eth_addr, e) ; (pk, sig) :
        keccak256(pkx_bytes || pky_bytes)[12:32] == eth_addr
      AND ECDSA_verify_secp256k1(pk, sig, e) == true }

Public inputs: the 20-byte Ethereum address and the message hash e. Private witnesses: pk = (pkx, pky) and sig = (r, s).

A verifier learns that some valid secp256k1 ECDSA signature exists under a key whose Ethereum address is eth_addr, without seeing the key or the signature. Revealing (r, s) together with e is enough to recover pk via ecrecover, which is why both stay hidden.

Files added under lib/circuits/hidden_pk/:

  • hidden_pk_circuit.h: composes ECDSA verify with Keccak-256 over pkx_bytes || pky_bytes (64 bytes, one Keccak block) and equates digest bytes [12:32] with the public eth_addr
  • hidden_pk_witness.h: witness computation from (pk, e, r, s)
  • hidden_pk_test.cc: ZK prove/verify test and BM_HiddenPKProver benchmark
  • CMakeLists.txt

Tests

# Full test suite (circuit size + ZK prove/verify)
./clang-build-release/circuits/hidden_pk/hidden_pk_test

# Circuit size only (~300ms, mostly compilation)
./clang-build-release/circuits/hidden_pk/hidden_pk_test --gtest_filter=HiddenPK.CircuitSize

# Full ZK prove + verify with timing breakdown
./clang-build-release/circuits/hidden_pk/hidden_pk_test --gtest_filter=HiddenPK.ZkProverVerifier

# Prover benchmark (circuit compiled outside the loop)
./clang-build-release/circuits/hidden_pk/hidden_pk_test --benchmark_filter=BM_HiddenPKProver

Notes

  • Tests cover the happy path. Negative tests (bad signature, mismatched address) are planned as a follow-up.
  • hidden_pk is registered under the existing "experiments and tests" comment in lib/CMakeLists.txt. No production code depends on it.
  • The standard ECDSA verifier circuit is used. A designated-prover variant (the prover holds sk, so the two variable-base MSMs collapse to fixed-base) would cut constraints roughly 3-5x and proof size to ~50-80 KB. Left as future work.

@google-cla
Copy link
Copy Markdown

google-cla Bot commented May 4, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant