The jammed OMA model now matches the transmit chain the paper
describes, the key-length sweep averages the eavesdropper over eight
substitute-key draws, and verify_math gains the coded-OMA outage
reference, symbolic checks of the three algebraic identities, and the
cross-period remainder of Proposition 2. The README records the energy
and channel conventions.
The ciphertext-only check trained its own L=16 model and printed only a
verdict; it now attacks the main configuration and writes
data/cov_attack.csv, which the manuscript cites.
diag_maskdegen writes data/maskdegen.csv so the claim it supports is
traceable; the legend guard inflates by the marker radius and refuses a
legend that leaves the canvas; one legend size on every figure.
Every OMA reference takes the L/16 combining gain so the comparison
stays resource matched, four hardcoded copies of the configuration are
replaced by MAIN_D or the main curve, and stage_J's K-by-L Gaussian
draw becomes its exact scalar Beta equivalent.
stage_F was missed in the structured-family regeneration, so sec_brute.csv
and sec_sens.csv still carried learned-family results. Re-running it moves
the L=16 brute-force point from 0.7495 to 0.5916, which now agrees with
sec_brute_cmp.csv rather than contradicting it.
make_tables.py bolds the Walsh-Hadamard row the way it already bolds the
proposed and invariant rows, since that family is the main configuration.
Unconstrained key training converged to disjoint sparse supports: 99
percent of each users key energy sat on three or four of the sixteen
entries, with pairwise disjoint supports and one numerically dead
codebook column. That is an orthogonal slot allocation, so the
superposition collapsed into OMA and the key space was far smaller than
the dense direction the brute-force study assumes.
The main configuration is now the structured Walsh-Hadamard family,
which is dense, exactly orthogonal, unit modulus, and already the best
family in the key-family table. base_keys generalizes to any key length
by truncating the next power-of-two Sylvester order, and the key-length
sweep keeps only lengths where the truncated rows stay exactly
orthogonal, verified numerically.
Also fixes the M-PAM energy normalization in oma_ser_keylen, which used
sqrt(6g/(M^2-1)) where unit average symbol energy gives A^2=3/(M^2-1);
the closed form was 3 dB optimistic and now reproduces a direct Monte
Carlo to 1e-5.
Results move accordingly: the proposal now stays below OMA at every SNR
and reaches 1.52x at key length 64, while the jamming margin falls to
5.5-6.3 dB and the brute-force curve to 0.59 at a million guesses.
Resource-match the OMA reference in the key-length sweep (oma_ser_keylen),
which gives it the L/16 combining gain the longer frame allows. The
proposal now passes a resource-matched OMA by 1.27x at L=64 rather than
the 4.3x reported against a fixed-d reference.
Densify the JSR, sensitivity, and brute-force grids so the curves are
smooth, give the index cipher its channel floor instead of error-free
reception, and add the permutation-key known-plaintext attack
(exp_permkpa) so Fig. 7 carries a conventional linear scheme.
Add check_cov_attack.py and check_cov_ceiling.py: a referee raised a
ciphertext-only second-order attack; the exact-population test shows the
received covariance leaks only a sparse rank-deficient subset of the key
Gram and leaves the eavesdropper at the random-guess level.
Dump verify_math.csv, move the superseded V=256 pilot CSVs to data/pilot.
Give the orthogonal-access jammer its own Rayleigh channel in
oma_ser_jammed, matching the convention every simulated scheme already
used. Without it the closed-form curve faced a jammer at full power in
every frame while the Monte Carlo curves faced a fading one, which
inverted the ordering of the comparison.
Measure the outsider error rate for the fixed-key and naive-refresh
cases as well, and emit the two refresh tables from make_tables.py, so
no cell of the paper is hand-typed.
Derives each block key from the transformations that leave the decision
statistic invariant: a global sign per frame entry, a relabeling of the
frame entries applied to keys and codebook together, and a permutation
of which user holds which row. The legitimate error rate is unchanged
at 0.257 across 24 blocks while a refresh that installs fresh
orthogonal keys reaches 0.710, and a key recovered by known plaintext
returns to the random-guess level one block later.
- exclude the all-ones Walsh-Hadamard row and test every key family
against the all-ones guess
- pass the model dimension to the noise scaling so the key-length sweep
runs at a fixed per-dimension SNR
- known-plaintext attack with nested accumulation and common random
numbers, averaged over 40 collections
- key sensitivity and brute-force search extended to the permutation
key and the index cipher
- make_tables regenerates all three result tables from the CSVs
Reproducibility package for the TIFS submission: transmit and receive
core, security stages (eavesdropper, jamming, key families, attack
difficulty, known-plaintext), real BERT token streams, closed-form
verification, and the scripts that regenerate every figure and table
from the released CSVs.