# Overview

<figure><img src="/files/bKOLTLhlAhiyozQrZwnV" alt=""><figcaption></figcaption></figure>

This documentation contains everything you need to get started using Proof of Passport.

### Common use cases for Proof of Passport:

* **Airdrop protection:** Protect a token distribution from bots
* **Social media:** Add humanity checks to user's profiles
* **Quadratic funding:** Prevent farmers from skewing rewards
* **Wallet recovery:** Safeguard assets using IDs as recovery sources
* **Sanction list checking:** Check users are not on sanctioned entity lists.&#x20;

{% hint style="info" %}
Proof of Passport is still in beta. [Contact us](https://t.me/FlorentTavernier) if you have questions.
{% endhint %}


# Quickstart

To implement OpenPassport in your app, you need to implement it in both your front-end and back-end. The front-end will generate a QR code containing all the information relative to your app and what you are requesting users to disclose. The back-end will verify proofs and manage nullifiers.

🚧 Deeplinking is WIP. If you want to implement OpenPassport in a mobile application, please [contact us](https://t.me/openpassport).

### Implement `OpenPassportQRcode` in your front-end

#### Install dependencies

```bash
npm install @openpassport/core @openpassport/qrcode
```

#### Instantiate OpenPassportVerifier

```typescript
import { OpenPassportVerifier } from '@openpassport/core';

const scope = "myExampleApp";
const openPassportVerifier: OpenPassportVerifier = new OpenPassportVerifier('prove_offchain', scope);
```

`OpenPassportVerifier` requires two arguments: 'scope' and 'mode'.

* `scope` is simply an identifier for your app, choose a simple one in standard ASCII.
* `mode` corresponds to the behavior of the circuit.

Two modes are available according to where you want to verify the proof:

| Mode            | Usecases          |
| --------------- | ----------------- |
| prove\_offchain | web2 applications |
| prove\_onchain  | web3 dApps        |

Two more modes are available to enable full anonymity, cf. ...

#### Disclosing passport data

Call methods from openPassportVerifier to ask users to disclose specific passport data.

```typescript
const openPassportVerifier: OpenPassportVerifier = new OpenPassportVerifier('prove_offchain', scope).setMinimumAge(18);
```

See all methods on [OpenPassportVerifier](/docs/technical-docs/sdk-class/openpassportverifier) documentation.

#### Test environment

If you want to debug your app with a mock passport generated inside the application, you have to call the method `allowMockPassports();`

```typescript
const openPassportVerifier: OpenPassportVerifier = new OpenPassportVerifier('prove_offchain', scope).allowMockPassports();
```

#### Instantiate OpenPassportQRcode

`OpenPassportQRcode` is a React component that you can instantiate in your front-end:

```typescript
import { OpenPassportQRcode } from '@openpassport/qrcode';

// [...]

const name = 'My Example App 🥳';
 
return (
<OpenPassportQRcode
appName={name}
userId={userId}
userIdType={'uuid'}
openPassportVerifier={openPassportVerifier}
onSuccess={(attestation) => {
// send the code to the backend server
}} 
/> 
);
```

Here are the different parameters of `OpenPassportQRcode`:

<table><thead><tr><th width="208">Parameter</th><th width="194">Type</th><th>Description</th></tr></thead><tbody><tr><td>appName</td><td>string</td><td>Name of your app, part that will be displayed in the mobile app.</td></tr><tr><td>userId</td><td>string</td><td>userID is passed as a parameter of the proof in order to prevent users from stealing proof between each other.</td></tr><tr><td>userIdType</td><td>'hex' | 'uuid' | 'string'</td><td>Type of userId.</td></tr><tr><td>openPassportVerifier</td><td>OpenPassportVerifier</td><td>Instance of OpenPassportVerifier.</td></tr><tr><td>onSuccess</td><td>function</td><td>Callback method fired after proof verification. This is the place where you want to send the proof to your backend for web2 apps or send tx to verifier contracts for dApps.</td></tr></tbody></table>

### Verify the proof in your back-end (or smart-contracts)

#### Web2 apps

**Install dependencies:**

```bash
npm install @openpassport/core
```

**Instantiate `OpenPassportVerifier`**

Note: you have to use the same scope as in your front-end.

```typescript
import { OpenPassportVerifier } from '@openpassport/core';

const scope = "myExampleApp";
const openPassportVerifier: OpenPassportVerifier = new OpenPassportVerifier('prove_offchain', scope);
```

**Verify the proof:**

```typescript
import { OpenPassportVerifierReport } from '@openpassport/core';

const scope = "myExampleApp";
const validProof: boolean = (openPassportVerifier.verify(openPassportAttestation) as OpenPassportVerifierReport).valid;
```

**Nullify the proof:**

```typescript
import { OpenPassportDynamicAttestation } from '@openpassport/core';

const dynamicAttestation = new OpenPassportDynamicAttestation(openPassportAttestation);
const nullifier = dynamicAttestation.getNullifier();

const validNullifier: boolean = verifyNullifierIsNotAlreadyRegistered(nullifier) // you have to manage nullifiers yourself
```

Once the proof and nullifier are verified, you can fire your custom functions:

```typescript
if (validProof && validNullifier) {
const userId = dynamicAttestation.getUserId();
addUserToMyBirthdayWhitelist(userId); // fire your custom code implementation
}
```

**Web3 dApps**

Install dependencies:


# Privacy flow

The two-step flow lets your users register an identity into the OpenPassport user set, than use this identity to generate proofs. It's ideal for applications that:

* Need on chain verification
* Want an end-to-end auditable process while still protecting the identity of the user from the issuing country, even in scenarios in which the government takes significant steps to deanonymize users.&#x20;
* Need the server to never learn the nationality of the user
* Are fine with the user having to wait between registration and action, to make sure a large enough anonymity set is formed.


# Playground

To try out OpenPassport, open the [playground](https://www.openpassport.app/showcase) and create a mock application. You'll be prompted to open the App Clip (iOS) or install the app (Android). Scan your passport and generate a proof of identity. If you don't have a passport in hand or yours isn't supported currently, you can access a mock passport data generator from the 'Camera Screen' by clicking on the text above the button.


# Setup WSS

Set-up a web-socket server between your app and OpenPassport.

### Context

Web-socket are used to communicate between OpenPassport mobile app and web browser SDK.   OpenPassportQRcode component is using by default OpenPassport one.

We encourage you to deploy and manage your own WSS.

#### [Github repo](https://github.com/zk-passport/websocket-server)

This web-socket server is designed to run on a linux server with Node.js installed.

You can run it with [PM2](https://pm2.keymetrics.io/docs/usage/quick-start/), any process manager or simply with node.

### Installation

Clone the repository:

```
git clone https://github.com/zk-passport/websocket-server
```

Install dependencies:

```
cd websocket-server
yarn install
```

### Usage

Start the server:

```
yarn start
```

### Nginx Configuration example

To ensure secure communication between the mobile application and the websocket server, it is necessary for the server to have an `HTTPS` endpoint.

Redirect your domain to the server ip address and [setup ssl with certbot.](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04)

Here is an example of an Nginx configuration that sets up an HTTPS endpoint for the websocket server:

````
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    server {
        listen 443 ssl;
        server_name <your-domain> www.<your-domain>;

        ssl_certificate /etc/letsencrypt/live/<your-domain>/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/<your-domain>/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

        location /websocket {
            proxy_pass http://localhost:3200;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
}
```
````


# SDK class


# OpenPassportVerifier

The `OpenPassportVerifier` class is designed to facilitate the verification of user credentials and disclosures in applications using the OpenPassport system. It supports various modes of operation, allowing for both on-chain and off-chain proof verification. The class provides methods to configure verification parameters such as minimum age, nationality, and OFAC checks, and to generate intents for user interactions.

#### Parameters

| Parameter | Type     | Description                                                            |
| --------- | -------- | ---------------------------------------------------------------------- |
| `mode`    | `Mode`   | The mode of operation, determining the type of proof verification.     |
| `scope`   | `string` | An identifier for the application, used to distinguish different apps. |

#### Functions

| Function                     | Parameters                                                                                                         | Description                                                                                                                  | Output                                |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `setMinimumAge`              | `age: number`                                                                                                      | Sets the minimum age requirement for verification. Throws an error if age is less than 10 or more than 100.                  | `this`                                |
| `setNationality`             | `country: (typeof countryNames)[number]`                                                                           | Sets the nationality requirement for verification.                                                                           | `this`                                |
| `discloseNationality`        | None                                                                                                               | Sets nationality to 'Any', allowing disclosure of any nationality.                                                           | `this`                                |
| `excludeCountries`           | `...countries: (typeof countryNames)[number][]`                                                                    | Excludes specified countries from verification.                                                                              | `this`                                |
| `enableOFACCheck`            | None                                                                                                               | Enables OFAC (Office of Foreign Assets Control) check for verification.                                                      | `this`                                |
| `setModalServerUrl`          | `modalServerUrl: string`                                                                                           | Sets the URL for the modal server used in verification.                                                                      | `this`                                |
| `setCommitmentMerkleTreeUrl` | `commitmentMerkleTreeUrl: string`                                                                                  | Sets the URL for the commitment Merkle tree, required for 'register' mode.                                                   | `this`                                |
| `setRpcUrl`                  | `rpcUrl: string`                                                                                                   | Sets the RPC URL for on-chain operations.                                                                                    | `this`                                |
| `allowMockPassports`         | None                                                                                                               | Enables the use of mock passports for testing purposes.                                                                      | `this`                                |
| `getIntent`                  | `appName: string, userId: string, userIdType: UserIdType, sessionId: string, websocketUrl: string = WEBSOCKET_URL` | Generates an intent string for user interaction, encoding the necessary verification parameters. Used by OpenPassportQRcode. | `string`                              |
| `verifyProof`                | `proof: OpenPassportAttestation`                                                                                   | Verifies a proof against the configured verification parameters.                                                             | `Promise<OpenPassportVerifierReport>` |


# OpenPassport Attestation

The `OpenPassportAttestation` interface represents the structure of an attestation used in the OpenPassport system. It includes details about the credential subject, proof, and document signing certificate (DSC) proof. It has been designed according to W3C standards.

#### Parameters

| Parameter           | Type       | Description                                      |
| ------------------- | ---------- | ------------------------------------------------ |
| `@context`          | `string[]` | Context URLs for the attestation.                |
| `type`              | `string[]` | Types of the attestation.                        |
| `issuer`            | `string`   | The issuer of the attestation.                   |
| `issuanceDate`      | `string`   | The date the attestation was issued.             |
| `credentialSubject` | `object`   | Contains details about the user and application. |
| `proof`             | `object`   | Contains passport proof.                         |
| `dscProof`          | `object`   | Contains DSC proof details for verification.     |
| `dsc`               | `object`   | Contains DSC details.                            |

### `OpenPassportDynamicAttestation`

The `OpenPassportDynamicAttestation` class extends `OpenPassportAttestation` and provides methods to parse and retrieve specific attributes from the attestation.

#### Functions

<table><thead><tr><th width="221">Function</th><th width="126">Parameters</th><th width="309">Description</th><th>Output</th></tr></thead><tbody><tr><td><code>getUserId</code></td><td>None</td><td>Retrieves the user ID from the parsed public signals.</td><td><code>string</code></td></tr><tr><td><code>getNullifier</code></td><td>None</td><td>Retrieves the nullifier from the parsed public signals.</td><td><code>string</code></td></tr><tr><td><code>getCommitment</code></td><td>None</td><td>Retrieves the commitment from the parsed public signals.</td><td><code>string</code></td></tr><tr><td><code>getNationality</code></td><td>None</td><td>Retrieves the nationality from the unpacked reveal data.</td><td><code>string</code></td></tr><tr><td><code>getCSCAMerkleRoot</code></td><td>None</td><td>Retrieves the CSCAMerkleRoot from the DSC proof public signals.</td><td><code>string</code></td></tr></tbody></table>


# Mobile app

The typescript frontend calls native modules in Swift and Kotlin that call [witnesscalc](https://github.com/0xPolygonID/witnesscalc) and [rapidsnark](https://github.com/iden3/rapidsnark).&#x20;

Using the PolygonID stack for client-side proving allowed us to get down to \~4s proofs on the latest iPhone for our 450k constraint circuit, and \~200ms for our 7k constraints circuit.


# Circuits

We split OpenPassport circuits into two steps according to a Semaphore-style design. This lets users do actions without revealing which signature algorithm was used to sign their passport.

The first step is registration. It allows users to prove their passport is valid without revealing any of their private data.

![Screenshot 2024-06-16 at 08.58.42](https://hackmd.io/_uploads/r1QpoF3BC.png)

We currently support two signature algorithms:

* [sha256WithRSAEncryption](https://github.com/zk-passport/proof-of-passport/blob/main/circuits/circuits/register_sha256WithRSAEncryption_65537.circom)
* sha1WithRSAEncryption

We are working on adding more, [see details here](https://github.com/zk-passport/proof-of-passport/issues/38).

After the proof is generated, it is sent to a smart contract and adds a commitment to a merkle tree. The tree is currently on Optimism, but can be migrated easily. The hash of the issuer's signature is used as a nullifier.

The second step is [interaction](https://github.com/zk-passport/proof-of-passport/blob/main/circuits/circuits/disclose.circom), also called broadcasting a message in Semaphore.

![Screenshot 2024-06-16 at 09.02.48](https://hackmd.io/_uploads/H1t2nthrA.png)

It involves proving inclusion of the commitment in the merkle tree, and optionally disclosing some private data. Any data in the MRZ can be disclosed thanks to a bitmap passed as private inputs. This includes:

* Issuing state
* Name
* Passport number
* Nationality
* Date of birth
* Gender
* Expiry date

Additionally, we crafted specific modules in the circuit to disclose:

* Passport is not expired
* Age is above a certain threshold

A `user_identifier` is committed in this proof. For onchain usage, it is used to avoid frontrunning. For offchain usage, it can be used by apps to identify users uniquely and make sure someone who obtains a proof later cannot impersonate someone.


# Registry


