# 6.1 Zero-Knowledge Proofs for KYC (zk-KYC)

zk-KYC allows users to prove to the agreement: "I am a legitimate, unsanctioned, real user" without revealing "who I am".

#### 6.1.1 Circuit Design for Identity Verification&#x20;

Our ZK circuit (written based on Circom or Halo2) is designed to prove a specific arithmetic statement.

1\. Certificate Issuance (Credential Issuance - Off-chain)

First, the user presents physical credentials on their local device to a trusted third-party issuer (such as Synaps or Binance). Once the issuer verifies the credentials, they digitally sign the user's decentralized identifier (DID) to generate a credential $C$.

$$
C = \text{Sign}*{Issuer}(DID*{user}, \text{Attributes})
$$

2\. Circuit Statement

When a user wants to interact with OmniPact (e.g., to deposit a large sum of money), a Proof $\pi$ must be generated.

A zero-knowledge circuit $C\_{kyc}$ contains the following constraints:

* Inputs:
  * Private Inputs: User's private key $$ $sk$ $$,certificate $$ $C$ $$, the Merkle Path of the credentials.
  * Public Inputs: Issuer public key$$ $PK\_{Issuer}$ $$,Merkle Root on the compliance list $$ $R\_{valid}$ $$,Merkle Root on the sanctions list $$ $R\_{sanctions}$ $$。

**Constraints:**

* Signature verification: Proves that $C$ is indeed a valid credential issued by $PK\_{Issuer}$.

$$
\text{VerifySig}(PK\_{Issuer}, C) == \text{true}
$$

* Proof of Ownership: Proof of user ownership of the credentials $$ $C$ $$ Bound private key $$ $sk$ $$
* Membership: Proof that the credential exists in the valid user tree $$ $R\_{valid}$ $$ middle.
* Non-Membership: Proof that the user is not on the OFAC sanctions list $$ $R\_{sanctions}$ $$ middle.
* Attribute assertion: (Optional) Proof `Attributes.Age >= 18` 或 `Attributes.Country != "North Korea",`However, the specific values ​​are not disclosed.

3\. Output

Circuit output proof $\pi$. Smart contract verification.

$$
\text{Verify}(\pi, PublicInputs)
$$

If true, the transaction is allowed. No user names or identification numbers are stored on the blockchain throughout the entire process.

#### 6.1.2 Nullifier Implementation for Anonymity&#x20;

While protecting privacy, we must prevent "identity double-spending," which means that the same compliant user can re-enter under a different alias after being banned, or the same user can claim "newcomer rewards" multiple times. To address this, we have introduced a nullifier mechanism.

1\. Deterministic and irreversible identifiers

The nullifier is a hash value that is unique to the same user within the same scope, but it cannot be used to deduce the user's identity.

Nullifier calculation formula:

$$
Nullifier = \text{PoseidonHash}(sk\_{user}, \text{Scope}, \text{Salt})
$$

* $$ $sk\_{user}$ $$:The user's secret private key (which is also the private input of the ZK circuit).
* Scope: Scope parameter.
  * If it is a global ban list, the scope is `PROTOCOL_ID`。
  * If it is a single voting activity, the scope is `ELECTION_ID`。
* PoseidonHash: A hash algorithm that is friendly to ZK circuits.

2\. Mechanism

1. Generation: Each time a user submits zk-KYC proof, the circuit will calculate as a byproduct $$Nullifier$$ And it is made public as Public Output.
2. Record: Smart contracts maintain a `mapping(bytes32 => bool) usedNullifiers`。
3. Anti-replay:
   * If the goal is "limited to one per person", contract review `usedNullifiers[Nullifier]` Is it `true.`If so, then refuse.
   * If the purpose is "blacklist tracking," when a nullifier is marked as malicious by the OmniPact governance committee, that nullifier will be permanently added to the blacklist`Blacklist`。
4. Anonymity: due to $$ $sk\_{user}$ $$ Only the user knows that what an external observer sees is a string of random gibberish. Even if the user uses the OmniPact protocol in different DApps, the generated nullifier will be completely different as long as the scope is different, thus preventing cross-application linkability attacks.

***

{% hint style="success" %}
A perfect mathematical balance has been found between the seemingly contradictory demands of "absolute privacy" and "regulatory compliance".
{% endhint %}


---

# 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://docs.omnipact.io/developers/omnipact-technology-white-paper/readme/privacy-and-compliance-framework/6.1-zero-knowledge-proofs-for-kyc-zk-kyc.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.
