Main configuration d=256, L=64: all data, figures and checks re-run
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.
This commit is contained in:
+47
-27
@@ -47,15 +47,24 @@ 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,
|
||||
chk("gain 24 to 35 percent",
|
||||
round(-max(rel)) == 24 and round(-min(rel)) == 35,
|
||||
"%.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,
|
||||
chk("24 and 35 in tex", "$24$ to\n$35$~percent" in tex or "$24$ to $35$~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))
|
||||
dev = max(abs(x - ch) for x in ew)
|
||||
chk("outsider at chance to 3.5e-4", dev < 3.6e-4, "max deviation %.2e" % dev)
|
||||
chk("3.5e-4 in tex", "$3.5\\times10^{-4}$" in tex, "searched tex",
|
||||
needs_tex=True)
|
||||
|
||||
# the main configuration's legitimate rate, the reference every later
|
||||
# assertion compares against; taken from the curve the main
|
||||
# configuration produced rather than looked up by key length
|
||||
MAIN_LEGIT = [float(x["legit"]) for x in sn if float(x["snr_db"]) == 10][0]
|
||||
chk("main legitimate 0.053", round(MAIN_LEGIT, 3) == 0.053,
|
||||
"%.4f" % MAIN_LEGIT)
|
||||
|
||||
# --- Fig. 3: key-length ratio ----------------------------------------
|
||||
k = rows("sec_keylen.csv")
|
||||
@@ -70,11 +79,10 @@ chk("keys exactly orthogonal in the sweep",
|
||||
|
||||
# --- Fig. 4: jamming --------------------------------------------------
|
||||
g = col("sec_jam_gap.csv", "gap_db")
|
||||
chk("gap 5.5-6.3 dB", round(min(g), 1) == 5.5 and round(max(g), 1) == 6.3,
|
||||
chk("gap 10.1-11.1 dB", round(min(g), 1) == 10.1 and round(max(g), 1) == 11.1,
|
||||
"%.3f to %.3f" % (min(g), max(g)))
|
||||
lin = (10 ** (min(g) / 10), 10 ** (max(g) / 10))
|
||||
chk("about four times power", lin[0] < 4.5 and lin[1] > 3.4,
|
||||
"%.2f to %.2f" % lin)
|
||||
chk("more than ten times power", lin[0] > 10.0, "%.2f to %.2f" % lin)
|
||||
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)
|
||||
@@ -83,32 +91,40 @@ chk("no stale 8.1 dB", "$8.1$~dB" not in tex, "searched tex", needs_tex=True)
|
||||
# --- Fig. 6: brute force ---------------------------------------------
|
||||
b = rows("sec_brute_cmp.csv")
|
||||
sm = float(b[-1]["ser_mask"])
|
||||
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("brute 0.67 at 1e6", round(sm, 2) == 0.67, "%.4f" % sm)
|
||||
chk("0.67 in tex", "$0.67$" in tex, "searched tex", needs_tex=True)
|
||||
closed = (ch - sm) / (ch - MAIN_LEGIT)
|
||||
chk("brute closes about a third", 0.30 < closed < 0.40, "%.3f" % closed)
|
||||
bf = float(b[-1]["best_frac"]) * 100
|
||||
chk("permutation 3.4 percent of positions", round(bf, 1) == 3.4, "%.2f" % bf)
|
||||
pad0 = next((x["K"] for x in b if float(x["ser_pad"]) < 0.1), None)
|
||||
chk("index cipher collapses at 65536", pad0 == "65536", str(pad0))
|
||||
|
||||
# --- Fig. 7: known plaintext -----------------------------------------
|
||||
kp = rows("kpa.csv")
|
||||
legit = float([x for x in k if int(x["L"]) == 16][0]["legit_ser"])
|
||||
legit = MAIN_LEGIT
|
||||
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)
|
||||
chk("KPA three frames at 20 dB", first20 == "3", "first N = %s" % first20)
|
||||
chk("KPA ten frames at 10 dB", first10 == "10", "first N = %s" % first10)
|
||||
kp0 = [x for x in kp if int(x["snr_db"]) == 0]
|
||||
w0 = float(kp0[-1]["eve_ser"]) / legit
|
||||
chk("0 dB no longer holds", w0 < 1.03, "64 frames reach %.3f of legitimate" % w0)
|
||||
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)
|
||||
chk("perm KPA at N=6 near its own legitimate",
|
||||
abs(p6 - MAIN_LEGIT) < 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,
|
||||
chk("refresh 364.6 bits",
|
||||
round(float(rs["Invariant"]["entropy_bits"]), 1) == 364.6,
|
||||
"%.3f" % float(rs["Invariant"]["entropy_bits"]))
|
||||
chk("fixed key 15.0 bits",
|
||||
round(float(rs["None (fixed key)"]["entropy_bits"]), 1) == 15.0,
|
||||
chk("fixed key 23.8 bits",
|
||||
round(float(rs["None (fixed key)"]["entropy_bits"]), 1) == 23.8,
|
||||
"%.4f" % float(rs["None (fixed key)"]["entropy_bits"]))
|
||||
chk("invariant refresh free",
|
||||
abs(float(rs["Invariant"]["legit"]) - float(rs["None (fixed key)"]["legit"]))
|
||||
@@ -119,8 +135,8 @@ chk("invariant refresh free",
|
||||
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,
|
||||
chk("headline recovery 96 vs 93 percent",
|
||||
round(rec["legit"] * 100) == 96 and round(rec["oma"] * 100) == 93,
|
||||
"%.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"]
|
||||
@@ -137,19 +153,23 @@ chk("L=8 crowding, proposal behind OMA",
|
||||
chk("0.949 and 0.685 in tex", "0.949" in tex and "0.685" in tex,
|
||||
"searched tex", needs_tex=True)
|
||||
|
||||
# the Fig. 2 inset plots this ratio, so its stated span must hold
|
||||
# the OMA-to-proposed ratio the narration quotes
|
||||
sr = rows("sec_snr.csv")
|
||||
rt = [float(r["oma"]) / float(r["legit"]) for r in sr]
|
||||
chk("inset ratio spans 1.01 to 1.09", 1.005 < min(rt) and max(rt) < 1.095,
|
||||
"%.3f to %.3f" % (min(rt), max(rt)))
|
||||
chk("ratio spans 1.32 to 1.54", round(min(rt), 2) == 1.32
|
||||
and round(max(rt), 2) == 1.54, "%.3f to %.3f" % (min(rt), max(rt)))
|
||||
|
||||
# the three secrets named in the setup
|
||||
chk("secret sizes UL=64, perm 64, pad 16",
|
||||
all(t in tex for t in ["$UL=64$ key entries",
|
||||
"one permutation of $64$ positions",
|
||||
chk("secret sizes UL=256, perm 256, pad 16",
|
||||
all(t in tex for t in ["$UL=256$ key entries",
|
||||
"one permutation of $256$ positions",
|
||||
"$16$ pad\nbits per user"]),
|
||||
"searched tex", needs_tex=True)
|
||||
|
||||
chk("no stale d=64 configuration in tex",
|
||||
"$d=64$ real dimensions" not in tex and "$d/U=16$" not in tex,
|
||||
"searched tex", needs_tex=True)
|
||||
|
||||
# Fig. 5 shows the permutation curve tracking the mask curve
|
||||
sc = rows("sec_sens_cmp.csv")
|
||||
dv = max(abs(float(r["ser_mask"]) - float(r["ser_perm"])) for r in sc)
|
||||
|
||||
Reference in New Issue
Block a user