diff --git a/README.md b/README.md index 49432f7..74c09da 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,15 @@ Seeds are fixed: training 1, evaluation 777, attacker key guess comparison 11, key refresh 5150. Re-running reproduces the released CSV files. +## Conventions + +Flat Rayleigh fading, one gain per user per frame, with unit mean power. +A frame carries unit energy, so the SNR in decibels is the frame energy +over the total noise across all `d` real dimensions, and every scheme in +a comparison spends the same energy, bandwidth and rate. The +jamming-to-signal ratio is the jammer energy over the same frame energy. +Logarithms in an entropy or an information rate are base two. + ## Figure and table map | Artifact | Script | Data | @@ -77,6 +86,11 @@ files. | Key family table | `exp_full.stage_D` | `sec_maskfam.csv`, `sec_regjam.csv` | | Headline recovery table | `exp_real_sec` | `real_sec_stats.json` | | Key refresh tables | `exp_refresh` | `refresh_summary.csv`, `refresh_kpa.csv` | +| Information-theoretic leakage | `exp_infotheory` | `infotheory.csv` | +| Semantic similarity | `exp_semantic` | `semantic.csv` | +| Load and channel-estimate sweeps | `exp_users_csi` | `users.csv`, `csi.csv` | +| Permutation-variant check | `exp_full.stage_M` | `perm_variant.csv` | +| Closed-form and symbolic checks | `verify_math` | `verify_math.csv` | ## Security scope diff --git a/code/check_consistency.py b/code/check_consistency.py index 3381f0b..4f9f77d 100644 --- a/code/check_consistency.py +++ b/code/check_consistency.py @@ -212,10 +212,44 @@ chk("learned support overlap 0.10", round(float(md["learned"]["mean_overlap"]), 2) == 0.10, md["learned"]["mean_overlap"]) chk("degeneracy numbers in tex", - "$5$ to $8$ of the $64$ entries" in tex and "overlap of\n$0.10$" in tex - or "$5$ to $8$ of the $64$ entries" in tex and "overlap of $0.10$" in tex, + "$5$ to $8$ of the $64$ entries" in tex + and "overlapping by $0.10$ on average over user pairs" in " ".join(tex.split()), "searched tex", needs_tex=True) +# --- key-length sweep floor ------------------------------------------ +# The eavesdropper column is an average over eight substitute-key draws, +# so the quoted floor must track the data and not one lucky draw. +kl = rows("sec_keylen.csv") +floor = min(float(r["eve_ser"]) for r in kl) +chk("eavesdropper floor over key length", abs(floor - 0.9984) < 5e-4, + "%.6f" % floor) +if HAVE_TEX: + chk("quoted eavesdropper floor in tex", "$0.9984$" in tex, + "searched tex", needs_tex=True) + + +# --- tables against their generator ----------------------------------- +# Every printed table cell must be the one make_tables.py derives from +# data/, so a rerun that moves a number cannot leave the manuscript behind. +if HAVE_TEX: + import io + import contextlib + import make_tables + buf = io.StringIO() + with contextlib.redirect_stdout(buf): + make_tables.compare_table() + make_tables.maskfam_table() + make_tables.refresh_tables() + rows = [r.strip() for r in buf.getvalue().split("\n") + if r.rstrip().endswith(r"\\")] + flat = " ".join(tex.split()) + lost = [r for r in rows if " ".join(r.split()) not in flat] + chk("table rows match the generator", not lost, + "%d rows, %d missing" % (len(rows), len(lost)), needs_tex=True) + for r in lost: + print(" missing:", r[:78]) + + # --- abstract --------------------------------------------------------- a = (tex.split(r"\begin{abstract}")[1].split(r"\end{abstract}")[0].strip() if HAVE_TEX else "") diff --git a/code/check_texhealth.py b/code/check_texhealth.py deleted file mode 100644 index a02dadf..0000000 --- a/code/check_texhealth.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -"""Guard against mangled TeX control sequences. - -Shell heredocs silently turn a backslash escape into the control -character it names, so \times becomes a tab followed by "imes" and \ref -becomes a carriage return followed by "ef". LaTeX compiles both without -an error and prints the wreckage, so the build log cannot catch this. -This scan can. -""" -import re -import sys -from pathlib import Path - -TEX = Path(__file__).resolve().parents[1] / "main.tex" -CTRL = {"\t": "TAB", "\r": "CR", "\x08": "BS", "\x0c": "FF", - "\x07": "BEL", "\x0b": "VT", "\x00": "NUL"} -# a macro name shorn of its first letter, which is what the escape ate -STUBS = ["ef{", "abel{", "ite{", "extbf{", "extit{", "ext{", "imes", - "rac{", "eft(", "ight)", "ho_", "elta", "psilon", "ambda", - "igma", "ewline", "otag", "uad", "nderline", "ag{", "egin{", - "nd{", "aption{", "ilde{", "ar{", "at{", "ec{"] -PAT = re.compile("(?