Skip to main content

Zero-Knowledge Proofs

Argus uses zero-knowledge proofs to enable HUMINT sources to make verifiable claims without revealing sensitive information.

What Are ZK Proofs?

Zero-knowledge proofs let you prove a statement is true without revealing why it's true. For example:

  • Location: "I was within 50km of Kyiv" without revealing exact coordinates
  • Reputation: "My reputation is ≥ 70" without revealing exact score
  • Identity: "This new identity is the same person as an old one" without linking them

Supported Proof Types

🌍 Location Attestation

Prove you were in a geographic region without revealing your exact location.

Use cases:

  • Verify on-the-ground presence for conflict intel
  • Prove attendance at events without tracking
  • Regional expertise verification

How it works:

Private input: (actualLat, actualLon, salt)
Public input: (targetLat, targetLon, maxDistance)
Proof: "I was within maxDistance km of (targetLat, targetLon)"

API:

# Generate proof
POST /api/zk/location/prove
{
"actualLat": 50.4501, # Your actual latitude (private)
"actualLon": 30.5234, # Your actual longitude (private)
"targetLat": 50.4500, # Target latitude (public)
"targetLon": 30.5200, # Target longitude (public)
"maxDistanceKm": 50 # Maximum distance (public)
}

# Returns proof + commitment

⭐ Reputation Threshold

Prove your reputation meets a minimum threshold for bounty eligibility.

Use cases:

  • Qualify for high-reputation bounties
  • Prove expertise level without exact score
  • Tiered access control

How it works:

Private input: (publicKey, reputationScore, salt)
Public input: (threshold)
Proof: "My reputation is >= threshold"

API:

POST /api/zk/reputation/prove
{
"publicKey": "0x...", # Your source public key
"threshold": 70 # Minimum reputation to prove
}

🔄 Identity Rotation

Rotate to a new codename while preserving reputation, without linking old and new identities.

Use cases:

  • Periodic identity rotation for safety
  • Escape compromised identity
  • Fresh start without losing reputation

How it works:

Private input: (oldPublicKey, oldPrivateKey, newPublicKey, reputation)
Public input: (newPublicKeyHash, reputationCommitment, nullifier)
Proof: "I control oldIdentity and am transferring its reputation to newIdentity"

The nullifier prevents the same old identity from being rotated twice.

API:

# Step 1: Generate rotation proof
POST /api/zk/identity/rotate
{
"oldPublicKey": "0x...",
"oldPrivateKey": "0x...",
"newPublicKey": "0x..."
}

# Step 2: Complete rotation
POST /api/zk/identity/complete
{
"proof": {...},
"publicSignals": [...],
"newPublicKey": "0x..."
}

Technical Details

Circuits

Circuits are written in Circom and compiled to R1CS constraints. We use:

  • Poseidon Hash: ZK-friendly hash function for commitments
  • Groth16: Proof system (small proofs, fast verification)
  • BN128 curve: Ethereum-compatible elliptic curve

Security Model

What's HiddenWhat's Revealed
Exact locationProximity to target
Exact reputationWhether above threshold
Old identityThat rotation occurred
Private keysPublic key hashes

Commitments

Before generating a proof, you create a commitment to your private data:

commitment = Poseidon(privateData, salt)

This commitment is public, but reveals nothing about privateData without the salt.

Nullifiers

For one-time actions (like identity rotation), we use nullifiers:

nullifier = Poseidon(identityKey, action, salt)

Once a nullifier is used, it's recorded. Attempting to reuse it fails, preventing double-spending of reputation.

Client-Side Proof Generation

For maximum privacy, generate proofs client-side:

import { generateLocationProof } from '@argus/zk-client';

// All computation happens in your browser
const proof = await generateLocationProof({
actualLat: myLat, // Never sent to server
actualLon: myLon, // Never sent to server
targetLat: 50.45,
targetLon: 30.52,
maxDistanceKm: 50
});

// Only send proof + public signals
await submitProof(proof);

Verification

Anyone can verify a proof without knowing the private inputs:

const isValid = await verifyLocationProof(
proof,
publicSignals,
verificationKey
);

Verification is:

  • Fast: ~10ms
  • Trustless: No need to trust the prover
  • Deterministic: Same inputs always verify the same way

Roadmap

Current (v0.1)

  • ✅ Location attestation (mock proofs)
  • ✅ Reputation threshold (mock proofs)
  • ✅ Identity rotation (mock proofs)
  • ✅ API endpoints

Coming (v0.2)

  • ⏳ Compiled circuits (real proofs)
  • ⏳ Client-side proof generation SDK
  • ⏳ On-chain verification (NEAR)
  • ⏳ Time-bounded presence proofs

Future (v0.3+)

  • 📋 Device attestation (trusted hardware)
  • 📋 Media authenticity proofs
  • 📋 Aggregate proofs (batch verification)
  • 📋 Cross-source collaboration proofs

FAQ

Do I need special hardware?

No. Proof generation runs in any modern browser or Node.js environment.

How long does proof generation take?

  • Location proof: ~2-5 seconds
  • Reputation proof: ~1-2 seconds
  • Identity rotation: ~3-5 seconds

Can proofs be faked?

No. The cryptographic properties of ZK-SNARKs make it computationally infeasible to create a valid proof for a false statement.

What if I lose my private key?

You lose the ability to generate proofs for that identity. This is a feature, not a bug - it prevents key theft from being silent.

Are proofs stored on-chain?

Currently no. Proofs are verified by the Argus API. On-chain verification (for decentralized verification) is on the roadmap.