# Tangle Cryptographic Contact Discovery & Privacy Architecture (VOPRF / PSI)

## 1. Executive Summary

Tangle employs **Privacy-Preserving Contact Discovery** based on the **RFC 9497 2-Round Verifiable Oblivious Pseudorandom Function (VOPRF)** over the prime-order elliptic curve **NIST P-256 (secp256r1)**.

### Core Guarantees:
1. **Zero Raw Phone Storage**: The server never permanently stores plaintext phone numbers or simple hashes (e.g., raw SHA-256) in PostgreSQL. Phone numbers are represented as opaque, deterministic `blinded_identity` tokens derived via the server's private OPRF key.
2. **Zero Address Book Exposure**: When a user syncs their device contacts, the server never learns who is in the user's phonebook.
3. **No Database Scraping**: The client cannot download or enumerate the full list of Tangle registered users.
4. **Provable Server Evaluation**: The server returns Chaum-Pedersen Discrete Logarithm Equality (DLEQ) zero-knowledge proofs demonstrating that evaluations used the true server key, preventing rogue server manipulation.

---

## 2. Threat Model & Security Analysis

| Threat / Attacker | Attack Vector | Tangle Defense Mechanism |
| :--- | :--- | :--- |
| **Database Compromise (Dump Leak)** | Attacker dumps the PostgreSQL database (e.g., SQL injection, backup breach) and tries to extract user phone numbers. | Raw phone numbers are completely absent. Identifiers are stored as `blinded_identity = H2(phone, k · H1(phone))`. Because phone numbers are low-entropy (~10¹⁰ global space), standard hashes are vulnerable to brute-force rainbow tables. In Tangle, the server private key $k$ is stored in secure secret storage (HSM / KMS), rendering offline rainbow table attacks computationally infeasible without $k$. |
| **Honest-but-Curious Server / Operator** | The server or insider inspects incoming contact discovery requests to discover user relationships or social graphs. | The mobile client generates a cryptographically random blinding scalar $r \in \mathbb{F}_q^*$ for each contact, transmitting only blinded curve points $B = r \cdot P$. By the Discrete Logarithm problem, the server cannot recover $P$ or the contact's phone number from $B$. |
| **Malicious Server (Impersonation / Key Substitution)** | Compromised server attempts to return arbitrary or mismatched points to manipulate client contact discovery. | Each server evaluation includes a non-interactive zero-knowledge DLEQ proof $(c, s)$. The mobile client verifies that $\log_G(Y) == \log_B(E)$ using the server's public key $Y = k \cdot G$. Any tampered or substituted evaluation is immediately rejected. |
| **Malicious Client (Phonebook Sweeping / Enumeration)** | Attacker signs up for an account and queries billions of phone numbers to build a directory of registered users. | 1. **Authentication Required**: All VOPRF evaluation and matching endpoints require an authenticated Bearer JWT.<br>2. **Strict Sliding-Window Rate Limits**: Max 10 VOPRF evaluations per user per hour enforced via in-memory sliding-window limiter.<br>3. **Batch Constraints**: Max 500 contacts per request.<br>4. **Opaque Matches**: Match responses return only public profiles (`id, username, display_name, avatar_url, public_key`), never raw phone numbers. |
| **Log Leakage** | Internal server logs expose user contacts. | Logging is strictly sanitized: raw phone numbers, blinded curve points, and token hashes are excluded from server stdout/stderr logs. Only aggregate counts and anonymized user UUIDs are recorded. |

---

## 3. Cryptographic Protocol Specification (RFC 9497 VOPRF)

### Mathematical Parameters:
- **Curve**: NIST P-256 ($y^2 = x^3 - 3x + b \pmod p$).
- **Base Point**: Generator $G$.
- **Subgroup Order**: $q \approx 2^{256}$.
- **Server Private Key**: $k \in \mathbb{F}_q^*$ (configured via `VOPRF_SERVER_SECRET`).
- **Server Public Key**: $Y = k \cdot G$.
- **Hash Functions**:
  - $H_1(\text{phone}) \to \mathbb{G}$: Hash-to-curve using Try-and-Increment with domain separator `"TANGLE_VOPRF_P256_HASH_TO_CURVE_V1"`.
  - $H_2(\text{phone}, U) \to \{0,1\}^{256}$: Finalize token using HMAC-SHA256 with domain separator `"TANGLE_VOPRF_FINALIZE_V1"`.

### Protocol Steps:

```mermaid
sequenceDiagram
    autonumber
    actor Alice as Client (Alice)
    participant Server as Tangle Backend
    participant DB as PostgreSQL

    Note over Alice: Alice normalizes phone numbers to E.164: +15551234567
    Alice->>Server: GET /api/v1/users/contacts/voprf/params
    Server-->>Alice: Returns Curve (P-256) and Server Public Key Y = k · G
    
    Note over Alice: For each contact phone:<br/>1. P = H1(phone)<br/>2. Sample random r ∈ [1, q-1]<br/>3. B = r · P (Blinded Point)
    Alice->>Server: POST /api/v1/users/contacts/voprf/evaluate<br/>Payload: [B1, B2, ..., Bn] (Max 500)
    
    Note over Server: Rate limit check: max 10/hr<br/>For each Bi:<br/>1. Check Bi on curve & not infinity<br/>2. Ei = k · Bi<br/>3. Generate DLEQ proof (ci, si)
    Server-->>Alice: Returns [{Ei, Proof(ci, si)}, ...]

    Note over Alice: For each result:<br/>1. Verify DLEQ: Verify(Y, Bi, Ei, ci, si) == true<br/>2. Unblind: Ui = r⁻¹ · Ei = k · Pi<br/>3. Token = H2(phone, Ui)
    Alice->>Server: POST /api/v1/users/contacts/voprf/match<br/>Payload: [Token1, Token2, ...]
    
    Server->>DB: SELECT ... WHERE blinded_identity = ANY($tokens)
    DB-->>Server: Matched user rows
    Server-->>Alice: Returns matched public profiles
    Note over Alice: Alice maps tokens back to local address book entries!
```

