Semaphore Protocol

Semaphore is a zero-knowledge protocol developed by Koh Wei Jie (and later maintained by the Privacy and Scaling Explorations team at Ethereum Foundation) that enables anonymous signaling with group membership proofs. The core primitive: a user generates an identity (a secret Ed25519-like keypair), registers their identity commitment (a public hash of their identity) into a group’s Merkle tree, and later signals without revealing which group member they are — while the nullifier mechanism prevents them from signaling twice for the same external context (preventing double-voting). Semaphore serves as infrastructure for higher-level applications: anonymous voting systems (MACI), anonymous account recovery, privacy-preserving credentials, and whistleblowing platforms. The protocol is implemented as Circom circuits (~32,768 constraints), a Solidity smart contract for on-chain group management, and a JavaScript/TypeScript SDK for easy integration. Semaphore v3 (2023) significantly reduced circuit complexity and improved developer ergonomics.


Core Protocol

Three Phases:

1. Identity Generation (off-chain, user’s device):

“`

identity_secret = randomly generated

identity_nullifier = hash(identity_secret, 0)

identity_commitment = hash(identity_nullifier, hash(identity_secret))

“`

2. Group Registration (on-chain):

  • User (or admin) adds identity_commitment to group’s Merkle tree
  • Group tree stored in Semaphore contract
  • Anyone can verify tree membership (commitment is public; identity is not)

3. Signaling (ZK proof off-chain, verification on-chain):

“`

Proof proves:

  • I know secret corresponding to some commitment in the group tree
    signal_hash = hash(my_signal)
    nullifier_hash = hash(identity_nullifier, external_nullifier)

“`

Nullifier prevents double-signaling: Same external_nullifier (e.g., “vote round 1”) + same identity always produces same nullifier_hash → contract rejects if nullifier_hash already used.


Applications Built on Semaphore

Application Use Case
MACI Anti-bribery voting with Semaphore identity
Crypt-Keeper Browser ZK identity wallet
Privacy-preserving DAO Anonymous voting for sensitive governance
Zupass Event attendance credential (Zuzalu)
Worldcoin Basis for World ID’s anonymous action scheme

Signal Types

A “signal” in Semaphore can be anything:

  • A vote: signal = keccak256("yes_on_proposal_3")
  • A message: signal = hash(message_content)
  • An attestation: signal = hash(credential_claim)
  • Any arbitrary data

Related Terms


Sources

  1. “Semaphore: A Privacy Gadget Built on Ethereum” — Koh Wei Jie / Ethereum Foundation (2019). The original Semaphore paper — introducing the group membership signal primitive, nutlifier design, circuit construction, and example applications.
  1. “MACI: Minimal Anti-Collusion Infrastructure for Voting” — Barry Whitehat / Ethereum Foundation (2019). Introduction of MACI — an application layer built on Semaphore-like ZK identity that prevents voter bribery and coercion in on-chain governance by making votes cryptographically unverifiable to third parties.
  1. “Zupass: ZK Event Credentials and Semaphore Identity” — PSE / 0xPARC (2023). Documentation of Zupass — a ZK identity and credential wallet built on Semaphore, developed for the Zuzalu event — enabling attendees to prove event membership and unlock features without revealing their specific identity.
  1. “Semaphore v3: Upgraded Protocol and Developer Experience” — PSE (Privacy and Scaling Explorations / Ethereum Foundation) (2023). Documentation of Semaphore v3 — the refactored version with redesigned circuits (Circom 2.0-based), improved SDK, reduced constraint count, and new features for large-scale group management.
  1. “ZK Identity Primitives: From Semaphore to World ID” — Worldcoin Foundation (2023). Analysis of the evolution from Semaphore’s group membership primitive to more complex ZK identity systems — specifically how Worldcoin’s World ID builds Sybil resistance and unique humanity verification on top of Semaphore-compatible primitives.