# What's zKey?

zKey is a self-custodial wallet using zero-knowledge proof that allows you to login to Dapps with your familiar social accounts like Google, Apple, and Facebook. Designed to be the most suitable wallet for consumer Dapps, it offers unmatched advantages in the three most critical areas.

**Convenience**

* No need to back up private keys or seed phrases.
* No clients or plugins.
* Uses session key to avoid signing for each transaction.

**Security**

* Inherits advanced account security solutions from Google & Apple of 2FA to protect users’ keys from being lost.
* Zero-knowledge proof enables the verification of users' unique Web2 identities on the blockchain, ensuring that only the rightful owner can access the wallet.

**Privacy**

* Zero-knowledge proof enables the verification of users’ Web2 identities without revealing the content to the public.
* The unique salt unlinks users’ on-chain address from their off-chain identities.

Web3 has spent 10 years on building infrastructure, now it has come to a time for applications. zKey will give users the best experience of a self-custodial wallet ever.


# Structure

<figure><img src="https://4212951670-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FpYH8jrGc6LuTg6Qf4MFw%2Fuploads%2FU3DPgNFVxvU9TjkxW4FF%2Fimage.png?alt=media&amp;token=6a9c746b-6afd-4961-ba28-9c0caf308eae" alt=""><figcaption></figcaption></figure>


# Components

1. OpenID Provider(OP)

An entity that has implemented the OpenID Connect and OAuth 2.0 protocols, including Google, Apple, Meta, etc. A key feature of these providers is their ability to issue a signed JWT containing a set of claims to authenticate the end-user.

2. JSON Web Token(JWT)

A signed statement issued by OPs containing claims about the user. We use some of the claims parsed from JWT to derive the zKey address and verify users’ identities, including `sub` that uniquely identifies the user per provider, `iss` that identifies the provide, and `aud` that identifies the application.

3. User

An end user that owns the zKey address and performs transactions using existing OpenID credentials.

4. Frontend

The frontend application that supports zKey, responsible for storing the session private key, directing users to complete the OAuth login flow, creating and signing a zKey transaction.

Since there is no need to securely store or export the key pair, there is no requirement for an additional client or plugin. The frontend can be seamlessly integrated into any Dapp, significantly minimizing the effort required for users to utilize the Dapp.

5. Salt Service

Generates a unique salt and saves it securely. We currently utilize Google Cloud to back up the salt and might move to additional servers.

6. ZK Proving Service

Generates zero-knowledge proofs that attest to the validity of the JWT and salt without revealing the contents.

We are currently using zk-SNARKs to generate proofs, as they are more suitable for handling small proof sizes.

7. Contracts

Consists of a Wallet Contract and an Authentication Contract on Starknet.

The Wallet Contract sets up public key recovery by calling the Authentication Contract and executes transactions.

The Authentication Contract is a set of Cairo files exported from the circuit and deployed on Starknet. This contract will verify zero-knowledge proofs and authenticate transactions.


# Workflow

1. **Get JWT**

In the process of zKey, the OP is utilized as a certificate authority by embedding data into the nonce during the OpenID authentication process.

* The frontend generates a session key pair `(pri_k, pub_k)`, a randomness `random1`, an expiry time `exp`, and computes the nonce via `nonce=H(pub_k, random1, exp)`.
* User goes through OP’s login flow and passes in the nonce.
* Upon successful authentication, the frontend gets a JWT, denoted as `jwt` , from the OP.
* The frontend parses `jwt` and gets `sub`, `iss`,`aud`. The `jwt` serves as a certificate for `pub_k`, confirming that the owner of `pri_k` is indeed the user identified by the `sub` issued by the OP.

2. **Get Salt & Address**

zKey addresses can be generated from any unique and stable identifier provided by the OP to ensure that each user has a distinct address. However, this approach presents a privacy issue: the same identifier might be returned when users log in to different apps, potentially exposing the link between their on-chain addresses and their Web2 identities. To address this problem, a salt is introduced, which unlinks the user’s OP-issued identifier from their on-chain address.

* The frontend generates a `salt` and saves it in the salt backup service.
* The frontend computes the zKey address `zkaddr = H(sub, aud, iss, salt)` . The `zkaddr` will be compatible with all types of wallets and blockchains.
* The frontend computes the wallet address `waddr = H(zkaddr)` .

3. **Get ZKP**

Now we can use the salt and the JWT to compute a zero-knowledge proof and demonstrate the association between `pub_k` and `waddr` .

We utilize a ZKP service to generate the proof, as the computation might be challenging on users' local devices. This service operates within NVIDIA's Hopper trusted computing environment, ensuring no sensitive information is leaked. The average generation time is approximately 2 seconds.

* The frontend passes `jwt`, `OP_k`(OP’s public key), `salt`, `pub_k`, `random1` to the ZKP Service to generate a proof. The frontend also passes `iss`, `sub`, `aud`, `nonce`that can be parsed from `jwt` to help the ZKP Service verify all the inputs.
* The ZKP Service returns a proof and public signals including `assic(iss)`, `assic(aud)`, `exp`, `zkaddr`, `pub_k`. Additionally, `iss` and `aud` are converted to `ascii(iss)` and `ascii(aud)` as it's the only format the circuit can handle.

4. **Submit Transaction**

Since zKey is built on Starknet, which natively supports smart contract wallets, the `pub_k` can be embedded into the wallet, eliminating the need to verify the ZKP for every transaction.

* `waddr` will be deployed initially to create the corresponding Wallet Contract, with a temporary public key and no private key. This step is solely for establishing the wallet on-chain, as the function does not support proof verification during the initial wallet deployment.
* After the initial deployment of `waddr`, the frontend submits a proof and public signals to the Wallet Contract. The Wallet Contract computes `waddr` from `zkaddr` and in the public signals to ensure the proof is sent to the correct Wallet Contract. Once verified, it calls the Authentication Contract to validate the proof and signals. Upon successful verification, `pub_k` is written into the contract, and the user only needs to sign with `pri_k` for future transactions.
* When users need to reset the session keys(this occurs in scenarios such as when they lose their keys), the same process applies, and the old `pub_k` will be overwritten with the new `pub_k`. As long as they retain the OP's account and the salt, they can retrieve the same address and reset their key pair at any time.


# Session Keys

Session keys allow Dapps to sign transactions on behalf of a user with specific limitations, such as expiry time, token limit, etc.

Each zKey login assigns users a session key with an expiry time, allowing them to autonomously sign transactions in a Dapp. This enables an immersive gameplay experience without the need to handle every transaction. Users only need to log in again and obtain new session keys when the session key expires or they lose their keys.


# Performance

The ZKP generation time is \~2 seconds, the smart contract feedback time is 2 seconds (4 seconds for the first deployment), the Google login server response time is under 1 second, and the total login time for registration and recovery ranges from 5 to 10 seconds.


