# How ZK Login Works

{% stepper %}
{% step %}

### Generating the Ephemeral Key Pair

The login flow begins on the client side. Before any OAuth request is made, the application generates:

* An **ephemeral private key** (`esk`) and its corresponding **ephemeral public key** (`epk`).
* A random byte string called the **`epk_blinder.`**

These are temporary credentials, valid only for a short session window defined by an **ephemeral expiry time** (`epk_expiry_time`).

{% endstep %}

{% step %}

### The OAuth Request

When the OAuth request is sent to Google, an additional component is embedded in it: a **hash of the `epk` and `epk_blinder`**. Google includes this hash in the JWT (JSON Web Token) it returns, effectively binding the ephemeral key pair to your Google session.

{% endstep %}

{% step %}

### The Salt Service

Once the JWT is returned, the following components are sent to the **Salt Service**:

* The JWT (in Base64 format).
* The ephemeral public key (`epk`).
* The `epk_blinder.`
* The ephemeral expiry time (`epk_expiry_time`).

The Salt Service is responsible for:

1. Verifying the authenticity of the JWT.
2. Verifying the hash embedded in the JWT against the provided `epk` and `epk_blinder` .
3. Generating a unique salt derived from the JWT's components (specifically the `sub` and `iss` fields).
4. Computing a deterministic wallet address (`addr`): this becomes the permanent on-chain address associated with your Gmail account.

{% hint style="info" %}

#### The salt ensures that your on-chain address is unique and consistent across sessions, while never revealing your email address or identity on-chain.

{% endhint %}

{% endstep %}

{% step %}

### The Proof Server

At this stage, the user holds all of the following:

<table><thead><tr><th width="226.83203125">Component</th><th>Description</th></tr></thead><tbody><tr><td><code>jwt_base64</code></td><td>The JWT returned by Google</td></tr><tr><td><code>epk</code></td><td>Ephemeral public key</td></tr><tr><td><code>epk_blinder</code></td><td>Random blinding value</td></tr><tr><td><code>epk_expiry_time</code></td><td>Session expiry time</td></tr><tr><td><code>salt</code></td><td>Unique salt from the Salt Service</td></tr><tr><td><code>addr</code></td><td>Deterministic wallet address</td></tr></tbody></table>

All of these are submitted to the **Proof Server**, which:

1. Prepares all inputs required by the ZK circuit
2. Generates a **zero-knowledge proof**
3. Returns the proof along with a **public input component** to the user

The proof cryptographically ties your wallet address to your Gmail account and ephemeral key pair, without revealing any private information to the chain or any third party.

{% hint style="warning" %}
While the Salt Service can derive your wallet address, you cannot transact from it without a valid proof. The proof is what binds everything together and authorizes on-chain activity.
{% endhint %}
{% endstep %}
{% endstepper %}

#### Summary

ZK Login effectively bridges Web2 identity and Web3 access, allowing seamless onboarding without compromising user privacy or decentralization.

```
User logs in with Gmail
        ↓
Ephemeral key pair (esk, epk) + epk_blinder generated
        ↓
OAuth request sent → JWT returned (with epk hash embedded)
        ↓
JWT + epk + epk_blinder → Salt Service
        → Verifies JWT & hash
        → Returns: salt + wallet address (addr)
        ↓
All components → Proof Server
        → Generates ZK proof
        → Returns: proof + public inputs
        ↓
User can now sign transactions on-chain
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wp.vola.network/docs/vola-architecture/zk-login-and-identity/how-zk-login-works.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
