Semaphore V2 is Live! - Privacy & Scaling Explorations

Originally published on Jul 6, 2022:

Semaphore is a zero-knowledge protocol that lets Ethereum users prove their membership of a group and send signals such as votes or endorsements without revealing their original identity. The ability to do these two simple things anonymously opens up a world of possibilities — some of which are already being worked on, some we can’t wait to see explored and hopefully some we haven’t even thought of yet :D.

Semaphore is not a user-facing application, but is designed to provide powerful and simple tools for Ethereum devs to build dapps with private credentials. It was first proposed by Kobi Gurkan, Koh Wei Jie and Barry Whitehat, and V1 was released in 2019.

We’re excited to share that Semaphore V2 has just been released with lots of improvements to the protocol and developer tooling, thanks to extensive contributions by Cedoor and Andrija Novakovic. Contracts have been deployed to Kovan, Goerli and Arbitrum.

How does Semaphore work?

Semaphore provides three main functions — creating private identities, adding identities to groups and sending anonymous signals.


There are several public and private values associated with a user’s identity:

  • Identity trapdoor: a secret value that can be used to derive a public value, but not vice versa — similar to how you can derive an Ethereum address from a private key, but you can’t determine the private key from the public address.
  • **Identity nullifier: **a secret value which is hashed with a public value to detect double signaling while preserving anonymity.
  • **Identity secret: **a secret value representing the user’s identity, derived by hashing together the identity trapdoor and identity nullifier.
  • Identity commitment: a public value which is a hash of the identity secret.

Generating a Semaphore identity

The identity trapdoor, identity nullifier and identity secret are generated by the user when they create their Semaphore identity. These values are never revealed on-chain; instead, they are used to create zero knowledge proofs so the user can prove things about themselves publicly without revealing their identity.


Groups are an important concept when we speak about privacy and zero knowledge technologies. They can be thought of as anonymity sets, and are a way to establish necessary trust between a set of participants while letting users keep control over how their identities are stored and used.

In Semaphore, a “group” can mean many things. It might be people who have an account on some platform, employees of a specific company, voters in an election — essentially, any set of individuals who are eligible to participate in something.

For example, you might require an email address from a particular university in order to join a group. Rather than storing that email in a database and using it to log in, tying all of their activity to their identity, a user proves only that they have the credential. There is no stored record of which email address was used. Members of the group can be confident that they are interacting with fellow students or colleagues, even though individual identities are unknown.

Adding members to a Semaphore group

When a user joins a group, their public identity commitment is added to that group’s Merkle tree. This lets the protocol check that the user is in the group and is therefore eligible to send signals, without seeing their identity.

There’s no single approach to groups. Semaphore uses incremental binary Merkle trees, Poseidon hashes and Semaphore identity commitments as tree leaves (more on that later), but different types of Merkle trees, hash functions, or leaf values could theoretically be used. The goal is that Semaphore groups can act as a standard to improve composability and interoperability between protocols and applications in the Ethereum ecosystem.


Signals are signed messages which are broadcast on-chain. They contain an endorsement of some data, such as a vote, along with proofs that:

  • The user is a member of the group, i.e. the sender belongs to a valid Merkle tree
  • The same user created the signal and the proof.

Each signal also contains a nullifier, which is a hash of the identity nullifier and a public external nullifier. If the nullifier has been used before, the protocol knows that the user has signaled more than once.

New in V2

The recently-released V2 introduced a number of changes and improvements, including:

  • Circuits have been simplified: it is no longer necessary to have an EdDSA private key, enabling a simpler circuit and more efficient zero-knowledge proof generation.
  • The hash function used for identity commitments and Merkle trees moved from MiMC to Poseidon, which has some security advantages, roughly halves the proving time and improves gas efficiency.
  • Contracts have been modularized, giving developers more freedom to use what they need and choose between different implementation levels.
  • Three new JavaScript libraries were created: Semaphore identities, Semaphore groups, Zero-knowledge proofs
  • An audit of Semaphore v2 was completed in May.

