diff --git a/code/check_consistency.py b/code/check_consistency.py index d03417b..23ea793 100644 --- a/code/check_consistency.py +++ b/code/check_consistency.py @@ -1,14 +1,17 @@ # -*- coding: utf-8 -*- -"""Final consistency check: every headline number vs its raw CSV.""" +"""Final consistency check: every headline number vs its raw CSV. + +A quoted value that goes stale during a revision is the failure mode this +guards against, so each assertion recomputes from data/ rather than from +another quoted value. The manuscript-side assertions are skipped when +main.tex is absent, which is the case in the reproducibility package. +""" import csv import math import re from pathlib import Path base = Path(__file__).resolve().parents[1] -# The manuscript is not part of the reproducibility package, so the -# tex-side assertions are skipped when it is absent and the data-side -# assertions still run. _tex_path = base / "main.tex" HAVE_TEX = _tex_path.exists() tex = _tex_path.read_text(encoding="utf-8") if HAVE_TEX else "" @@ -38,56 +41,100 @@ def chk(label, cond, detail, needs_tex=False): print("headline numbers vs raw data") -# 1.27x key-length ratio +# --- Fig. 2: the proposal is below OMA ------------------------------- +sn = rows("sec_snr.csv") +lg = [float(x["legit"]) for x in sn] +om = [float(x["oma"]) for x in sn] +rel = [(a - b) / b * 100 for a, b in zip(lg, om)] +chk("legit below OMA at every SNR", max(rel) < 0, "max relative %+.2f%%" % max(rel)) +chk("gain 1.3 to 7.9 percent", + round(-max(rel), 1) == 1.3 and round(-min(rel), 1) == 7.9, + "%.2f to %.2f percent" % (-max(rel), -min(rel))) +chk("1.3 and 7.9 in tex", "$1.3$ to\n$7.9$~percent" in tex or "$1.3$ to $7.9$~percent" in tex, + "searched tex", needs_tex=True) +ew = [float(x["eve_wrong"]) for x in sn] +ch = float(sn[0]["chance"]) +chk("outsider at chance to 2e-5", max(abs(x - ch) for x in ew) < 2e-5, + "max deviation %.2e" % max(abs(x - ch) for x in ew)) + +# --- Fig. 3: key-length ratio ---------------------------------------- k = rows("sec_keylen.csv") r64 = [x for x in k if int(x["L"]) == 64][0] ratio = float(r64["oma"]) / float(r64["legit_ser"]) -chk("key-length ratio 1.27", round(ratio, 2) == 1.27, "%.4f" % ratio) -chk("1.27 in tex", tex.count("1.27") >= 2, "%d occurrences" % tex.count("1.27"), needs_tex=True) +chk("key-length ratio 1.52", round(ratio, 2) == 1.52, "%.4f" % ratio) +chk("1.52 in tex", tex.count("1.52") >= 2, "%d occurrences" % tex.count("1.52"), + needs_tex=True) +chk("keys exactly orthogonal in the sweep", + max(float(x["mask_xcorr"]) for x in k) < 1e-6, + "max xcorr %.2e" % max(float(x["mask_xcorr"]) for x in k)) -# blind-jammer gap +# --- Fig. 4: jamming -------------------------------------------------- g = col("sec_jam_gap.csv", "gap_db") -chk("gap 7.4-8.1 dB", round(min(g), 1) == 7.4 and round(max(g), 1) == 8.1, +chk("gap 5.5-6.3 dB", round(min(g), 1) == 5.5 and round(max(g), 1) == 6.3, "%.3f to %.3f" % (min(g), max(g))) -chk("no stale 8.5 dB", "8.5$~dB" not in tex, "searched tex", needs_tex=True) lin = (10 ** (min(g) / 10), 10 ** (max(g) / 10)) -chk("about six times power", lin[0] < 6.5 and lin[1] > 5.5, +chk("about four times power", lin[0] < 4.5 and lin[1] > 3.4, "%.2f to %.2f" % lin) - -# blind vs permutation j = rows("sec_jam_cmp.csv") dmax = max(abs(float(r["blind"]) - float(r["perm_blind"])) for r in j) chk("within 0.002", dmax <= 0.002, "%.5f" % dmax) -chk("no stale 0.0015 in jamming", "$0.0015$ of the proposed" not in tex, "ok", needs_tex=True) +chk("no stale 8.1 dB", "$8.1$~dB" not in tex, "searched tex", needs_tex=True) -# brute force +# --- Fig. 6: brute force --------------------------------------------- b = rows("sec_brute_cmp.csv") sm = float(b[-1]["ser_mask"]) -chk("brute 0.76 both places", tex.count("$0.76$") >= 2, "%.4f measured" % sm, needs_tex=True) -chk("no stale 0.75 in summary", - "$0.75$ after $10^{6}$" not in tex, "summary row", needs_tex=True) +chk("brute 0.59 at 1e6", round(sm, 2) == 0.59, "%.4f" % sm) +chk("0.59 in tex", "$0.59$" in tex, "searched tex", needs_tex=True) +pad0 = next((x["K"] for x in b if float(x["ser_pad"]) < 0.27), None) +chk("index cipher collapses at 65536", pad0 == "65536", str(pad0)) -# refresh -rs = {r["scheme"]: r for r in rows("refresh_summary.csv")} +# --- Fig. 7: known plaintext ----------------------------------------- +kp = rows("kpa.csv") +legit = float([x for x in k if int(x["L"]) == 16][0]["legit_ser"]) +thr = legit * 1.02 +first20 = next((x["n_frames"] for x in kp + if int(x["snr_db"]) == 20 and float(x["eve_ser"]) <= thr), None) +first10 = next((x["n_frames"] for x in kp + if int(x["snr_db"]) == 10 and float(x["eve_ser"]) <= thr), None) +chk("KPA five frames at 20 dB", first20 == "5", "first N = %s" % first20) +chk("KPA twenty-four frames at 10 dB", first10 == "24", "first N = %s" % first10) +pk = rows("pkpa.csv") +p6 = float([x for x in pk if x["n_frames"] == "6"][0]["eve_ser"]) +chk("perm KPA at N=6 near its own 0.258", abs(p6 - 0.258) < 0.005, "%.4f" % p6) + +# --- refresh ---------------------------------------------------------- +rs = {x["scheme"]: x for x in rows("refresh_summary.csv")} chk("refresh 64.8 bits", round(float(rs["Invariant"]["entropy_bits"]), 1) == 64.8, "%.3f" % float(rs["Invariant"]["entropy_bits"])) chk("fixed key 15.0 bits", round(float(rs["None (fixed key)"]["entropy_bits"]), 1) == 15.0, "%.4f" % float(rs["None (fixed key)"]["entropy_bits"])) +chk("invariant refresh free", + abs(float(rs["Invariant"]["legit"]) - float(rs["None (fixed key)"]["legit"])) + < 0.001, "%.4f vs %.4f" % (float(rs["Invariant"]["legit"]), + float(rs["None (fixed key)"]["legit"]))) -# permutation KPA -pk = rows("pkpa.csv") -p6 = float([r for r in pk if r["n_frames"] == "6"][0]["eve_ser"]) -chk("perm KPA at N=6 near 0.303", abs(p6 - 0.303) < 0.005, "%.4f" % p6) +# --- real tokens ------------------------------------------------------ +import json +st = json.loads((base / "data" / "real_sec_stats.json").read_text()) +rec = st["recovery"]["28"] +chk("headline recovery 78 vs 76 percent", + round(rec["legit"] * 100) == 78 and round(rec["oma"] * 100) == 76, + "%.1f vs %.1f" % (rec["legit"] * 100, rec["oma"] * 100)) +chk("legit leads OMA at every point", + all(st["recovery"][s]["legit"] > st["recovery"][s]["oma"] + for s in st["recovery"]), + "checked %d points" % len(st["recovery"])) -# abstract +# --- abstract --------------------------------------------------------- a = (tex.split(r"\begin{abstract}")[1].split(r"\end{abstract}")[0].strip() if HAVE_TEX else "") w = len(re.split(r"\s+", a)) if a else 0 chk("abstract <= 250 words", w <= 250, "%d words" % w, needs_tex=True) chk("abstract has no abbreviations", - not re.findall(r"\b[A-Z]{2,}\b", a), str(re.findall(r"\b[A-Z]{2,}\b", a)), needs_tex=True) + not re.findall(r"\b[A-Z]{2,}\b", a), str(re.findall(r"\b[A-Z]{2,}\b", a)), + needs_tex=True) print() print("ALL CONSISTENT" if ok else "INCONSISTENCIES FOUND") diff --git a/code/exp_full.py b/code/exp_full.py index 11a6c19..f307a04 100644 --- a/code/exp_full.py +++ b/code/exp_full.py @@ -149,9 +149,43 @@ def get_model(P=4, vu=16, d=64, U=4, iters=4000, seed=1, freeze_W=None, tag=""): return m +def base_keys(U: int, Lp: int) -> torch.Tensor: + """The structured key family: U non-constant rows of a Walsh-Hadamard + matrix, truncated to Lp entries. + + Row 0 of the Sylvester construction is the all-ones vector, which any + adversary can write down without searching, so the users take rows + 1..U. The construction exists at power-of-two orders, so for other + key lengths the next power-of-two order is truncated to Lp entries. + That truncation keeps the entries unit modulus and, at every length + the evaluation uses, keeps the rows exactly orthogonal as well; the + measured cross-correlation is reported alongside every sweep point. + Requires U <= Lp - 1 non-constant rows to exist.""" + n = 1 << max(math.ceil(math.log2(max(Lp, U + 1))), 1) + H = hadamard(n) + if H.shape[0] - 1 < U: + raise ValueError(f"key length {Lp} admits only {H.shape[0]-1} " + f"non-constant rows, fewer than U={U}") + return torch.tensor(H[1:U + 1, :Lp].copy(), dtype=torch.float32) + + +def main_model(iters=4000, P=4, vu=16, d=64, U=4): + """The main configuration used by every stage below. + + The keys are frozen to the structured Walsh-Hadamard family rather + than learned. Unconstrained mask training converges to disjoint + sparse supports, that is, to an orthogonal slot allocation, which + collapses the superposition into OMA and leaves the key space far + smaller than a dense direction in R^L. The structured family is + dense, exactly orthogonal, and unit modulus, which is also the + condition the key-refresh invariance argument requires.""" + return get_model(P=P, vu=vu, d=d, U=U, iters=iters, + freeze_W=base_keys(U, d // P)) + + def stage_A(): print("[A] security vs SNR (V=65536) ...") - m = get_model(iters=4000) + m = main_model() snr = [float(v) for v in range(0, 21, 2)] frames = 800_000 legit = eval_ser_sse(m, snr, frames=frames) @@ -226,10 +260,14 @@ def oma_ser_keylen(L, snr_db, bits=16, n_grid=200_000): if bits % L: return float("nan") M = 2 ** (bits // L) + # M-PAM levels +-A, +-3A, ..., +-(M-1)A with unit AVERAGE symbol energy + # give A^2 = 3/(M^2-1), so the distance to the decision boundary is A + # and the Q-function argument is h*sqrt(3*g/(M^2-1)). Using 6 instead + # of 3 would assume an average energy of two per dimension. x = (np.arange(n_grid) + 0.5) / n_grid h = np.sqrt(-np.log(1.0 - x)) g = 10.0 ** (snr_db / 10.0) - arg = np.clip(h * math.sqrt(6.0 * g / (M * M - 1.0)), 0, 38) + arg = np.clip(h * math.sqrt(3.0 * g / (M * M - 1.0)), 0, 38) q = (1.0 - 1.0 / M) * np.array([math.erfc(v / math.sqrt(2.0)) for v in arg]) q = np.clip(q, 0.0, 1.0) @@ -239,8 +277,12 @@ def oma_ser_keylen(L, snr_db, bits=16, n_grid=200_000): def stage_B(): print("[B] key length (dense grid so the curve is smooth) ...") rows = [] - for d in [16, 24, 32, 40, 48, 56, 64, 80, 96, 128, 192, 256]: - m = get_model(d=d, iters=4000) + # L = d/P. Lengths 6, 10 and 14 are dropped because the + # truncated Walsh-Hadamard rows are not exactly orthogonal + # there, and L=4 admits only three non-constant rows for + # U=4 users. + for d in [32, 48, 64, 80, 96, 128, 192, 256]: + m = main_model(d=d) # same structured family as Fig. 2 lg = eval_ser_sse(m, [10.0], frames=500_000)[0] ew = eve_wrong_mask(m.users, m.L, seed=20260813).to(DEVICE) ev = eval_ser_eve(m, ew, [10.0], frames=500_000)[0] @@ -255,7 +297,7 @@ def stage_B(): def stage_C(): print("[C] jamming vs JSR ...") - m = get_model(iters=4000) + m = main_model() jsr = [-10.0, -5.0, 0.0, 5.0, 10.0, 15.0, 20.0] blind = eval_ser_jam(m, 10.0, jsr, frames=500_000, mode="blind", target=0) matched = eval_ser_jam(m, 10.0, jsr, frames=500_000, mode="matched", target=0) @@ -280,7 +322,7 @@ def stage_D(): # Walsh-Hadamard rows (orthogonal). Row 0 of the Sylvester # construction is the all-ones vector, which any adversary can write # down, so it is excluded and the users take rows 1 to U. - Hd = torch.tensor(hadamard(Lp)[1:U + 1], dtype=torch.float32) + Hd = base_keys(U, Lp) # the main configuration's key family fams["hadamard"] = Hd ones = torch.ones(U, Lp) # the cheapest possible guess rows = [] @@ -395,7 +437,7 @@ def stage_E(): attacker can BUILD from public knowledge at JSR 0 dB (matched if the masks are public, blind if the PHY structure is secret).""" print("[E] scheme comparison ...") - m = get_model(iters=4000) + m = main_model() F = 400_000 d = m.P * m.L set_seed(20260813) @@ -506,7 +548,7 @@ def stage_F(): rho_max(K, L) is sampled by Monte Carlo and mapped through the measured sensitivity curve of (i).""" print("[F] attack difficulty ...") - m = get_model(iters=4000) + m = main_model() F = 200_000 true_m = m.masks().detach().cpu() gen = torch.Generator().manual_seed(31) @@ -582,7 +624,7 @@ def stage_I(): unknown pad bits, which stay uniform, are all guessed right. """ print("[I] key sensitivity across schemes ...") - m = get_model(iters=4000) + m = main_model() F = 600_000 # more frames per point for a smooth curve TRIALS_MASK = 12 # independent substitute keys per point d = m.P * m.L @@ -726,7 +768,7 @@ def stage_L(): slot assignment is public and needs no key """ print("[L] jamming across schemes ...") - m = get_model(iters=4000) + m = main_model() F = 300_000 d = m.P * m.L gp = torch.Generator().manual_seed(11) diff --git a/code/exp_kpa.py b/code/exp_kpa.py index dd538c3..9788af0 100644 --- a/code/exp_kpa.py +++ b/code/exp_kpa.py @@ -25,7 +25,7 @@ import torch from sse_lib import (DATA, DEVICE, SSE, rayleigh_gain, snr_to_sigma2, set_seed, write_csv, eval_ser_sse) -from exp_full import get_model, eval_ser_eve +from exp_full import main_model, eval_ser_eve SNRS = [0.0, 10.0, 20.0] NFRAMES = [1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 24, 32, 48, 64] @@ -110,7 +110,7 @@ def key_correlation(est: torch.Tensor, true: torch.Tensor) -> float: def main(): set_seed(SEED) - model = get_model(iters=4000) + model = main_model() model.eval() true_m = model.masks().detach() legit = eval_ser_sse(model, [10.0], frames=200_000)[0] diff --git a/code/exp_permkpa.py b/code/exp_permkpa.py index 0c0d13a..cac6907 100644 --- a/code/exp_permkpa.py +++ b/code/exp_permkpa.py @@ -24,7 +24,7 @@ import numpy as np import torch from sse_lib import write_csv, set_seed, DATA, DEVICE -from exp_full import get_model, eval_scheme_permuted_eve, rayleigh_gain +from exp_full import main_model, eval_scheme_permuted_eve, rayleigh_gain try: from scipy.optimize import linear_sum_assignment @@ -44,12 +44,18 @@ except ImportError: # greedy fallback COLLECT_DB = 20.0 DECODE_DB = 10.0 -TRIALS = 20 -EVAL_FRAMES = 100_000 +# The curve's variance is dominated by WHICH positions the recovered +# permutation gets wrong, not by the SER estimate inside one trial: the +# within-trial standard deviation at 50k frames is 2e-3 while the +# trial-to-trial spread is ~1.6e-2. Averaging over many independent +# collections is therefore what smooths the curve, so trials are raised +# and per-trial frames lowered at roughly constant total cost. +TRIALS = 120 +EVAL_FRAMES = 50_000 def main(): - m = get_model(iters=4000) # training needs grad + m = main_model() # training needs grad m.eval() _run(m) @@ -68,7 +74,7 @@ def _run(m): print(f"[P] permutation known-plaintext, collect {COLLECT_DB:.0f} dB, " f"decode {DECODE_DB:.0f} dB ...") rows = [] - for nf in [1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 24, 32, 48, 64]: + for nf in [1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 20, 24, 32, 48, 64]: fr, sr = [], [] for t in range(TRIALS): g = torch.Generator().manual_seed(909 + 1000 * t + nf) diff --git a/code/exp_real_sec.py b/code/exp_real_sec.py index be33794..d95e424 100644 --- a/code/exp_real_sec.py +++ b/code/exp_real_sec.py @@ -29,7 +29,7 @@ import torch import sse_lib as L from sse_lib import (DATA, DEVICE, SSE, rayleigh_gain, snr_to_sigma2, set_seed, write_csv) -from exp_full import get_model, eve_wrong_mask +from exp_full import main_model, eve_wrong_mask SNR_GRID = [0, 4, 8, 12, 16, 20, 24, 28] # headline recovery is meaningful only where the legitimate user clears @@ -136,7 +136,7 @@ def main(): f"distinct tokens, max id {int(ids_all.max())}") # keys and codebook trained on uniform indices, reused unchanged - model = get_model(P=P_MAX, vu=VU, d=64, U=U, iters=4000) + model = main_model(P=P_MAX, vu=VU, d=64, U=U) model.eval() eve_m = eve_wrong_mask(U, model.L, seed=20260813) # outsider diff --git a/code/exp_refresh.py b/code/exp_refresh.py index c508e8e..e817744 100644 --- a/code/exp_refresh.py +++ b/code/exp_refresh.py @@ -45,7 +45,8 @@ import numpy as np import torch from sse_lib import DATA, DEVICE, SSE, write_csv, eval_ser_sse -from exp_full import hadamard, get_model, eval_ser_eve, eve_wrong_mask +from exp_full import (hadamard, get_model, base_keys, eval_ser_eve, + eve_wrong_mask) from exp_kpa import collect_known_plaintext, solve_keys SEED = 5150 @@ -53,13 +54,6 @@ BLOCKS = 24 FRAMES = 300_000 -def base_keys(U: int, Lp: int) -> torch.Tensor: - """The fixed orthogonal key set the codebook is trained around. Row 0 - of the Sylvester construction is the all-ones vector, which any - adversary can write down, so the users take rows 1 to U.""" - return torch.tensor(hadamard(Lp)[1:U + 1], dtype=torch.float32) - - def kdf_invariant(seed: int, block: int, U: int, Lp: int): """Derive one block's key material from the invariance group.""" rng = np.random.default_rng([seed, block]) diff --git a/code/replot_security.py b/code/replot_security.py index edced97..34f6e51 100644 --- a/code/replot_security.py +++ b/code/replot_security.py @@ -11,9 +11,11 @@ Label dictionary is fixed here and copied verbatim into tables and prose. fig_sec_kpa.pdf : eavesdropper SER vs known-plaintext frames (Fig. 7) fig_sec_real.pdf : token error rate on real streams (Fig. 8) -Curves that coincide by construction are drawn deliberately layered, the -lower one wide and semi-transparent and the upper one narrow with open -markers, so every legend entry has a visible curve. +Curves that coincide by construction are drawn deliberately layered: the +lower one wide and semi-transparent, the upper one narrow with open +markers, and their markers staggered to different sample points through +markevery offsets. Marker size is uniform across every figure, so the +stagger, not the size, is what keeps each legend entry visible. """ from __future__ import annotations from pathlib import Path @@ -34,7 +36,7 @@ plt.rcParams.update({ "font.serif": ["DejaVu Serif", "Times New Roman"], "font.size": 9, "axes.labelsize": 9, - "legend.fontsize": 7.4, + "legend.fontsize": 6.6, "xtick.labelsize": 8, "ytick.labelsize": 8, "axes.grid": True, @@ -42,7 +44,7 @@ plt.rcParams.update({ "grid.linewidth": 0.4, "grid.alpha": 0.6, "lines.linewidth": 1.3, - "lines.markersize": 3.4, + "lines.markersize": 4.5, "figure.figsize": (3.15, 2.36), "pdf.fonttype": 42, }) @@ -70,9 +72,9 @@ LBL = { "outsider": "Outsider", } # deliberate-layering style for the LOWER of two coinciding curves -UNDER = dict(lw=2.6, ms=7, alpha=0.85) +UNDER = dict(lw=2.6, alpha=0.85) # thick filled line, layered under # and for the curve riding on top of it -OVER = dict(lw=1.2, ms=4.5, mfc="none") +OVER = dict(lw=1.2, mfc="none") # thin open marker, rides on top def load(name): @@ -106,6 +108,27 @@ def save(fig, name): f"{name}: axis label '{lbl.get_text()}' is clipped " f"(label {b} outside figure {fbox}); shorten the " f"label or widen the margin") + # No curve may pass under the legend box. Reading the code cannot + # reveal this, so the check is made on the rendered geometry, the + # same discipline as the clipping guard above. + leg = ax.get_legend() + if leg is not None: + lb = leg.get_window_extent() + for line in ax.get_lines(): + # full-span reference lines (axhline/axvline) carry axes- + # fraction endpoints [0,1]; they are not data curves and, + # spanning the whole axis, would forbid any bottom legend + xd = list(line.get_xdata()) + if xd == [0, 1] or list(line.get_ydata()) == [0, 1]: + continue + xy = line.get_xydata() + if len(xy) == 0: + continue + for px, py in ax.transData.transform(xy): + if lb.x0 <= px <= lb.x1 and lb.y0 <= py <= lb.y1: + raise RuntimeError( + f"{name}: a data curve passes under the legend " + f"box; move the legend or shrink it") fig.savefig(FIG / f"{name}.pdf") plt.close(fig) print("[OK]", name) @@ -117,11 +140,11 @@ def fig_snr(): fig, ax = plt.subplots() # legitimate and OMA coincide by construction; layered deliberately ax.semilogy(x, col(r, "legit"), color=C_LEGIT, marker="o", ls="-", - label=LBL["legit"], **UNDER) + markevery=(0, 3), label=LBL["legit"], **UNDER) ax.semilogy(x, col(r, "oma"), color=C_OMA, marker="^", ls=":", - label=LBL["oma"], **OVER) + markevery=(1, 3), label=LBL["oma"], **OVER) ax.semilogy(x, col(r, "eve_public"), color=C_PUB, marker="v", - ls="none", markersize=5.2, markerfacecolor="none", + ls="none", markevery=(2, 3), markerfacecolor="none", label=LBL["eve_pub"]) ax.semilogy(x, col(r, "eve_wrong"), color=C_EVE, marker="s", ls="--", label=LBL["eve_key"]) @@ -151,7 +174,9 @@ def fig_keylen(): ax.set_xlabel("Key length $L$") ax.set_ylabel("SER") ax.set_xscale("log", base=2) - ax.legend(loc="center right", bbox_to_anchor=(0.98, 0.72)) + # the curves sweep the upper-left to lower-right diagonal, leaving the + # lower-left corner empty + ax.legend(loc="lower left") save(fig, "fig_sec_keylen") @@ -171,9 +196,9 @@ def fig_jam(): markevery=me, label=LBL["oma"] + ", targeted") # the two blind curves agree to 0.002; deliberate layering ax.plot(x, col(r, "blind"), color=C_LEGIT, marker="o", ls="-", - markevery=me, label=LBL["mask"] + ", blind", **UNDER) + markevery=(0, me), label=LBL["mask"] + ", blind", **UNDER) ax.plot(x, col(r, "perm_blind"), color=C_EVE, marker="s", ls="-.", - markevery=me, label=LBL["perm"] + ", blind", **OVER) + markevery=(me // 2, me), label=LBL["perm"] + ", blind", **OVER) nojam = float(load("sec_jam.csv")[0]["nojam"]) ax.axhline(nojam, color=C_OMA, ls=(0, (1, 3)), lw=0.9) ax.text(max(x) - 0.6, nojam + 0.02, LBL["nojam"], ha="right", @@ -194,11 +219,11 @@ def fig_sens(): x = col(r, "frac") fig, ax = plt.subplots() ax.plot(x, col(r, "ser_mask"), color=C_LEGIT, marker="o", ls="-", - label=LBL["mask"], **UNDER) + markevery=(0, 3), label=LBL["mask"], **UNDER) ax.plot(x, col(r, "ser_perm"), color=C_EVE, marker="s", ls="--", - label=LBL["perm"], **OVER) + markevery=(1, 3), label=LBL["perm"], **OVER) ax.plot(x, col(r, "ser_pad"), color=C_PUB, marker="v", ls="-.", - lw=1.2, ms=4.5, mfc="none", label=LBL["pad"]) + markevery=(2, 3), lw=1.2, mfc="none", label=LBL["pad"]) chance = 1.0 - (1.0 / 16.0) ** 4 ax.axhline(chance, color=C_CH, ls=":", lw=0.9, label=LBL["chance"]) ax.set_xlabel("Fraction of the key recovered") @@ -236,13 +261,13 @@ def fig_real(): fig, ax = plt.subplots() # legitimate/OMA and insider/outsider coincide pairwise; layered ax.semilogy(x, col(r, "ter_legit"), color=C_LEGIT, marker="o", ls="-", - label=LBL["legit"], **UNDER) + markevery=(0, 2), label=LBL["legit"], **UNDER) ax.semilogy(x, col(r, "ter_oma"), color=C_OMA, marker="^", ls=":", - label=LBL["oma"], **OVER) + markevery=(1, 2), label=LBL["oma"], **OVER) ax.semilogy(x, col(r, "ter_insider"), color=C_PUB, marker="v", ls="-.", - lw=2.6, alpha=0.85, ms=7, label=LBL["insider"]) + markevery=(0, 2), lw=2.6, alpha=0.85, label=LBL["insider"]) ax.semilogy(x, col(r, "ter_eve"), color=C_EVE, marker="s", ls="--", - label=LBL["outsider"], **OVER) + markevery=(1, 2), label=LBL["outsider"], **OVER) ax.set_xlabel("SNR (dB)") ax.set_ylabel("TER") ax.set_xlim(min(x), max(x)) @@ -280,7 +305,10 @@ def fig_kpa(): ax.set_xlabel("Known-plaintext frames $N$") ax.set_ylabel("Eavesdropper SER") ax.set_xscale("log", base=2) - ax.legend(loc="upper right") + # the 0 dB curve sweeps the upper-right, so anchor the legend at the + # top edge past the steep drops, above every curve at large N + ax.set_ylim(top=1.18) + ax.legend(loc="upper right", bbox_to_anchor=(1.0, 1.04)) save(fig, "fig_sec_kpa") diff --git a/code/run_remaining.py b/code/run_remaining.py new file mode 100644 index 0000000..ba8dec0 --- /dev/null +++ b/code/run_remaining.py @@ -0,0 +1,28 @@ +"""Run the stages that live outside exp_full, after the main sweep. + +Order matters: exp_refresh trains its own model around the same base keys, +exp_kpa and exp_permkpa attack the main configuration, and exp_real_sec +reuses the main configuration on real token streams. Each writes only CSV. +""" +import runpy +import sys +import time + +STAGES = [ + ("known-plaintext attack", "exp_kpa.py"), + ("permutation known-plaintext attack", "exp_permkpa.py"), + ("key-refresh layer", "exp_refresh.py"), + ("real token streams", "exp_real_sec.py"), +] + +for label, script in STAGES: + print(f"\n{'=' * 60}\n== {label} ({script})\n{'=' * 60}", flush=True) + t0 = time.time() + try: + runpy.run_path(script, run_name="__main__") + except Exception as exc: # keep going, report at end + print(f"[FAIL] {script}: {type(exc).__name__}: {exc}", flush=True) + sys.exit(1) + print(f"[done] {label} in {time.time() - t0:.0f} s", flush=True) + +print("\nall remaining stages complete") diff --git a/data/kpa.csv b/data/kpa.csv index 9a4bdf1..50adcdb 100644 --- a/data/kpa.csv +++ b/data/kpa.csv @@ -1,43 +1,43 @@ snr_db,n_frames,kappa,eve_ser -0,1,0.2374871574,0.99874975 -0,2,0.6126027606,0.96312825 -0,3,0.7285515711,0.921628875 -0,4,0.8244251639,0.85221925 -0,5,0.868628718,0.797125 -0,6,0.8920436099,0.745713875 -0,8,0.9208301157,0.67688775 -0,10,0.9429872826,0.592138625 -0,12,0.9557282105,0.534421875 -0,16,0.9700051412,0.44833975 -0,24,0.9802580416,0.38197025 -0,32,0.9852379695,0.351050875 -0,48,0.9904022858,0.32166525 -0,64,0.993118532,0.307348 -10,1,0.3489475794,0.989224875 -10,2,0.8794977516,0.704872 -10,3,0.9473693997,0.547376875 -10,4,0.9682661489,0.455776875 -10,5,0.9782963678,0.3962285 -10,6,0.9843041778,0.359232 -10,8,0.9900029436,0.326613375 -10,10,0.9934537426,0.306601375 -10,12,0.9949941516,0.2992645 -10,16,0.9965374678,0.291205125 -10,24,0.9978871465,0.285018125 -10,32,0.9984912023,0.28255425 -10,48,0.9990138412,0.280105125 -10,64,0.9992718786,0.279036875 -20,1,0.596763967,0.861350125 -20,2,0.984469898,0.34732075 -20,3,0.9948319912,0.300176375 -20,4,0.9975389287,0.286598125 -20,5,0.9984581739,0.282405125 -20,6,0.9988854468,0.2803655 -20,8,0.9992000297,0.279362875 -20,10,0.9994319767,0.278179625 -20,12,0.9995499209,0.277694875 -20,16,0.9996712342,0.277181875 -20,24,0.9997934118,0.276410875 -20,32,0.999845539,0.2763615 -20,48,0.9999018267,0.276363875 -20,64,0.9999270439,0.276194125 +0,1,0.2506237943,0.998554125 +0,2,0.591645799,0.9303495 +0,3,0.7079962283,0.8537115 +0,4,0.7998725504,0.767802875 +0,5,0.850597313,0.684796 +0,6,0.8767687038,0.6361745 +0,8,0.9171553269,0.520736875 +0,10,0.936547631,0.455442125 +0,12,0.9516445503,0.400028875 +0,16,0.9666089579,0.344806875 +0,24,0.9785378739,0.3075 +0,32,0.9843035683,0.29181625 +0,48,0.989774394,0.27860675 +0,64,0.9924546674,0.272548625 +10,1,0.3695881277,0.986553125 +10,2,0.880338943,0.55928725 +10,3,0.9474378824,0.4139 +10,4,0.9692240357,0.339236625 +10,5,0.9786081538,0.3095635 +10,6,0.9846392065,0.292632375 +10,8,0.9900667578,0.278431375 +10,10,0.9934557095,0.270305 +10,12,0.9948186457,0.267862125 +10,16,0.9963249952,0.264728875 +10,24,0.9976470947,0.26182575 +10,32,0.998370938,0.260598625 +10,48,0.9989489555,0.259409125 +10,64,0.9992221802,0.258898125 +20,1,0.6164694946,0.807168125 +20,2,0.9846389949,0.29904075 +20,3,0.9948147267,0.268233 +20,4,0.9972566783,0.262752625 +20,5,0.9983854383,0.260594375 +20,6,0.9988236457,0.259794 +20,8,0.9991258562,0.259128625 +20,10,0.9993467629,0.258526 +20,12,0.9994955555,0.25809525 +20,16,0.9996308014,0.258118625 +20,24,0.9997742459,0.25761825 +20,32,0.9998249143,0.25777975 +20,48,0.9998879731,0.257699625 +20,64,0.9999218643,0.257602125 diff --git a/data/pkpa.csv b/data/pkpa.csv index 8b67480..238d796 100644 --- a/data/pkpa.csv +++ b/data/pkpa.csv @@ -1,15 +1,17 @@ n_frames,perm_frac,eve_ser -1,0.20234375,0.998977 -2,0.7140625,0.7107255 -3,0.91484375,0.4172725 -4,0.94921875,0.324415 -5,0.9515625,0.340107 -6,0.94765625,0.3034795 -8,0.95625,0.303056 -10,0.95546875,0.3027505 -12,0.94921875,0.3028 -16,0.9546875,0.3036285 -24,0.94921875,0.303151 -32,0.95234375,0.302631 -48,0.95,0.3030415 -64,0.9515625,0.3025125 +1,0.2545572917,0.9990345 +2,0.7299479167,0.8108416667 +3,0.9266927083,0.4801366667 +4,0.9885416667,0.3021165 +5,0.9955729167,0.2737706667 +6,0.9997395833,0.2587145 +7,1,0.2575458333 +8,1,0.2575538333 +10,1,0.2575 +12,1,0.2576706667 +16,1,0.2577931667 +20,1,0.2578143333 +24,1,0.2574975 +32,1,0.2576283333 +48,1,0.2576288333 +64,1,0.2575123333 diff --git a/data/real_sec_stats.json b/data/real_sec_stats.json index 68db78e..136583a 100644 --- a/data/real_sec_stats.json +++ b/data/real_sec_stats.json @@ -10,19 +10,19 @@ "headline_runs": 4, "recovery": { "20": { - "legit": 0.1985369609856263, + "legit": 0.22112422997946612, "eve": 0.0, "insider": 0.0, "oma": 0.19815195071868583 }, "24": { - "legit": 0.5103952772073922, + "legit": 0.5395277207392197, "eve": 0.0, "insider": 0.0, "oma": 0.5160420944558521 }, "28": { - "legit": 0.7630903490759754, + "legit": 0.7804158110882957, "eve": 0.0, "insider": 0.0, "oma": 0.7583418891170431 diff --git a/data/real_sec_ter.csv b/data/real_sec_ter.csv index d40b202..9f02a43 100644 --- a/data/real_sec_ter.csv +++ b/data/real_sec_ter.csv @@ -1,9 +1,9 @@ snr_db,ter_legit,ter_eve,ter_insider,ter_oma -0,0.8937765021,0.9999699976,0.999212437,0.8927576706 -4,0.6685672354,0.9999337447,0.9977085667,0.6680284423 -8,0.3903512281,0.9999224938,0.9958434175,0.3898399372 -12,0.1875025002,0.9999362449,0.9946258201,0.1874349948 -16,0.08110023802,0.9999349948,0.9938970118,0.08109648772 -20,0.03404147332,0.9999337447,0.9936357409,0.03380395432 -24,0.01362108969,0.9999274942,0.9934882291,0.01364484159 -28,0.005464187135,0.9999312445,0.993449476,0.005405432435 +0,0.8789390651,0.9999649972,0.9990586747,0.8927576706 +4,0.6421088687,0.9999537463,0.9975273022,0.6680284423 +8,0.3651042083,0.9999649972,0.9957384091,0.3898399372 +12,0.1726488119,0.9999537463,0.9944920594,0.1874349948 +16,0.07386590927,0.9999337447,0.9938557585,0.08109648772 +20,0.0309237239,0.9999362449,0.9936069886,0.03380395432 +24,0.01248849908,0.9999324946,0.9934769782,0.01364484159 +28,0.004962897032,0.999924994,0.9934394752,0.005405432435 diff --git a/data/sec_brute_cmp.csv b/data/sec_brute_cmp.csv index 033cf91..ed6d503 100644 --- a/data/sec_brute_cmp.csv +++ b/data/sec_brute_cmp.csv @@ -1,15 +1,15 @@ K,ser_mask,ser_perm,ser_pad,best_kappa,best_frac -1,0.9993527855,0.9999542171,0.9999893771,0.1909643153,0.0160546875 -3,0.9977393447,0.9999284847,0.9999681312,0.3326517476,0.0281640625 -10,0.9952796283,0.9998968587,0.9998937706,0.450762326,0.043046875 -30,0.9895360243,0.9998741146,0.9996813118,0.5560672497,0.05375 -100,0.9834025595,0.9998495442,0.998937706,0.6290900875,0.0653125 -300,0.9728417994,0.9998307015,0.996813118,0.688703621,0.0741796875 -1000,0.9568452325,0.9998081233,0.9893770599,0.7427389508,0.0848046875 -3000,0.9366731394,0.9997877864,0.9681311798,0.7822538913,0.094375 -10000,0.9075372546,0.9997705208,0.8937705994,0.8169040678,0.1025 -30000,0.8818766363,0.9997525081,0.6813117981,0.8434367197,0.1109765625 -65536,0.8592861449,0.9997413851,0.303815,0.8592030095,0.1162109375 -100000,0.8443657504,0.9997355745,0.303815,0.8678447033,0.1189453125 -300000,0.802269081,0.9997181429,0.303815,0.8874619916,0.1271484375 -1000000,0.7622180175,0.9997021224,0.303815,0.9034448904,0.1346875 +1,0.9993544844,0.9999768274,0.9999886992,0.1909643153,0.0160546875 +3,0.997243306,0.9999681491,0.9999660976,0.3326517476,0.0281640625 +10,0.9938504211,0.999957483,0.9998869919,0.450762326,0.043046875 +30,0.9845428901,0.9999498125,0.9996609756,0.5560672497,0.05375 +100,0.9739208985,0.999941526,0.9988699188,0.6290900875,0.0653125 +300,0.9540369033,0.9999351712,0.9966097565,0.688703621,0.0741796875 +1000,0.9234069553,0.9999275566,0.9886991882,0.7427389508,0.0848046875 +3000,0.884658701,0.9999206979,0.9660975647,0.7822538913,0.094375 +10000,0.8305012761,0.999914875,0.8869918823,0.8169040678,0.1025 +30000,0.7833179277,0.9999088001,0.660975647,0.8434367197,0.1109765625 +65536,0.7451236968,0.9999050488,0.25939,0.8592030095,0.1162109375 +100000,0.7206406422,0.9999030892,0.25939,0.8678447033,0.1189453125 +300000,0.6546171753,0.9998972103,0.25939,0.8874619916,0.1271484375 +1000000,0.5948033388,0.9998918073,0.25939,0.9034448904,0.1346875 diff --git a/data/sec_compare.csv b/data/sec_compare.csv index d762ce3..212edc8 100644 --- a/data/sec_compare.csv +++ b/data/sec_compare.csv @@ -1,6 +1,6 @@ scheme,legit_ser,eve_out,eve_in,jam0_ser -proposed,0.303585,0.99983,0.99998,0.80612 -public_mask,0.303585,0.303585,0.303585,0.95359 -perm_key,0.303435,0.9999775,0.303435,0.8065225 -index_cipher,0.303585,0.9999847412,0.9999847412,0.95359 +proposed,0.257845,1,0.9999775,0.7719425 +public_mask,0.257845,0.257845,0.257845,0.91675 +perm_key,0.2580675,0.99999,0.2580675,0.7721175 +index_cipher,0.257845,0.9999847412,0.9999847412,0.91675 oma_plain,0.2747696909,0.2747696909,0.2747696909,nan diff --git a/data/sec_jam.csv b/data/sec_jam.csv index 8ab7cfa..eadf12c 100644 --- a/data/sec_jam.csv +++ b/data/sec_jam.csv @@ -1,8 +1,8 @@ jsr_db,blind,matched,nojam --10,0.468186,0.720358,0.302716 --5,0.633112,0.874476,0.302716 -0,0.806548,0.9534,0.302716 -5,0.918778,0.984432,0.302716 -10,0.970874,0.994914,0.302716 -15,0.989928,0.9984,0.302716 -20,0.996858,0.999468,0.302716 +-10,0.41313,0.602758,0.257308 +-5,0.583948,0.79449,0.257308 +0,0.772444,0.917424,0.257308 +5,0.902872,0.97136,0.257308 +10,0.964788,0.990494,0.257308 +15,0.988114,0.99704,0.257308 +20,0.99617,0.999024,0.257308 diff --git a/data/sec_jam_cmp.csv b/data/sec_jam_cmp.csv index ba77a3c..33689b5 100644 --- a/data/sec_jam_cmp.csv +++ b/data/sec_jam_cmp.csv @@ -1,17 +1,17 @@ jsr_db,blind,matched,perm_blind,oma_targeted --10,0.4691233333,0.7203966667,0.4694833333,0.6401244609 --8,0.52954,0.7906333333,0.5275833333,0.7152454705 --6,0.5965433333,0.8503566667,0.59758,0.7840240868 --4,0.6703433333,0.8956333333,0.6699733333,0.8424432091 --2,0.7420833333,0.9283666667,0.7431533333,0.8888838836 -0,0.8070433333,0.9532066667,0.8059933333,0.9237966241 -2,0.8593066667,0.96942,0.85862,0.9488822017 -4,0.9014266667,0.9805533333,0.9025733333,0.9662811712 -6,0.9327633333,0.9872533333,0.9318466667,0.9780307416 -8,0.9549433333,0.9917766667,0.9550866667,0.9858109157 -10,0.9699833333,0.99508,0.9707366667,0.9908905586 -12,0.98118,0.9966966667,0.9804366667,0.9941743502 -14,0.9872866667,0.9979833333,0.9879066667,0.9962827887 -16,0.9922966667,0.99871,0.9921133333,0.9976304229 -18,0.9948766667,0.9992,0.99484,0.9984893291 -20,0.99685,0.9994833333,0.9969366667,0.9990359654 +-10,0.4144466667,0.6026633333,0.4142366667,0.6401244609 +-8,0.47322,0.6827466667,0.4749333333,0.7152454705 +-6,0.5445766667,0.7588666667,0.54569,0.7840240868 +-4,0.6223533333,0.8241966667,0.6225633333,0.8424432091 +-2,0.7009733333,0.8757933333,0.7011833333,0.8888838836 +0,0.7724933333,0.9165966667,0.7720633333,0.9237966241 +2,0.8337533333,0.9441633333,0.8322966667,0.9488822017 +4,0.88268,0.9645966667,0.88304,0.9662811712 +6,0.9196833333,0.97682,0.9193566667,0.9780307416 +8,0.9457333333,0.9852033333,0.9457433333,0.9858109157 +10,0.96429,0.9906933333,0.96467,0.9908905586 +12,0.97734,0.9942133333,0.9765066667,0.9941743502 +14,0.98498,0.9962466667,0.9854933333,0.9962827887 +16,0.9904633333,0.9975066667,0.99042,0.9976304229 +18,0.99391,0.99848,0.99382,0.9984893291 +20,0.99619,0.9990566667,0.9963433333,0.9990359654 diff --git a/data/sec_jam_gap.csv b/data/sec_jam_gap.csv index 971cb50..a30636e 100644 --- a/data/sec_jam_gap.csv +++ b/data/sec_jam_gap.csv @@ -1,201 +1,201 @@ ser,gap_db -0.7203966667,7.395409349 -0.7217858794,7.394580398 -0.7231750921,7.393751447 -0.7245643049,7.392922496 -0.7259535176,7.392093545 -0.7273427303,7.391264594 -0.728731943,7.390435644 -0.7301211558,7.389606693 -0.7315103685,7.388777742 -0.7328995812,7.387948791 -0.734288794,7.38711984 -0.7356780067,7.386290889 -0.7370672194,7.385461939 -0.7384564322,7.384632988 -0.7398456449,7.383804037 -0.7412348576,7.382975086 -0.7426240704,7.383719533 -0.7440132831,7.386932812 -0.7454024958,7.390146092 -0.7467917085,7.393359371 -0.7481809213,7.39657265 -0.749570134,7.39978593 -0.7509593467,7.402999209 -0.7523485595,7.406212489 -0.7537377722,7.409425768 -0.7551269849,7.412639048 -0.7565161977,7.415852327 -0.7579054104,7.419065607 -0.7592946231,7.422278886 -0.7606838358,7.425492166 -0.7620730486,7.428705445 -0.7634622613,7.431918725 -0.764851474,7.435132004 -0.7662406868,7.438345284 -0.7676298995,7.441558563 -0.7690191122,7.444771843 -0.770408325,7.447985122 -0.7717975377,7.451198402 -0.7731867504,7.454411681 -0.7745759631,7.457624961 -0.7759651759,7.46083824 -0.7773543886,7.46405152 -0.7787436013,7.467264799 -0.7801328141,7.470478079 -0.7815220268,7.473691358 -0.7829112395,7.476904638 -0.7843004523,7.480117917 -0.785689665,7.483331197 -0.7870788777,7.486544476 -0.7884680905,7.489757756 -0.7898573032,7.492971035 -0.7912465159,7.493110679 -0.7926357286,7.4893604 -0.7940249414,7.485610121 -0.7954141541,7.481859841 -0.7968033668,7.478109562 -0.7981925796,7.474359282 -0.7995817923,7.470609003 -0.800971005,7.466858724 -0.8023602178,7.463108444 -0.8037494305,7.459358165 -0.8051386432,7.455607885 -0.8065278559,7.451857606 -0.8079170687,7.454642491 -0.8093062814,7.461282924 -0.8106954941,7.467923358 -0.8120847069,7.474563791 -0.8134739196,7.481204225 -0.8148631323,7.487844658 -0.8162523451,7.494485092 -0.8176415578,7.501125525 -0.8190307705,7.507765959 -0.8204199832,7.514406392 -0.821809196,7.521046826 -0.8231984087,7.527687259 -0.8245876214,7.534327693 -0.8259768342,7.540968126 -0.8273660469,7.54760856 -0.8287552596,7.554248993 -0.8301444724,7.560889427 -0.8315336851,7.567529861 -0.8329228978,7.574170294 -0.8343121106,7.580810728 -0.8357013233,7.587451161 -0.837090536,7.594091595 -0.8384797487,7.600732028 -0.8398689615,7.607372462 -0.8412581742,7.614012895 -0.8426473869,7.620653329 -0.8440365997,7.627293762 -0.8454258124,7.633934196 -0.8468150251,7.640574629 -0.8482042379,7.647215063 -0.8495934506,7.653855496 -0.8509826633,7.653807084 -0.852371876,7.645603621 -0.8537610888,7.637400158 -0.8551503015,7.629196695 -0.8565395142,7.620993232 -0.857928727,7.612789769 -0.8593179397,7.604690194 -0.8607071524,7.609289208 -0.8620963652,7.613888221 -0.8634855779,7.618487234 -0.8648747906,7.623086248 -0.8662640034,7.627685261 -0.8676532161,7.632284274 -0.8690424288,7.636883288 -0.8704316415,7.641482301 -0.8718208543,7.646081314 -0.873210067,7.650680328 -0.8745992797,7.655279341 -0.8759884925,7.659878354 -0.8773777052,7.664477367 -0.8787669179,7.669076381 -0.8801561307,7.673675394 -0.8815453434,7.678274407 -0.8829345561,7.682873421 -0.8843237688,7.687472434 -0.8857129816,7.692071447 -0.8871021943,7.696670461 -0.888491407,7.701269474 -0.8898806198,7.705868487 -0.8912698325,7.7104675 -0.8926590452,7.715066514 -0.894048258,7.719665527 -0.8954374707,7.72426454 -0.8968266834,7.708663797 -0.8982158961,7.689747699 -0.8996051089,7.670831601 -0.9009943216,7.651915503 -0.9023835343,7.648634256 -0.9037727471,7.652417362 -0.9051619598,7.656200468 -0.9065511725,7.659983574 -0.9079403853,7.66376668 -0.909329598,7.667549785 -0.9107188107,7.671332891 -0.9121080235,7.675115997 -0.9134972362,7.678899103 -0.9148864489,7.682682209 -0.9162756616,7.686465314 -0.9176648744,7.69024842 -0.9190540871,7.694031526 -0.9204432998,7.697814632 -0.9218325126,7.701597738 -0.9232217253,7.705380843 -0.924610938,7.709163949 -0.9260001508,7.712947055 -0.9273893635,7.716730161 -0.9287785762,7.712515836 -0.9301677889,7.68932668 -0.9315570017,7.666137524 -0.9329462144,7.647766978 -0.9343354271,7.661181255 -0.9357246399,7.674595531 -0.9371138526,7.688009808 -0.9385030653,7.701424084 -0.9398922781,7.714838361 -0.9412814908,7.728252637 -0.9426707035,7.741666914 -0.9440599162,7.75508119 -0.945449129,7.768495467 -0.9468383417,7.781909743 -0.9482275544,7.79532402 -0.9496167672,7.808738296 -0.9510059799,7.822152572 -0.9523951926,7.835566849 -0.9537844054,7.82423082 -0.9551736181,7.787989163 -0.9565628308,7.801358196 -0.9579520436,7.814727229 -0.9593412563,7.828096263 -0.960730469,7.841465296 -0.9621196817,7.85483433 -0.9635088945,7.868203363 -0.9648981072,7.881572397 -0.9662873199,7.89494143 -0.9676765327,7.908310464 -0.9690657454,7.921679497 -0.9704549581,7.898323164 -0.9718441709,7.896911546 -0.9732333836,7.895499928 -0.9746225963,7.894088311 -0.976011809,7.892676693 -0.9774010218,7.891265075 -0.9787902345,7.889853457 -0.9801794472,7.888441839 -0.98156866,7.824207805 -0.9829578727,7.864499773 -0.9843470854,7.904791741 -0.9857362982,7.945083709 -0.9871255109,7.985375677 -0.9885147236,7.932516304 -0.9899039363,7.872849328 -0.9912931491,7.813182351 -0.9926823618,7.750636227 -0.9940715745,7.986447804 -0.9954607873,8.12093709 -0.99685,7.761658031 +0.6026633333,5.493678481 +0.6046408543,5.495143167 +0.6066183752,5.496607853 +0.6085958961,5.498072538 +0.6105734171,5.499537224 +0.612550938,5.50100191 +0.614528459,5.502466596 +0.6165059799,5.503931281 +0.6184835008,5.505395967 +0.6204610218,5.506860653 +0.6224385427,5.508301835 +0.6244160637,5.509221054 +0.6263935846,5.510140274 +0.6283711055,5.511059493 +0.6303486265,5.511978713 +0.6323261474,5.512897932 +0.6343036683,5.513817151 +0.6362811893,5.514736371 +0.6382587102,5.51565559 +0.6402362312,5.516574809 +0.6422137521,5.517494029 +0.644191273,5.518413248 +0.646168794,5.519332468 +0.6481463149,5.520251687 +0.6501238358,5.521170906 +0.6521013568,5.522090126 +0.6540788777,5.523009345 +0.6560563987,5.523928564 +0.6580339196,5.524847784 +0.6600114405,5.525767003 +0.6619889615,5.526686223 +0.6639664824,5.527605442 +0.6659440034,5.528524661 +0.6679215243,5.529443881 +0.6698990452,5.5303631 +0.6718765662,5.53128232 +0.6738540871,5.532201539 +0.675831608,5.533120758 +0.677809129,5.534039978 +0.6797866499,5.534959197 +0.6817641709,5.535878416 +0.6837416918,5.535503786 +0.6857192127,5.533851599 +0.6876967337,5.532199412 +0.6896742546,5.530547225 +0.6916517755,5.528895037 +0.6936292965,5.52724285 +0.6956068174,5.525590663 +0.6975843384,5.523938475 +0.6995618593,5.522286288 +0.7015393802,5.522063588 +0.7035169012,5.525405405 +0.7054944221,5.528747221 +0.707471943,5.532089038 +0.709449464,5.535430855 +0.7114269849,5.538772672 +0.7134045059,5.542114488 +0.7153820268,5.545456305 +0.7173595477,5.548798122 +0.7193370687,5.552139939 +0.7213145896,5.555481755 +0.7232921106,5.558823572 +0.7252696315,5.562165389 +0.7272471524,5.565507206 +0.7292246734,5.568849022 +0.7312021943,5.572190839 +0.7331797152,5.575532656 +0.7351572362,5.578874473 +0.7371347571,5.582216289 +0.7391122781,5.585558106 +0.741089799,5.588899923 +0.7430673199,5.59224174 +0.7450448409,5.595583557 +0.7470223618,5.598925373 +0.7489998827,5.60226719 +0.7509774037,5.605609007 +0.7529549246,5.608950824 +0.7549324456,5.61229264 +0.7569099665,5.615634457 +0.7588874874,5.618885922 +0.7608650084,5.613646281 +0.7628425293,5.608406639 +0.7648200503,5.603166998 +0.7667975712,5.597927356 +0.7687750921,5.592687715 +0.7707526131,5.587448073 +0.772730134,5.583317494 +0.7747076549,5.587339621 +0.7766851759,5.591361749 +0.7786626968,5.595383876 +0.7806402178,5.599406004 +0.7826177387,5.603428132 +0.7845952596,5.607450259 +0.7865727806,5.611472387 +0.7885503015,5.615494514 +0.7905278224,5.619516642 +0.7925053434,5.62353877 +0.7944828643,5.627560897 +0.7964603853,5.631583025 +0.7984379062,5.635605152 +0.8004154271,5.63962728 +0.8023929481,5.643649408 +0.804370469,5.647671535 +0.8063479899,5.651693663 +0.8083255109,5.65571579 +0.8103030318,5.659737918 +0.8122805528,5.663760046 +0.8142580737,5.667782173 +0.8162355946,5.671804301 +0.8182131156,5.675826428 +0.8201906365,5.679848556 +0.8221681575,5.683870684 +0.8241456784,5.687892811 +0.8261231993,5.676216805 +0.8281007203,5.664125326 +0.8300782412,5.652033848 +0.8320557621,5.639942369 +0.8340332831,5.630154814 +0.836010804,5.634337883 +0.837988325,5.638520953 +0.8399658459,5.642704022 +0.8419433668,5.646887091 +0.8439208878,5.651070161 +0.8458984087,5.65525323 +0.8478759296,5.6594363 +0.8498534506,5.663619369 +0.8518309715,5.667802439 +0.8538084925,5.671985508 +0.8557860134,5.676168577 +0.8577635343,5.680351647 +0.8597410553,5.684534716 +0.8617185762,5.688717786 +0.8636960972,5.692900855 +0.8656736181,5.697083925 +0.867651139,5.701266994 +0.86962866,5.705450063 +0.8716061809,5.709633133 +0.8735837018,5.713816202 +0.8755612228,5.717999272 +0.8775387437,5.704285934 +0.8795162647,5.688192672 +0.8814937856,5.67209941 +0.8834713065,5.666428984 +0.8854488275,5.676382997 +0.8874263484,5.68633701 +0.8894038693,5.696291023 +0.8913813903,5.706245035 +0.8933589112,5.716199048 +0.8953364322,5.726153061 +0.8973139531,5.736107074 +0.899291474,5.746061086 +0.901268995,5.756015099 +0.9032465159,5.765969112 +0.9052240369,5.775923124 +0.9072015578,5.785877137 +0.9091790787,5.79583115 +0.9111565997,5.805785163 +0.9131341206,5.815739175 +0.9151116415,5.825693188 +0.9170891625,5.824055924 +0.9190666834,5.787467425 +0.9210442044,5.781806417 +0.9230217253,5.790159547 +0.9249992462,5.798512677 +0.9269767672,5.806865807 +0.9289542881,5.815218937 +0.930931809,5.823572067 +0.93290933,5.831925197 +0.9348868509,5.840278327 +0.9368643719,5.848631457 +0.9388418928,5.856984587 +0.9408194137,5.865337718 +0.9427969347,5.873690848 +0.9447744556,5.866565539 +0.9467519765,5.856412766 +0.9487294975,5.875987642 +0.9507070184,5.895562519 +0.9526845394,5.915137396 +0.9546620603,5.934712273 +0.9566395812,5.95428715 +0.9586171022,5.973862027 +0.9605946231,5.993436904 +0.9625721441,6.013011781 +0.964549665,6.044395891 +0.9665271859,6.026989308 +0.9685047069,6.00649273 +0.9704822278,5.985996153 +0.9724597487,5.965499576 +0.9744372697,5.945002998 +0.9764147906,5.924506421 +0.9783923116,5.900370081 +0.9803698325,5.94627134 +0.9823473534,5.9921726 +0.9843248744,6.038073859 +0.9863023953,6.081945759 +0.9882799162,6.082821636 +0.9902574372,6.083697512 +0.9922349581,6.152098946 +0.9942124791,6.265817892 +0.99619,6.055737705 diff --git a/data/sec_keylen.csv b/data/sec_keylen.csv index ac68c79..db10306 100644 --- a/data/sec_keylen.csv +++ b/data/sec_keylen.csv @@ -1,13 +1,9 @@ L,d,legit_ser,eve_ser,mask_xcorr,oma -4,16,0.9997925,0.999963,0.01188752614,0.961963405 -6,24,0.9921175,0.9996935,0.09415384382,nan -8,32,0.9297855,0.999972,0.007307400461,0.4769767714 -10,40,0.6965535,0.9999585,0.006223429926,nan -12,48,0.416604,0.999781,0.005153660662,nan -14,56,0.3323575,0.999695,0.005685989745,nan -16,64,0.2762895,0.9999285,0.007116591092,0.2747696909 -20,80,0.2076175,0.9996245,0.003162040841,0.2289444229 -24,96,0.1829615,0.999975,0.002973971656,0.1961714033 -32,128,0.131901,0.9998895,0.005575809628,0.1524639978 -48,192,0.090206,0.999845,0.005743456539,0.1054308944 -64,256,0.0635265,0.9997915,0.006678360514,0.08056383667 +8,32,0.948557,0.997348,0,0.6849191155 +12,48,0.413714,0.999937,0,nan +16,64,0.257299,0.9999905,0,0.2747696909 +20,80,0.1874125,0.9998835,0,0.2289444229 +24,96,0.1522385,0.99938,0,0.1961714033 +32,128,0.107608,0.9997135,0,0.1524639978 +48,192,0.0719285,0.9897345,0,0.1054308944 +64,256,0.0530375,0.9997025,0,0.08056383667 diff --git a/data/sec_sens_cmp.csv b/data/sec_sens_cmp.csv index e41d746..cd87b87 100644 --- a/data/sec_sens_cmp.csv +++ b/data/sec_sens_cmp.csv @@ -1,14 +1,14 @@ frac,ser_mask,ser_perm,ser_pad -0,0.9999779167,0.9999883333,0.9999893771 -0.2,0.9997833333,0.9995633333,0.9999023796 -0.4,0.9984945833,0.9950233333,0.9991029086 -0.6,0.9915358333,0.9543866667,0.9917561005 -0.75,0.9643629167,0.8802716667,0.9564884375 -0.85,0.8872583333,0.727755,0.8680976078 -0.9,0.7787070833,0.5709983333,0.7703445963 -0.92,0.7202866667,0.502115,0.7133141438 -0.94,0.6145370833,0.4848966667,0.6421212878 -0.955,0.52254125,0.4416266667,0.5773478672 -0.97,0.4333570833,0.3520316667,0.5008509328 -0.985,0.3505958333,0.30335,0.4105086147 -1,0.2758220833,0.303165,0.303815 +0,0.9999758333,0.9999883333,0.9999886992 +0.2,0.9998233333,0.999845,0.9998961502 +0.4,0.998725,0.9983133333,0.9990456633 +0.6,0.98967125,0.9839833333,0.9912300403 +0.75,0.9379629167,0.9079,0.953711875 +0.85,0.7883508333,0.75701,0.8596806442 +0.9,0.6134920833,0.5836283333,0.7556898116 +0.92,0.5265704167,0.5003716667,0.6950201284 +0.94,0.43973,0.456195,0.6192843094 +0.955,0.3805966667,0.3946716667,0.5503775633 +0.97,0.3297841667,0.3282283333,0.4689992019 +0.985,0.2895645833,0.2584466667,0.3728919542 +1,0.2575758333,0.2577083333,0.25939 diff --git a/data/sec_snr.csv b/data/sec_snr.csv index 675fbcf..20efc06 100644 --- a/data/sec_snr.csv +++ b/data/sec_snr.csv @@ -1,12 +1,12 @@ snr_db,legit,eve_wrong,eve_none,eve_public,oma,chance -0,0.8944596875,0.9999621875,0.999988125,0.8945528125,0.8933480658,0.9999847412 -2,0.79877875,0.9999559375,0.999986875,0.798940625,0.7973276257,0.9999847412 -4,0.6697890625,0.9999446875,0.99998625,0.6702265625,0.6686275787,0.9999847412 -6,0.5269903125,0.999944375,0.99999125,0.5272609375,0.525415822,0.9999847412 -8,0.39087,0.9999415625,0.999988125,0.39062875,0.3892153151,0.9999847412 -10,0.2760796875,0.9999296875,0.999986875,0.2753090625,0.2747696909,0.9999847412 -12,0.1876809375,0.9999203125,0.9999884375,0.1878209375,0.1870712987,0.9999847412 -14,0.1250471875,0.999920625,0.9999896875,0.12470875,0.1241256148,0.9999847412 -16,0.0812634375,0.9999153125,0.999985625,0.08121,0.08092517452,0.9999847412 -18,0.05243375,0.9999090625,0.9999865625,0.0526228125,0.05214810026,0.9999847412 -20,0.0335228125,0.9999196875,0.999988125,0.033636875,0.03334949917,0.9999847412 +0,0.8821684375,0.999989375,0.9999803125,0.8819953125,0.8933480658,0.9999847412 +2,0.779363125,0.99999125,0.999980625,0.7794809375,0.7973276257,0.9999847412 +4,0.6455015625,0.9999884375,0.9999809375,0.64627375,0.6686275787,0.9999847412 +6,0.5016365625,0.9999903125,0.99998,0.5016371875,0.525415822,0.9999847412 +8,0.3675334375,0.999989375,0.9999775,0.3677109375,0.3892153151,0.9999847412 +10,0.2576425,0.99999375,0.999970625,0.2569871875,0.2747696909,0.9999847412 +12,0.1741078125,0.99999,0.9999703125,0.17413125,0.1870712987,0.9999847412 +14,0.115345,0.9999853125,0.999966875,0.1151475,0.1241256148,0.9999847412 +16,0.0748184375,0.9999846875,0.9999675,0.0747059375,0.08092517452,0.9999847412 +18,0.0480371875,0.9999884375,0.9999575,0.0481878125,0.05214810026,0.9999847412 +20,0.030745,0.99998875,0.9999559375,0.0308409375,0.03334949917,0.9999847412 diff --git a/fig/fig_sec_brute.pdf b/fig/fig_sec_brute.pdf index 46d2b3b..de2f3f8 100644 Binary files a/fig/fig_sec_brute.pdf and b/fig/fig_sec_brute.pdf differ diff --git a/fig/fig_sec_jam.pdf b/fig/fig_sec_jam.pdf index ea0bd01..8aee6f1 100644 Binary files a/fig/fig_sec_jam.pdf and b/fig/fig_sec_jam.pdf differ diff --git a/fig/fig_sec_keylen.pdf b/fig/fig_sec_keylen.pdf index fc4db14..3e125a0 100644 Binary files a/fig/fig_sec_keylen.pdf and b/fig/fig_sec_keylen.pdf differ diff --git a/fig/fig_sec_kpa.pdf b/fig/fig_sec_kpa.pdf index 5e38bcd..8fb26a2 100644 Binary files a/fig/fig_sec_kpa.pdf and b/fig/fig_sec_kpa.pdf differ diff --git a/fig/fig_sec_real.pdf b/fig/fig_sec_real.pdf index 7f4e733..9c2a813 100644 Binary files a/fig/fig_sec_real.pdf and b/fig/fig_sec_real.pdf differ diff --git a/fig/fig_sec_sens.pdf b/fig/fig_sec_sens.pdf index fe00e6e..e5cb4b4 100644 Binary files a/fig/fig_sec_sens.pdf and b/fig/fig_sec_sens.pdf differ diff --git a/fig/fig_sec_snr.pdf b/fig/fig_sec_snr.pdf index a4b803a..70fc83b 100644 Binary files a/fig/fig_sec_snr.pdf and b/fig/fig_sec_snr.pdf differ