Threat model
audience: contributors
This chapter restates the paper’s adversary model (§3.3) against the
concrete objects that exist in our prototype, and gives proof sketches
for the claims we make. The claims are scoped to one zipnet
instance — the committee Group<CommitteeMachine> identified by
INSTANCE.derive("committee") for a given operator-chosen name
(see design-intro — Instance-salt discipline).
Distinct instances on the same universe have disjoint GroupIds,
disjoint rosters, and disjoint anonymity sets; what holds for one
says nothing about another. Multi-instance composition is out of
scope here.
Goals and non-goals
Goal: unlinkability of (author, message) for messages published in
the Broadcasts collection, against any adversary that controls at most
N_S − 1 of N_S committee servers, the aggregator, the TEE host (of
an unbounded subset of clients), and the network. The adversary does
not control a strict majority of the honest clients. (The precise
(t, n)-anonymity formulation is in Appendix A of the paper.)
Non-goals:
- Byzantine fault tolerance of the consensus layer. Mosaik’s Raft variant is crash-fault tolerant, not Byzantine.
- Availability under any adversarial committee participation. In v1, a single crashed committee server halts round progression.
- Confidentiality of application payload. Once finalized,
broadcastis world-readable by design. - Resistance to message-length side channels (see security checklist).
Attacker powers
What the adversary can do:
- Read and modify any packet on the wire. iroh/QUIC authenticates peer identities, so the adversary cannot impersonate an honest node, but can block, delay, or corrupt packets (triggering Raft timeouts and stream reconnects).
- Control the operating system of any non-TEE node, including committee servers it is designated to operate.
- Issue arbitrary
Commands to the committee via a corrupt server (which forwards its own commands into the Raft log) or via a corrupt client (which sends arbitraryClientEnvelopes through the aggregator). - Compromise the TEE of any number of clients (and read their DH secrets) in the v1 mock path.
What the adversary cannot do (by assumption or by protocol):
- Compromise the TEE of a client in the v2 TDX path without triggering attestation failure. (Formal: SGX/TDX bound by the hardware root of trust.)
- Compromise the DH secret of every committee server simultaneously — anonymity requires at least one honest server.
- Force a
BroadcastRecordto contain aparticipantslist that includes an unregisteredClientId: the state machine rejects such an aggregate atSubmitAggregateapply time (see committee state machine).
Anonymity sketch
Let C₁, ..., C_N be the clients participating in round r. Each client
C_i contributes msg_i ⊕ (XOR over servers of pad_ij) to the
aggregate. The aggregate is:
agg_r = XOR_i (msg_i ⊕ XOR_j pad_ij)
= (XOR_i msg_i) ⊕ (XOR_i XOR_j pad_ij)
The broadcast is agg_r ⊕ (XOR_j partial_j) where partial_j = XOR_i pad_ij. Substituting:
broadcast = (XOR_i msg_i) ⊕ (XOR_i XOR_j pad_ij) ⊕ (XOR_j XOR_i pad_ij)
= (XOR_i msg_i) // the inner pads cancel
So the broadcast is exactly the XOR of every client’s slotted message. Given the deterministic slot assignment, messages land in distinct slots (modulo collisions) and can be read back slot-by-slot.
For unlinkability: given any one honest server j* whose pad secrets
are unknown to the adversary, every pad_{ij*} is PRF-indistinguishable
from uniform random (under the PRF security of the HKDF-AES
construction). Each honest client’s envelope_i = msg_i ⊕ XOR_j pad_ij
is therefore PRF-indistinguishable from uniform — the adversary cannot
distinguish which honest client authored which envelope. This is the
standard DC-net anonymity argument under the any-trust assumption.
The paper strengthens this to a (t, n) game (Appendix A). The
state-machine-level permutation check at SubmitAggregate apply ensures
the aggregate’s participants vector is a subset of the round’s client
roster: any participants shuffle by the adversary is a subset of
already-known IDs, so the permutation is within the honest anonymity set.
Integrity: what the state machine guarantees
- A committed
BroadcastRecordis the result of exactly oneSubmitAggregatefollowed by exactly oneSubmitPartialper committee member in that round’sserverssnapshot. No partial is double-counted; no aggregate is re-applied. - Every published
broadcastin the log is computable deterministically from the committed commands. A replay (e.g. after a committee server restart) produces the identical byte sequence.
Integrity: what the state machine does not guarantee
-
The honesty of the aggregator’s fold. A malicious aggregator can:
- omit an envelope (DoS a specific client),
- include a garbage envelope attributed to a real client’s
ClientId(see below), - lie about the
participantslist.
The state machine rejects a
SubmitAggregatewhoseparticipantsset is not a subset of theLiveRound.clientsroster, preventing the aggregator from naming rogue clients. It does not reject an aggregator that names honest clients whose envelopes were never received — but in that case the partial unblinds will remove the expected pads, and the slot of the missing client will show noise (sincemsg_i = 0was not what the honest client sent).A malicious aggregator cannot break anonymity; it can only degrade availability and introduce noise into specific slots.
-
The honesty of a committee server’s partial. A malicious server can submit a garbage
partial. The broadcast will be XORed with that garbage and published as garbage. The state machine has no way to detect this — DC-net unblinding does not carry a zero-knowledge proof. This is consistent with the paper: malicious servers break availability, not anonymity.A v2 mitigation (not in v1) is an anti-disrupter phase modeled on Riposte’s auditing or Blinder’s MPC format check.
Failure modes that break anonymity (not in the adversary model)
- All committee servers collude. By assumption the any-trust model is void; anonymity is lost. Operators must enforce the any-trust diversity axiom out of band.
- The same DH secret is used across roles. Re-using a
DhSecretbetween a committee server and a client (a pathological misconfiguration) would let the server correlate its own client envelopes with its own partial unblinds. TheClientId/ServerIdtype separation guards against this at the type level. - Traffic analysis across rounds. ZIPNet per se does not defend against a global passive adversary who correlates client connection times across many rounds. This is a transport-level concern and is inherited from mosaik’s iroh transport.
- Universe-level co-location. Running on the shared mosaik
universe (Shape B in design-intro) does not
weaken the anonymity argument: admission to the committee group and
to the public write-side streams is gated per-instance by
TicketValidatorcomposition (BundleValidator<K>today,+ Tdx::new().require_mrtd(...)in the TDX path). A peer on the universe who does not present the expected bundle — or MR_TD — is not admitted to the bond, and therefore cannot submit aCommand, a partial, or a client envelope. The universe topology is a discovery-scope decision, not a trust-scope decision.
Denial-of-service surface
| Attacker | Attack | Effect |
|---|---|---|
| Compromised TEE | Flood envelopes | Aggregator backpressures, drops lagging stream senders (mosaik TooSlow code 10_413) |
| Compromised aggregator | Omit / delay aggregates | Rounds stall until the committee’s round_deadline fires |
| Compromised committee server | Omit partial | Round never finalizes; operator intervenes or the server is rotated out |
| Compromised committee server | Submit malformed partial | Broadcast is garbage for this round; next round is clean |
| Network | Drop / delay packets | Raft heartbeats time out, election thrashes, rounds delayed |
All of these are availability issues and none of them break anonymity of past or future rounds.