Final revision: audit fixes, cross-scheme comparisons, known-plaintext stage

- 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
This commit is contained in:
KiHoLee
2026-08-13 21:21:46 +09:00
parent 37392bc38f
commit 25b5891b04
15 changed files with 279 additions and 56 deletions
+40 -16
View File
@@ -1,9 +1,11 @@
"""Generate the LaTeX rows of the two result tables from the CSVs, so
"""Generate the LaTeX rows of the three result tables from the CSVs, so
that every table in the paper is reproducible from data/ (TIFS mandate).
Prints the tabular body; paste into main.tex without edits.
Prints the tabular bodies; paste into main.tex without edits.
"""
from __future__ import annotations
import csv
import json
import math
from pathlib import Path
DATA = Path(__file__).resolve().parents[1] / "data"
@@ -17,39 +19,61 @@ NAME = {
"random": "Random",
"hadamard": "Walsh-Hadamard",
"learned": "Learned",
"learned_reg": r"Regularized~\eqref{eq:regloss}",
}
RECEIVER = {
"legit": "Legitimate", "oma": "OMA",
"insider": "Insider", "eve": "Outsider eavesdropper",
}
def f3(x: str) -> str:
"""Three decimals, or an em-dash for a value that does not apply."""
try:
return f"{float(x):.3f}"
except ValueError:
v = float(x)
except (TypeError, ValueError):
return "--"
return "--" if math.isnan(v) else f"{v:.3f}"
def cell(x: str, bold: bool) -> str:
s = f3(x)
if s == "--":
return "--"
return rf"$\mathbf{{{s}}}$" if bold else f"${s}$"
def compare_table():
print("% Table: scheme comparison (from sec_compare.csv)")
rows = list(csv.DictReader(open(DATA / "sec_compare.csv")))
order = ["public_mask", "perm_key", "index_cipher", "oma_plain", "proposed"]
rows = sorted(rows, key=lambda r: order.index(r["scheme"]))
rows.sort(key=lambda r: order.index(r["scheme"]))
for r in rows:
cells = [f3(r["legit_ser"]), f3(r["eve_out"]), f3(r["eve_in"]),
f3(r["jam0_ser"])]
if r["scheme"] == "proposed":
cells = [rf"$\mathbf{{{c}}}$" for c in cells]
else:
cells = [f"${c}$" if c != "--" else "--" for c in cells]
b = r["scheme"] == "proposed"
cells = [cell(r[k], b) for k in
("legit_ser", "eve_out", "eve_in", "jam0_ser")]
print(f"{NAME[r['scheme']]} & " + " & ".join(cells) + r" \\")
def maskfam_table():
print("% Table: key families (from sec_maskfam.csv)")
for r in csv.DictReader(open(DATA / "sec_maskfam.csv")):
print(f"{NAME[r['family']]} & ${f3(r['legit_ser'])}$ & "
f"${f3(r['eve_ser'])}$ & ${f3(r['mask_xcorr'])}$" + r" \\")
cells = [cell(r[k], False) for k in
("legit_ser", "eve_ser", "eve_ones_ser", "mask_xcorr")]
print(f"{NAME[r['family']]} & " + " & ".join(cells) + r" \\")
def real_table():
print("% Table: headline recovery (from real_sec_stats.json)")
st = json.loads((DATA / "real_sec_stats.json").read_text())
rec = st["recovery"]
snrs = sorted(rec, key=float)
for key in ("legit", "oma", "insider", "eve"):
cells = " & ".join(f"${rec[s][key]:.3f}$" for s in snrs)
print(f"{RECEIVER[key]} & {cells}" + r" \\")
if __name__ == "__main__":
compare_table()
print()
maskfam_table()
compare_table(); print()
maskfam_table(); print()
real_table()