mirror of
https://github.com/semaphore-protocol/semaphore.git
synced 2026-01-10 07:08:17 -05:00
147 lines
4.4 KiB
Plaintext
147 lines
4.4 KiB
Plaintext
---
|
|
sidebar_position: 1
|
|
title: Identities
|
|
---
|
|
|
|
import Tabs from "@theme/Tabs"
|
|
import TabItem from "@theme/TabItem"
|
|
|
|
# Semaphore identities
|
|
|
|
In order to join a [Semaphore group](/glossary#group), a user must first create a [Semaphore identity](/glossary#identity).
|
|
A Semaphore identity contains three values generated with the identity:
|
|
|
|
- Private key
|
|
- Public key
|
|
- Commitment
|
|
|
|
To use and verify the identity, the identity owner (user) must know its private key.
|
|
To prevent fraud, the owner should keep their private key secret.
|
|
|
|
## Install package
|
|
|
|
In your code, use the [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity) package to manage Semaphore identities.
|
|
|
|
<Tabs
|
|
defaultValue="npm"
|
|
groupId="package-managers"
|
|
values={[
|
|
{label: 'npm', value: 'npm'},
|
|
{label: 'Yarn', value: 'yarn'},
|
|
{label: 'pnpm', value: 'pnpm'}
|
|
]}
|
|
>
|
|
<TabItem value="npm">
|
|
```bash
|
|
npm install @semaphore-protocol/identity
|
|
```
|
|
</TabItem>
|
|
|
|
<TabItem value="yarn">
|
|
```bash
|
|
yarn add @semaphore-protocol/identity
|
|
```
|
|
</TabItem>
|
|
|
|
<TabItem value="pnpm">
|
|
```bash
|
|
pnpm add @semaphore-protocol/identity
|
|
```
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
:::info
|
|
Semaphore also provides `@semaphore-protocol/core`, which includes the functions of the following core packages: `@semaphore-protocol/identity`, `@semaphore-protocol/group`, `@semaphore-protocol/proof`.
|
|
:::
|
|
|
|
## Create identities
|
|
|
|
### Create random identities
|
|
|
|
To create a random identity, instantiate `Identity` without any parameters. For example:
|
|
|
|
```ts
|
|
import { Identity } from "@semaphore-protocol/identity"
|
|
|
|
const { privateKey, publicKey, commitment } = new Identity()
|
|
```
|
|
|
|
The new identity contains your private key, your public key, and its associated commitment, which serves as a public representation of the identity (similar to an Ethereum address).
|
|
|
|
### Create deterministic identities
|
|
|
|
If you pass a previously used private key or any secret value that acts as your private key as parameter, you can deterministically generate a Semaphore identity.
|
|
|
|
```ts
|
|
const identity1 = new Identity(privateKey)
|
|
// or
|
|
const identity2 = new Identity("secret-value")
|
|
```
|
|
|
|
:::tip
|
|
Building a system to save or recover secret values of Semaphore identities is nontrivial.
|
|
You may choose to delegate such functionality to existing wallets such as Metamask. For example:
|
|
|
|
1. In Metamask, a user signs a message with the private key of their Ethereum account.
|
|
2. In your application, the user creates a deterministic identity with the signed message that acts as your Semaphore private key.
|
|
3. The user can now recreate their Semaphore identity whenever they want by signing the same message with their Ethereum account in Metamask.
|
|
:::
|
|
|
|
:::warning Privacy risk
|
|
If a user signs the **same message** on multiple websites using MetaMask, all those websites will be able to **generate the same Semaphore identity**. This undermines anonymity and may allow third parties to **link identities across platforms** or even **gain control over a user's identity**.\
|
|
To mitigate this, encourage users to sign **unique messages per application** or implement safeguards that detect and warn about reuse.
|
|
:::
|
|
|
|
## Sign and verify messages
|
|
|
|
Semaphore V4 uses asymmetric cryptography and in particular EdDSA to generate the identity keys. It is therefore also possible to sign messages and verify their signatures.
|
|
|
|
### Sign a message
|
|
|
|
Any Semaphore identity can sign a message by simply passing a string, number or buffer.
|
|
|
|
```ts
|
|
const message = "Hello World"
|
|
|
|
const signature = identity1.signMessage(message)
|
|
```
|
|
|
|
### Verify a signature
|
|
|
|
After a message is signed, anyone can verify the signature using the message itself, the signature, and the signer's public key.
|
|
|
|
```ts
|
|
// Static method.
|
|
Identity.verifySignature(message, signature, identity1.publicKey)
|
|
```
|
|
|
|
## Export and import an identity
|
|
|
|
A Semaphore Identity can be exported and then imported later for reuse.
|
|
|
|
### Export an identity
|
|
|
|
Returns the private key encoded as a base64 string.
|
|
|
|
```ts
|
|
import { Identity } from "@semaphore-protocol/identity"
|
|
|
|
const identity = new Identity()
|
|
|
|
const privateKey = identity.export()
|
|
```
|
|
|
|
### Import an identity
|
|
|
|
Returns a Semaphore identity based on a private key encoded as a base64 string.
|
|
|
|
```ts
|
|
import { Identity } from "@semaphore-protocol/identity"
|
|
|
|
const identity = new Identity()
|
|
|
|
const privateKey = identity.export()
|
|
|
|
const identity2 = Identity.import(privateKey)
|
|
```
|