Published in


Anonymous Participation (e.g. voting) using BrightID


An application using BrightID can choose at most one of the following for its users.

1. Anonymity within a group of participants. (No one — not even BrightID node operators — knows which BrightID maps to which participant.)

2. The ability to re-register with an application; i.e. if an account becomes unrecoverable, a user can register to use the application again. To avoid abuse, there is a permanent link between the lost account and the new account.

In this article, we’ll focus on the first option and show how to use BrightID with applications that provide anonymity within a set of participants. In these cases, participants perform one or more unconnected actions (for example, votes), and there’s no need for an “account” or “profile” to provide a history of connected actions. In such cases, the possibility of re-registering with a new account connected to one’s previous account isn’t useful — and by disallowing it, anonymous participation becomes possible.

The solution uses Ethereum and a privacy mixer that accepts custom smart-contract-based (e.g. ERC-20) tokens. The use of MACI to provide privacy and collusion resistance is briefly discussed.

BrightID nodes do not store any personally identifiable information, only unique identifiers (i.e. BrightIDs). This article shows how to keep users anonymous even if third-party applications leak information.

Setting up Anonymous Participation

Create a Context

An application can have its own context with its own set of unique users, or it can share its context (and user registry — see below) with other applications.

To create a context, an application chooses which BrightID nodes will administer the context and provides them with the following:

  • Name of the context
  • linkAESKey (32 bytes). Used by nodes serving the context to privately share information with each other when a user links their BrightID to a contextId.

Create a User Registry

All users that will take part in anonymous actions within the new context should now link their BrightIDs to a previously unused Ethereum address as the contextId. This is as simple as creating a deep-link of the formbrightid://link-verification/<node url>/<context>/<ethereum address> for users to open in their mobile browser. The link is stored on BrightID nodes serving the context.

Distribute Action Tokens

The context creator should create and deploy a smart contract that implements the IBrightID interface. We’ve provided an example smart contract. Users can submit signed verifications obtained from a BrightID node’s /verifications endpoint to the smart contract. If a submitted address hasn’t been used (i.e. there are no previous addresses in the signed array, and no matching address in the smart contract storage), an action token should be minted for that address.

Mix Action Tokens

Although contextIds provide a middle layer to limit the visibility of BrightIDs, there is still a privacy weakness: BrightID nodes serving the context know which BrightIDs correspond to the newly created Ethereum addresses (contextIds). If an action token holder were to now use their token, BrightID nodes serving the context would see which BrightID is associated with each action.

To strengthen the privacy further, the tokens should be sent through a mixer and received into fresh Ethereum addresses. Now users can complete actions — limited to one per unique human — without associating them (even indirectly) to a specific BrightID. Not even BrightID nodes serving the context can tell which BrightID is associated with an action; they only know the set of action-takers (i.e. which BrightID are registered in the context).

Reusing Action Tokens

An action token can be reused for multiple actions with the following caveats:

  • A user’s “unique” status in BrightID may have changed between actions. (They may have been flagged as “fake,” “duplicate,” or “deceased” and removed from their primary group.)
  • The actions of a single participant will be anonymously linked to each other unless a mixer is used between actions.
  • A user that loses access to their action token will be unable to participate until old action tokens are retired and new ones issued.

Collusion Resistance

Mixing action tokens helps with privacy within a set of participants, but is not immune to collusion (e.g. vote buying). MACI (Minimal Anti-Collusion Infrastructure) precludes many forms of vote buying by giving a person being bribed a way to generate fake proofs that are indistinguishable from real ones. Because of the possibility of receiving a fake proof, a briber can’t know whether or not a bribe succeeded.

MACI conceals the links between actions and actors using zero-knowledge proofs. It could therefore take the place of action tokens and mixers while providing extra defenses against collusion.

Thanks to Aleeza Howitt for the suggestion of using a privacy mixer to simplify the integration of zero-knowledge proofs, and to Barry Whitehat, Koh Wei Jie, and Vitalik Buterin for chats on privacy and MACI.


* BrightID
* Discord (chat)



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store