Semaphore V4Trusted Setup ceremony is open for contributions until July 10.

Semaphore: Anonymous interactions

Using zero knowledge, Semaphore allows users to prove their membership of a group and send signals such as votes or endorsements without revealing their original identity. The goal is to make Semaphore a standard for anonymous signaling and group membership proving.



To reach a very large group of developers, a protocol needs to be extremely user-friendly, understandable and simple.


Achieve an excellent balance between simplicity and functionality through modularity, autonomy, and interoperability.


A protocol must not only work, it must also be extremely efficient if the goal is to support privacy by default for everyone.

Main focus

Developer experience

Enabling developers to focus on innovation by simplifying complexities while supporting diverse use cases.


Empowering individuals with knowledge, resources, and support, ensuring they're equipped to innovate and solve challenges.


Fostering spaces where collaboration thrives, ideas flourish, and diverse voices are celebrated.

Semaphore identities

A Semaphore identity is an EdDSA key-pair plus the commitment (i.e. the hash of the public key), which is used as the public value of the Semaphore group members.

Create Semaphore identities

import { Identity } from "@semaphore-protocol/identity" // Random identity. const identity1 = new Identity() // Passing a secret. const identity2 = new Identity("secret")

Private value

The private key is a secret that identity owners must keep private. It can either be generated randomly or passed as a parameter.

Public values

Semaphore uses the Poseidon hash function to derive the identity commitment from the identity public key. Identity commitments can be made public, similarly to Ethereum addresses.

Storing identities

Building a system to save or recover secret values of Semaphore identities is nontrivial. You may choose to delegate such functionality, for example by using a signature as a secret.

Semaphore groups

Semaphore groups are binary incremental Merkle trees that store the public identity commitment of each member.

Create Semaphore groups

import { Group } from "@semaphore-protocol/group" const members = [identity1.commitment, identity2.commitment] const group = new Group(members)

Merkle trees

Each leaf contains an identity commitment for a user. The structure of Merkle trees ensures that it can be efficiently proved that an identity commitment is a member of the group.

Types of groups

Groups can be created and managed in a decentralized fashion with Semaphore contracts or off-chain with the JavaScript libraries.

Group management

Users could join and leave groups by themselves, or an admin could add and remove them. Admins can be centralized authorities, Ethereum accounts, multi-sig wallets or smart contracts.

Semaphore proofs

Semaphore group members can prove that they are part of a group and send anonymous messages.

Generate Semaphore proofs

import { generateProof, verifyProof } from "@semaphore-protocol/proof" const scope = "Semaphore" const message = "Hello world" const proof = await generateProof(identity1, group, scope, message) await verifyProof(proof)


Only users who are part of a group can generate a valid proof for that group.


Group users can anonymously share messages such as votes or endorsements without revealing their original identity.

Proof verification

Semaphore proofs can be verified both on-chain with the Semaphore contracts, or off-chain with the JavaScript libraries.

Semaphore logo

Give feedback about the website

Copyright © 2024 Ethereum Foundation