Semaphore in Action

There are several apps already using Semaphore.

  • Unirep is a social media platform that uses anonymous reputation. Semaphore identities allow users to join with a unique identity, prove they’re eligible to post or give feedback, and use pseudonymous “personas” while choosing how much of their stable identity they reveal in any given interaction.
  • Interep uses zero knowledge proofs to verify reputation from an existing account such as Github or Twitter without retaining any identifying information. Users’ Semaphore identities are added to a “group” according to the strength of their imported reputation. Interep group membership can then be used as an access point for apps and services that need proof of humanity for sybil protection.
  • is a decentralized social network based on Ethereum and ENS. It uses Semaphore for anonymous user identities.

What’s inside?

On a more technical level, Semaphore combines zero knowledge proofs and Ethereum smart contracts.


Zero knowledge proofs are the key to Semaphore’s ability to provide sybil- and spam-resistant private credentials. Every signal sent by a user contains proofs of the user’s group membership and the validity of the signal. Proofs are generated off-chain, and can be verified either on-chain or off-chain.

Semaphore proof

The secure parameters for these proofs were generated in a trusted setup ceremony which was recently completed with over 300 participants.


The circuit structures how the ZKP inputs and outputs are generated, hashed and verified. It has three main components:

  • **Proof of membership: **An identity commitment is generated from the hash of the identity trapdoor and identity nullifier, then verifies the membership proof against the Merkle root and identity commitment.
  • **Nullifier hash: **nullifier hashes are saved in a Semaphore smart contract, so that the smart contract itself can reject a proof with an already used nullifier hash. The circuit hashes the identity nullifier and the external nullifier, then checks that it matches the given nullifier hash.
  • **Signal: **The circuit calculates a dummy square of the signal hash to prevent any tampering with the proof; if the public input changes then verification will fail.

Semaphore circuit

Smart Contracts

Semaphore includes three types of contracts:

  • **Base contracts provide the core functions. **`SemaphoreCore.sol` contains the functions to verify Semaphore proofs and to save the nullifier hash in order to avoid double signaling; `SemaphoreGroups.sol` contains the functions to create groups and add or remove members.
  • **Extension contracts **contain application logic for specific use-cases. `SemaphoreVoting.sol` contains essential functions to create polls, add voters and cast votes anonymously; `SemaphoreWhistleblowing.sol` contains essential functions to create entities, add whistleblowers and publish leaks anonymously. More extensions will be added in the future.
  • **Verifier contracts **verify Semaphore proofs generated with a specific tree depth. For example `Verifier20.sol` can verify proofs where the depth of the tree is 20, which means that the group used for those proofs can have a maximum of 2 ^20=1048576 members. A developer can choose to use a pre-deployed verifier or deploy their own, with depth ranging from 16–32.

What’s next?

Semaphore will continue to be developed and improved over time. Some potential future directions include:

Improving the developer experience:

  • Admin dashboard and APIs to manage zero-knowledge groups with a cloud or self-hosted infrastructure
  • Special contracts to allow only qualified users to join specific Semaphore groups (e.g. contract to allow only eth users with POAP to join the ‘poap’ group).
  • Improve current extension contracts and add new use cases.

Maturing the protocol:

  • Investigate plonkish circuits and other proving systems
  • Support proof aggregation

How to get involved

Semaphore is a project by and for the Ethereum community, and we welcome all kinds of contributions. You can find guidelines for contributing code on this page.

If you want to experiment with Semaphore, the Quick Setup guide and Semaphore Boilerplate are great places to start. Feel free to get in touch with any questions or suggestions, or just to tell us about your experience!

We would also love to hear from developers who are interested in integrating Semaphore into new or existing dapps. Let us know what you’re working on by opening an issue, or get in touch through the Semaphore Telegram group or the PSE Discord.

Subscribe to Privacy and Scaling Explorations
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
This entry has been permanently stored onchain and signed by its creator.