The Blind Machine

Allele Frequency with Variance

1.0.0 Ed25519 signed

Application digest — content address of the signed/ payload

b48cdffa32c46d2a5de95010ea12e434593b2af2179fcedf7f8e36ebc7245eec

98 lines · 5.63 KB · sha256:be84ccf56b84…28e338f5

# Security notes — `allele_frequency_with_variance`Scoped to this bundle. The platform-wide threat model lives in`docs/manifesto.md`, `docs/requirements.md`, and `docs/simulation_mode.md` §5.Kerckhoffs applied to a product: **no guarantee rests on the secrecy — or thehonesty — of the server.** Don't trust, verify.This is the multiplication-supporting sibling of the flagship: same inputs, butthe server SQUARES an encrypted value. The trust boundary is unchanged — theserver still holds no secret key and still returns only ciphertext.## Trust classes (what may cross the wire)| class | example artifact | may leave the owner's machine? ||-------|------------------|-------------------------------|| RAW | `raw.json` genotypes | **no** || ENCODED | `encoded.json` dosage vector | **no** || PRIVATE | `secret_context.tenseal` (secret key), `plain.json` | **no, ever** || ENCRYPTED | `cipher.bin`, `result.bin` (one BMCT1 container packing sum_g + sum_g2) | yes || PUBLIC | `public_context.tenseal` (secret key stripped; relin keys retained) | yes |Only ENCRYPTED and PUBLIC are ever uploaded. `00_keygen.py` writes the secret keyto `secret_context.tenseal`, which is used **only** by `40_decrypt.py` on theresearcher's machine. There is no `/api/v1` endpoint that accepts a secret key.## The public context carries relin keys — and that is safeUnlike the additive flagship, the published public context includes**relinearization keys**. Relin keys are a public evaluation key: they let theserver relinearize a degree-3 product ciphertext (the result of ct × ct) back todegree 2. They reveal **nothing** about any plaintext and cannot decrypt — onlythe secret key can. The server needs them purely to perform the square. **NoGalois (rotation) keys are generated**: the square is element-wise per slot, sothere is never a cross-slot rotation. Withholding Galois keys keeps the server'scapability minimal — it can add and element-wise square, nothing else.## Server holds no secret key`30_compute_encrypted.py` — the only server-side stage, a kit shim that runs`server.py`'s `compute` — loads the **public**context plus ciphertexts, homomorphically adds, and homomorphically squares(relin). It defensively refuses a context that carries a secret key(`context.is_private()` → error). The server therefore never sees a singleplaintext genotype; it operates on ciphertext and returns ciphertext (two blobs:`sum_g` and the server-derived `sum_g2`). Decryption happens only where thesecret key lives: locally.## Server-derived second moment — integrity, not blind trust`sum_g2` is computed **by the server, under encryption**, from the same `g`ciphertexts. The researcher never has to trust the server got the square right:the released `sum_g2` is bit-exact-verifiable against the cleartext oracle insimulation (`docs/simulation_mode.md`), and the compute is deterministic, sore-execution reproduces a bit-identical result digest. Squaring server-side (vsthe client sending `g²`) means the contributor payload stays minimal and thesecond moment can never be a client-fabricated value inconsistent with `g`.## The append-1 sentinel is NOT a MACBoth result vectors' trailing sentinel slot decrypts to the exact contributorcount N (sum path `Σ 1 = N`; square path `Σ 1² = N`), and `50_decode.py`cross-checks that the two agree. Dropping one upload yields N−1 in both (test:`test_sentinel_tracks_dropped_upload`). It catches **mechanical corruption /miscounting** — it gives **no** guarantee that contributions are distinct,genuine, or non-Sybil. Call it what it is: an integrity check, not authenticity.## What FHE here does and does not hide- **Hides:** individual genotype vectors from the server (inputs are ciphertext),  and the individual second moments (the server never decrypts `g²` per person).- **Does not hide:** the released aggregates themselves (`sum_g`, `sum_g2`, and  the derived mean/variance), and metadata (researcher identity, participant  count/timing, ciphertext sizes, protocol choice).- **Differencing (K vs K+1):** the *statistics* leak an individual if you can  compute `A_{K+1} − A_K` — and because BOTH moments are released, an attacker who  can difference recovers both `g` and `g²` for the marginal contributor.  `aggregate_only` + `min_contributors ≥ 30` (higher than the flagship's 20) +  `allowed_runs_per_project: 1` (cohort freeze + min-N + run cap) **mitigate**  this; they are not a complete defense. Overlapping/Sybil differencing across  separately frozen cohorts needs DP + cross-job query budgets (v2). Documented,  not hand-waved — see `docs/simulation_mode.md` §5.- **Verify-by-re-execution is determinism, not zero-knowledge.** Re-running  `30_compute_encrypted.py` on the same ciphertexts reproduces bit-identical  result digests; it proves the computation, it is not a ZK proof.## Exactness / parameter safetyBFV is exact in `Z_t`. The plaintext modulus must satisfy `t > max coordinatevalue`. Here the second moment dominates: `max sum_g2 = 4·N` (each `g² ≤ 4`). Thedefault `t = 786433` (a 20-bit batching prime, `≡ 1 (mod 32768)` as required atn=16384) stays exact for N up to ~196k; a real run at larger N must raise `t` (orthe simulation feasibility sweep will report `infeasible-at-these-params` onoverflow). Per-contributor `g² ≤ 4` and the sentinel sum N are both `≪ t`.**Noise budget:** the coeff-modulus chain `[60, 40, 40, 60]` gives twomultiplicative levels; the single depth-1 square consumes one, leaving headroom.A depth-2 circuit would need a longer chain (and a larger ring for the samesecurity), which is precisely the cost the benchmark matrix quantifies.

Packaged support file for application digest b48cdffa32c4…c7245eec. It ships in the archive for review, but is outside the signed payload digest.

Keyboard shortcuts

  • Cmd/Ctrl+K
    Focus global search
  • ?
    Open keyboard shortcuts

Send feedback

We'll only use this to respond to your feedback.