'use client'; import React, { useEffect, useState } from 'react'; import { ChevronLeft, KeyRound, ShieldCheck, AlertTriangle, FileKey } from 'lucide-react'; import { fetchInfonetStatus, type InfonetStatus } from '@/mesh/infonetEconomyClient'; interface FunctionKeyViewProps { onBack: () => void; } const PIECE_STATUS: Record = { not_implemented: { color: 'text-gray-500', label: 'NOT IMPLEMENTED' }, scaffolding: { color: 'text-amber-400', label: 'SCAFFOLDING' }, reference_impl: { color: 'text-blue-400', label: 'REFERENCE' }, production_rust: { color: 'text-green-400', label: 'PRODUCTION' }, }; export default function FunctionKeyView({ onBack }: FunctionKeyViewProps) { const [status, setStatus] = useState(null); useEffect(() => { let cancelled = false; void (async () => { try { const s = await fetchInfonetStatus(); if (!cancelled) setStatus(s); } catch { // ignore — render the design overview without status } })(); return () => { cancelled = true; }; }, []); return (
FUNCTION KEYS — Anonymous Citizenship Proof
A citizen proves "I am an Infonet citizen" to a real-world operator without revealing their Infonet identity. The naive approach (scramble a public key, record each redemption on chain) leaks identity through metadata correlation. The Function Keys design is six pieces; five are implemented; one (issuance via blind signatures / anonymous credentials) waits on a cryptographic primitive decision.
{status && (
Privacy Primitive Status
{Object.entries(status.privacy_primitive_status).map(([k, v]) => { const style = PIECE_STATUS[v] ?? PIECE_STATUS.not_implemented; return (
{k.replace(/_/g, ' ')}
{style.label}
); })}
Cryptographic primitives are stubbed via the locked Protocol contracts in services/infonet/privacy/contracts.py. When the privacy-core Rust binding lands, the scaffolding swaps for the production class — no caller changes.
)}
The Six Pieces
  1. 1. Issuance{' '} (NOT IMPLEMENTED — blind sig / BBS+ / U-Prove / Idemix)
    Protocol issues a credential proving citizenship without linking to node_id.
  2. 2. Nullifiers{' '} (implemented — pure SHA-256)
    nullifier = H(secret || operator_id). Different operators see different nullifiers for the same key — no cross-operator linkage. One-time-use per (key, operator) pair via a tracker.
  3. 3. Challenge-Response{' '} (implemented — HMAC-SHA256 placeholder)
    Operator issues a fresh nonce; key-holder signs with the Function Key's secret. Defeats screenshot, replay, key-sharing. Production wires the chosen blind-sig scheme; API stays compatible.
  4. 4. Two-Phase Commit Receipts{' '} (implemented)
    Phase 1: operator signs a verification receipt (day-bucket date, nullifier prefix only — NO timestamps, NO full nullifiers, NO node_id). Phase 2: citizen counter-signs after service rendered. Both parties hold a copy. Receipts NEVER published on-chain.
  5. 5. Enumerated Denial Codes{' '} (implemented — 3-value enum)
    Operators can reject for exactly three reasons: invalid signature, nullifier already seen, rate limit exceeded. Adding a 4th code is a hard fork. Anti-discrimination by design.
  6. 6. Batched Settlement{' '} (implemented)
    Operators settle in aggregate. Chain sees{' '} {operator_id, period_id, count}{' '} — never per-receipt detail. Fraud detection via statistical auditing, not per-redemption traces.
Production Readiness
The HMAC-SHA256 placeholder requires the verifier to know the citizen's secret — that is NOT private. Production replaces it with a blind-sig scheme that verifies without learning the secret.
The cryptographic scheme decision (RSA blind sigs vs BBS+ vs U-Prove vs Idemix) is open per IMPLEMENTATION_PLAN §6.4.
); }