---

## 4. Database Schema & Migration Strategy

### Database Representation:
- **`users.blinded_identity`** (`VARCHAR(64)`): Unique index `idx_users_blinded_identity` on non-null values. Stores the 64-character hexadecimal finalize token computed directly by the server during OTP registration:
  $$\text{blinded\_identity} = H_2(\text{phone}, k \cdot H_1(\text{phone}))$$
- **`phone_verifications.phone_blinded_id`** (`VARCHAR(64)`): Indexed for fast lookup of pending OTP verification attempts without retaining plaintext digits.

### Zero-Downtime Safe Migration Workflow:
1. **Schema Expansion**:
   Add `blinded_identity` and `phone_blinded_id` as nullable columns.
2. **Backfill Phase**:
   Read legacy records, compute `DeriveBlindedIdentity(normPhone)` using the server key, and populate new columns.
3. **Verification Gate**:
   Assert that `COUNT(*) WHERE phone_number IS NOT NULL AND blinded_identity IS NULL` is exactly $0$. If any unmigrated records exist, the migration aborts before dropping columns.
4. **Elimination Phase**:
   Execute `DROP COLUMN phone_number` and drop legacy phone indexes on both `users` and `phone_verifications`.

---

## 5. Security Limitations & Key Management

### Limitations:
1. **Server Key Confidentiality**: The privacy of blinded identifiers depends entirely on the secrecy of the server private key $k$. If $k$ is leaked along with a database dump, an attacker could build an offline dictionary of phone numbers and compute $H_2(\text{phone}, k \cdot H_1(\text{phone}))$.
2. **Key Rotation**: Changing the server private key $k$ invalidates all existing `blinded_identity` records in the database. Key rotation requires either:
   - A dual-key migration period where both old and new keys are supported during active user sessions.
   - Requiring users to re-verify phone numbers via SMS OTP upon next login.
3. **Sybil Contact Testing**: A malicious user can test whether a specific phone number is on Tangle by adding it to their address book and checking for a match. However, rate limits (10 syncs/hr, 500 contacts/batch) prevent large-scale namespace harvesting.

---

## 6. Production Readiness Notice

> [!IMPORTANT]
> **Independent Review Required Prior to Production Deployment**
> 
> Although all automated test suites pass (including protocol mathematical correctness, DLEQ proof verification, tamper rejection, rate limiting, and end-to-end integration matching), cryptographic code in production should undergo:
> 1. An independent external cryptographic audit of the NIST P-256 scalar multiplication and HashToCurve implementations.
> 2. Key management integration with a cloud Hardware Security Module (HSM) or secret manager (e.g., AWS KMS, HashiCorp Vault) rather than environment variables in production.
> 3. Timing-attack analysis on point parsing and validation routines.

---

## 7. Privacy-Preserving Link Reputation & Anti-Phishing Architecture

Tangle incorporates a client-side link defense system protecting users against malicious links, homoglyph lookalikes, obfuscated IP redirects, and phishing attacks while guaranteeing zero leakage of chat message content or visited URLs.

### Core Architectural Guarantees:
1. **$k$-Anonymity Hash Prefix Queries**: The client never transmits full URLs, domains, or query parameters to the backend or any external threat service. URLs are normalized locally and broken down into canonical Safe-Browsing host/path expressions. The client sends only 4-byte (8 hexadecimal character) SHA-256 hash prefixes.
2. **Client-Side Hash Verification**: The backend returns all threat entries matching the requested 4-byte prefix. The client locally computes the full 32-byte SHA-256 hash and compares it against the returned candidate hashes. A link is only confirmed malicious if the full 256-bit hash matches.
3. **Punycode & Homoglyph Lookalike Defenses**: Detects internationalized domains (`xn--...`), mixed Cyrillic/Greek scripts masquerading as Latin characters (e.g., Cyrillic 'а' U+0430 spoofing `paypal.com` or `google.com`), and fake user-info disguises (`https://google.com@phishing.com`).
4. **Non-Harmful Treatment of Unknown Links**: Unknown, unverified external links are never automatically labelled harmful or malware. They launch cleanly without alarmist disruption, reserving high-impact warning modals exclusively for confirmed threat intelligence matches and deceptive lookalike domains.
5. **SSRF-Safe Link Previews**: The backend preview proxy enforces strict protection against Server-Side Request Forgery (SSRF) and DNS rebinding attacks:
   - Private, loopback, link-local, multicast, and RFC 1918 addresses (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `127.0.0.0/8`, `169.254.0.0/16`, `::1`, `fc00::/7`, `fe80::/10`) are blocked before socket connection.
   - Socket connections hook a custom `Control` dialer that re-verifies the resolved IP address on every connection attempt, mitigating DNS rebinding time-of-check to time-of-use (TOCTOU) races.
   - Redirect chains are capped at 3 hops, with re-validation on every step.
   - Response bodies are capped at 512 KB to avoid decompression bombs.

