preliminary series

research

protecting content is the easy part. what this work measures is how much an observer who sees only timings and volumes can still learn, and what it costs to take that away.

flows
10
relays
3
suite
c25519
runs per configuration
5 x 30 s
statistic
median

the table and figures remain passive-attack results measured on revision 2078098 in three sets: main gives the rows without protection and with cover on top, rates the rows with a constant rate at the client, and paced the rows with relays on their own clocks. each client starts its schedule at a random phase. as a consistency check, the paced set repeats the client-only runs: its medians at a 10 ms window, auc 0.922 at 70 ms and 0.946 at 35 ms, lie within the run-to-run range of the rates set, 0.890 to 0.965 and 0.907 to 0.984. relays and clients run in one process on loopback, so there is no network delay. the last relay echoes every message: the conversation of two clients through a mailbox does not enter these numbers. with five runs per point no difference is claimed as significant; the full series of thirty runs per point is still to come.

the observer only sees when frames cross.

it watches the entry link and the last link between relays, counts frames per time window for every flow, and correlates every entry flow with every exit flow. the window is its choice, so both 10 ms and 100 ms are scored. chance is auc 0.5 and top-1 10%.

attack auc against bandwidth between relays and against round-trip latency, for cover on top, a constant rate at the client and relays on their own clocks
protectionbandwidth between relaysmedian round tripauc, 10 msauc, 100 mstop-1, 10 ms
nonex1.000.146 ms1.0001.000100%
cover on top, +2xx2.990.131 ms1.0001.000100%
constant rate at the client, 70 msx2.8548 ms0.9510.95170%
constant rate at the client, 35 msx5.6920 ms0.9620.93770%
relays on their own clocks, 66.5 msx3.00187 ms0.5620.4635%
relays on their own clocks, 33.25 msx6.0088 ms0.5540.48715%
both, client 70 ms, relays 66.5 msx3.00230 ms0.4620.4423%
both, client 35 ms, relays 33.25 msx5.99108 ms0.6730.47220%

what the series shows.

cover on top does not help.

cover traffic added on top of real messages does not help at all: even at three times the bandwidth every flow is linked.

a constant rate at the client does not hide a flow.

each client ticks with its own phase, and the phase crosses a chain of relays that forward at once. with a 10 ms window the attack links flows at every period: the auc medians lie between 0.93 and 0.99. at 100 ms the auc falls to between 0.50 and 0.55 only where the period divides the window, at 25, 50 and 100 ms, and stays at 0.77 to 0.95 elsewhere: with a dividing period nearly all scores tie, which says nothing about protection.

relays on their own clocks lower this attack.

the attack counts cells only: the moments the connections of a circuit open and close match along the chain and are not part of it yet. its auc medians lie between 0.44 and 0.67, against 0.94 to 1.00 in the other rows, but these runs cannot show that it is at chance: four of the eight medians lie outside 0.45 to 0.55, and such a claim needs an equivalence interval inside that band, with the quantity and margin fixed before the series, which five runs cannot give. the 95% interval of a single run includes 0.5 in 33 of 40 cases; of the other seven, three lie above and four below. five runs of ten flows cannot tell a small remaining leak from none; the full series is to settle it. the price is a constant stream on every link a relay sends on and about 2.7 to 2.8 node periods added to a round trip: 187 ms at 66.5 ms, 88 ms at 33.25 ms. in the rows with both measures, the relay period is 5% shorter than the client's, so a missed tick is caught up; the rows with relay clocks alone use the same relay periods with a client that sends at once.

the entry node is not modelled.

the observer watches two links and does not model the entry node, which sees the client's cells directly. whether a constant client rate hides from it the moments the client sends is not measured.

attack auc against the client's cell period for a 10 ms and a 100 ms window

what is measured, and what is planned.

key material
measured: exact contiguous 32-byte occurrences per selected client cell key in exported go Object payloads. at active/closed-now/closed-1s: c25519 none 3/3/3 and all 2/2/2; gost none 3/3/3 and all 1/0/0. every key in every child had that count. each condition planned and evaluated 30 fresh processes; all 360 evaluated, no exclusions. revision eddddb2, optimized go 1.27.3, linux/amd64. c25519 all remained observable after close; gost zeros do not prove erasure. external acquisition, disk/swap/history and other secrets remain unmeasured beyond v0.4.0.
forward secrecy
unit tests check that a setup cell stops opening once the node releases the onion key it was built for. opening setup cells recorded by a neighbour with keys taken from node memory, by recording age, remains unmeasured and deferred beyond v0.4.0. the cooperative client assay never decrypts recorded traffic.
metadata
a traffic correlation attack links the flows on the entry link to the flows on the last link between relays from cell timings and counts alone. auc, top-1 accuracy and tpr at fpr 0.01 are reported against cover traffic rate, a constant client rate and relays on their own clocks. node delay levels, message size classes and the topology of a conversation, two entries and the mailbox, are planned.
timing watermark
historical c25519 series f0f1885, optimized go 1.27.3: 960 completed executions in 40 repeat blocks. correct declaration with original-circuit responsiveness was 40/40 without relay pacing in each client mode and 0/40 at each tested positive period. at 25, 47.5, 50 and 52.5 ms the target stayed responsive in 40/40 of each active/sham condition; at 75 ms all six circuits closed in every one of 160 executions, availability loss. seven wrong active and seven sham declarations remain; immediate unpaced sham had 4/40. every denominator belongs to one mode, period and arm. the passive table keeps its separate revision.
partial compromise
how often a randomly drawn chain meets rogue nodes is computed and sampled with the client's own choice. a node's route knowledge is derived from the protocol, and a real-node lab test checks the trust boundary. the remaining full measurements of what nodes see and link are required for v0.4.0, in design and not implemented.
cost
round-trip latency through the chain, the bandwidth multiplier of cover and padding, and benchmarks of key agreement, signing and sealing a cell, gost versus x25519. node throughput, goodput per client and the cost of memory locking are planned.

series are run with the kind cluster stopped and no build on the host; every row of a correlation report records the load inside the vm the lab runs in, the seeds and the code revision. the seeds fix the client schedules, not the run: in the paced set, run twice with the same seeds and image, one relay-clock median moved by about 0.15. the round trip without protection or with cover only is below a millisecond and differs between sets by about 0.01 ms, so its last digits carry no meaning.

method and adversary models