Learned-key stages, per-scheme plot styles, KM naming

exp_learned.py mirrors every structured result stage for the learned key
family at the same SNRs, frame counts and seeds, so Figs. 2, 3, 4 and 7
and Tables IV and VI can carry both realizations of keyed masking.

replot_security.py gains a style registry: colour identifies the scheme
and line style the role, so a curve learned in one figure reads the same
in the next. Previously OMA was grey in two figures and teal in a third,
and blue meant the eavesdropper in one figure and the permutation key in
another.
This commit is contained in:
KiHoLee
2026-08-28 20:15:45 +09:00
parent 3a9a5eebf4
commit c00e8ab666
17 changed files with 320 additions and 57 deletions
+159
View File
@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
"""Learned-key counterparts of the structured-key result stages.
Keyed masking is realized two ways, with structured Walsh-Hadamard keys
and with keys learned in R^L. The two differ in key space, so the paper
reports both wherever a figure or table carries a keyed-masking result.
This script produces the learned side of the key-length sweep, the
jamming sweep, the known-plaintext attack, the scheme comparison and
the refresh, writing files named *_learned.csv next to the structured
ones.
Every evaluation mirrors its structured counterpart exactly: same SNR,
same frame counts, same seeds, same evaluators. Only the key family
differs.
"""
from __future__ import annotations
import math
from pathlib import Path
import torch
import exp_kpa
from exp_full import (MAIN_D, eval_ser_eve, eval_ser_jam, eve_wrong_mask,
get_model, mean_abs_xcorr, oma_ser_keylen)
from sse_lib import DATA, DEVICE, eval_ser_sse, write_csv
SEED = 1
def learned_model(d=MAIN_D, P=4, vu=16, U=4, iters=4000, seed=SEED):
"""The learned counterpart of main_model: same everything, keys free."""
return get_model(P=P, vu=vu, d=d, U=U, iters=iters, seed=seed)
def keylen():
"""Fig. 3's learned curve."""
print("[learned] key length ...")
rows = []
for d in [32, 48, 64, 80, 96, 128, 192, 256]:
m = learned_model(d=d)
lg = eval_ser_sse(m, [10.0], frames=500_000)[0]
ev = sum(eval_ser_eve(
m, eve_wrong_mask(m.users, m.L,
seed=20260813 + 101 * k).to(DEVICE),
[10.0], frames=500_000 // 8)[0]
for k in range(8)) / 8.0
rows.append((m.L, d, lg, ev, mean_abs_xcorr(m.masks().detach()),
oma_ser_keylen(m.L, 10.0)))
print(" L=%3d legit %.4f eve %.4f" % (m.L, lg, ev))
write_csv(DATA / "sec_keylen_learned.csv",
["L", "d", "legit_ser", "eve_ser", "mask_xcorr", "oma"], rows)
def jamming():
"""Fig. 4's learned curves."""
print("[learned] jamming ...")
m = learned_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)
nojam = eval_ser_jam(m, 10.0, [-40.0], frames=500_000, mode="blind",
target=0)[0]
write_csv(DATA / "sec_jam_learned.csv",
["jsr_db", "blind", "matched", "nojam"],
[(j, blind[i], matched[i], nojam) for i, j in enumerate(jsr)])
print(" blind :", ["%.3f" % v for v in blind])
def kpa():
"""Fig. 7's learned curve. The attack is linear algebra on the key,
so it applies to a real-valued key exactly as to a sign pattern."""
print("[learned] known plaintext ...")
m = learned_model()
m.eval()
true_m = m.masks().detach()
nmax = max(exp_kpa.NFRAMES)
rows = []
for snr in exp_kpa.SNRS:
acc = {n: [[], []] for n in exp_kpa.NFRAMES}
for t in range(exp_kpa.TRIALS):
gen = torch.Generator(device="cpu").manual_seed(
exp_kpa.SEED + int(snr) + 1000 * t)
digits, obs, h = exp_kpa.collect_known_plaintext(m, nmax, snr, gen)
eval_seed = 777 + 31 * t + int(snr)
for n in exp_kpa.NFRAMES:
est = exp_kpa.solve_keys(m, digits[:n], obs[:n], h[:n])
acc[n][0].append(exp_kpa.key_correlation(est, true_m))
acc[n][1].append(eval_ser_eve(m, est.cpu(), [10.0],
frames=exp_kpa.EVAL_FRAMES,
seed=eval_seed)[0])
for n in exp_kpa.NFRAMES:
ks, ss = acc[n]
rows.append((snr, n, sum(ks) / len(ks), sum(ss) / len(ss)))
print(" %4.0f dB done" % snr)
write_csv(DATA / "kpa_learned.csv",
["snr_db", "n_frames", "kappa", "eve_ser"], rows)
def refresh():
"""Table VI's learned rows: the invariance refresh acts through
eps^2 = 1 and a relabeling, so it is available to any real key."""
print("[learned] refresh ...")
m = learned_model()
W0, B0 = m.W.detach().clone(), m.B.detach().clone()
base = eval_ser_sse(m, [10.0], frames=300_000)[0]
out = []
for b in range(8):
g = torch.Generator(device=DEVICE).manual_seed(5150 + b)
xi = torch.randperm(m.L, generator=g, device=DEVICE)
eps = torch.randint(2, (m.L,), generator=g, device=DEVICE) * 2.0 - 1.0
tau = torch.randperm(m.users, generator=g, device=DEVICE)
with torch.no_grad():
m.W.copy_((W0[tau] * eps[None, :])[:, xi])
m.B.copy_(B0[:, xi])
lg = eval_ser_sse(m, [10.0], frames=300_000)[0]
ev = eval_ser_eve(m, eve_wrong_mask(m.users, m.L,
seed=20260813).to(DEVICE),
[10.0], frames=300_000)[0]
out.append((b, lg, ev))
with torch.no_grad():
m.W.copy_(W0); m.B.copy_(B0)
write_csv(DATA / "refresh_learned.csv",
["block", "legit_ser", "eve_ser"], out)
print(" unrefreshed %.5f refreshed %.5f..%.5f"
% (base, min(r[1] for r in out), max(r[1] for r in out)))
def compare():
"""Table IV's learned row: the same four columns as the structured
scheme, under the same jammer at a JSR of 0 dB."""
print("[learned] scheme comparison ...")
m = learned_model()
F = 300_000
legit = eval_ser_sse(m, [10.0], frames=F)[0]
out = eval_ser_eve(m, eve_wrong_mask(m.users, m.L,
seed=20260813).to(DEVICE),
[10.0], frames=F)[0]
ins = eval_ser_eve(m, m.masks().detach().roll(1, 0), [10.0], frames=F)[0]
jam = eval_ser_jam(m, 10.0, [0.0], frames=F, mode="blind", target=0)[0]
write_csv(DATA / "compare_learned.csv",
["scheme", "legit_ser", "eve_out", "eve_in", "jam0_ser"],
[("proposed_learned", legit, out, ins, jam)])
print(" legit %.4f out %.4f in %.4f jam %.4f"
% (legit, out, ins, jam))
def main():
keylen()
jamming()
kpa()
refresh()
compare()
print("[done] learned-key CSVs in", DATA)
if __name__ == "__main__":
main()
+13 -10
View File
@@ -11,15 +11,17 @@ from pathlib import Path
DATA = Path(__file__).resolve().parents[1] / "data"
NAME = {
"proposed": r"\textbf{Proposed keyed masking}",
"proposed": r"\textbf{KM (structured)}",
"proposed_learned": r"\textbf{KM (learned)}",
"public_mask": "Public masks",
"perm_key": r"Permutation key~\cite{chen2025shufflingtifs}",
"index_cipher": "Index cipher",
"oma_plain": "OMA (no encryption)",
"random": "Random",
"hadamard": "Walsh-Hadamard",
"learned": "Learned",
"learned_reg": r"Regularized~\eqref{eq:regloss}",
"hadamard": "Structured",
"learned": "Learned, plain",
"learned_reg": r"Learned, regularized~\eqref{eq:regloss}",
"invariant_learned": r"\textbf{Invariant, learned keys}",
}
RECEIVER = {
"legit": "Legitimate", "oma": "OMA",
@@ -57,7 +59,8 @@ def cell(x: str, bold: bool, wide: bool = False) -> str:
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"]
order = ["public_mask", "perm_key", "index_cipher", "oma_plain",
"proposed", "proposed_learned"]
rows.sort(key=lambda r: order.index(r["scheme"]))
# stage_E does not jam the orthogonal reference, because the jammer an
# OMA user faces is targeted at public slots rather than mask-matched
@@ -67,13 +70,13 @@ def compare_table():
for r in csv.DictReader(open(DATA / "sec_jam_cmp.csv"))}
oma_jam = jam[0.0]["oma_targeted"]
for r in rows:
b = r["scheme"] == "proposed"
b = r["scheme"].startswith("proposed")
if r["scheme"] == "oma_plain" and f3(r["jam0_ser"]) == "--":
r["jam0_ser"] = oma_jam
# four decimals would still print 1.0000 here, so the column
# stays at three and the caption names the chance level
cells = [cell(r[k], b) for k in
("legit_ser", "eve_out", "eve_in", "jam0_ser")]
("eve_out", "eve_in", "jam0_ser")]
print(f"{NAME[r['scheme']]} & " + " & ".join(cells) + r" \\")
@@ -84,7 +87,7 @@ def maskfam_table():
# emphasized the same way the proposed row is in the comparison
b = r["family"] == "hadamard"
cells = [cell(r[k], b) for k in
("legit_ser", "eve_ser", "eve_ones_ser", "mask_xcorr")]
("legit_ser", "eve_ser", "mask_xcorr")]
name = NAME[r["family"]]
if b:
name = r"\textbf{" + name + "}"
@@ -94,8 +97,8 @@ def maskfam_table():
def refresh_tables():
print("% Table: key refresh (from refresh_summary.csv)")
for r in csv.DictReader(open(DATA / "refresh_summary.csv")):
b = r["scheme"] == "Invariant"
name = r"\textbf{Invariant}" if b else r["scheme"]
b = r["scheme"].startswith("Invariant")
name = (r"\textbf{" + r["scheme"] + "}") if b else r["scheme"]
f = (lambda t: r"\mathbf{" + t + "}") if b else (lambda t: t)
print(f"{name} & ${f(format(float(r['legit']), '.3f'))}$ & "
f"${f(format(float(r['eve']), '.4f'))}$ & "
+75 -47
View File
@@ -56,27 +56,46 @@ plt.rcParams.update({
})
AXES_RECT = dict(left=0.215, right=0.970, top=0.955, bottom=0.225)
C_LEGIT = "#c0392b"
C_EVE = "#2c5fa8"
C_OMA = "#7f8c8d"
C_CH = "#95a5a6"
C_MATCH = "#8e44ad"
C_PUB = "#16a085"
C_LEARN = "#d98c00"
C_LEGIT = "#c0392b" # KM, structured keys
C_LEARN = "#d98c00" # KM, learned keys
C_OMA = "#7f8c8d" # orthogonal multiple access
C_PUB = "#16a085" # public masks
C_PERM = "#8e44ad" # permutation key
C_PAD = "#a0522d" # index cipher
C_EVE = "#2c5fa8" # an adversary of KM
C_CH = "#95a5a6" # chance and reference levels
C_MATCH = C_PUB # the matched jammer is what public masks admit
# One entry per curve the figures draw. Colour identifies the scheme and
# line style the role: solid for a legitimate rate, dashed for an
# adversary, dash-dot for a comparison scheme, dotted for a reference.
# Every figure reads its curves from here, so a reader who learns a
# curve in one figure reads the same curve in the next.
STY = {
"km_str": dict(color=C_LEGIT, marker="o", ls="-"),
"km_lrn": dict(color=C_LEARN, marker="d", ls="-"),
"oma": dict(color=C_OMA, marker="^", ls=":"),
"pub": dict(color=C_PUB, marker="v", ls="-."),
"perm": dict(color=C_PERM, marker="X", ls="--"),
"pad": dict(color=C_PAD, marker="P", ls="-."),
"eve": dict(color=C_EVE, marker="s", ls="--"),
"insider": dict(color=C_EVE, marker="v", ls="-."),
}
# fixed label dictionary: tables and prose copy these strings verbatim
LBL = {
"legit": "Legitimate",
"legit_learned": "Learned keys",
"legit": "KM (structured)",
"legit_learned": "KM (learned)",
"oma": "OMA",
"eve_pub": "Eavesdropper, public masks",
"eve_key": "Eavesdropper", # the wrong-key condition is in the caption
"chance": "Random guess",
"nojam": "No jammer",
"mask": "Keyed masking",
"mask": "KM (structured)",
"perm": "Permutation key",
"pad": "Index cipher",
"insider": "Insider",
"legit_ref": "Legitimate rate",
"outsider": "Outsider",
}
# deliberate-layering style for the LOWER of two coinciding curves
@@ -207,7 +226,7 @@ def main_legit(snr_db="10"):
def place_legend(ax, cands=("lower left", "upper left", "center left",
"center right", "lower center", "upper right",
"upper center", "center", "lower right"),
sizes=(9.2, 8.8, 8.4, 8.0, 7.6, 7.2), ncol=1):
sizes=(9.2, 8.8, 8.4, 8.0, 7.6, 7.2, 6.8, 6.4), ncol=1):
"""Choose the location and font size whose box the fewest curve points
fall inside, scored on rendered geometry rather than guessed from the
data. The size sweep is what makes a long label set placeable: a
@@ -271,23 +290,21 @@ def fig_snr():
# legitimate and the public-mask eavesdropper coincide by
# construction (same physical layer, public masks decode alike), so
# the pair is deliberately layered; OMA is separate at this frame
ax.semilogy(x, col(r, "legit"), color=C_LEGIT, marker="o", ls="-",
ax.semilogy(x, col(r, "legit"), **STY["km_str"],
markevery=(0, 3), label=LBL["legit"], **UNDER)
# the learned family is the other end of the key-space trade-off,
# so the figure carries what it costs at every SNR
rl = load("sec_snr_learned.csv")
ax.semilogy(col(rl, "snr_db"), col(rl, "legit"), color=C_LEARN,
marker="d", ls="-", markevery=(2, 3),
label=LBL["legit_learned"])
ax.semilogy(x, col(r, "oma"), color=C_OMA, marker="^", ls=":",
ax.semilogy(col(rl, "snr_db"), col(rl, "legit"), **STY["km_lrn"],
markevery=(2, 3), label=LBL["legit_learned"])
ax.semilogy(x, col(r, "oma"), **STY["oma"],
markevery=(1, 3), label=LBL["oma"], **OVER)
ax.semilogy(x, col(r, "eve_public"), color=C_PUB, marker="v",
ax.semilogy(x, col(r, "eve_public"), color=STY["pub"]["color"], marker=STY["pub"]["marker"],
ls="none", markevery=(2, 3), markerfacecolor="none",
label=LBL["eve_pub"])
# this figure carries two eavesdroppers, so the bare label of the
# key-length figure would not tell them apart
ax.semilogy(x, col(r, "eve_wrong"), color=C_EVE, marker="s", ls="--",
label="Eavesdropper, keyed")
ax.semilogy(x, col(r, "eve_wrong"), **STY["eve"], label="Eavesdropper, keyed")
# the chance level lies within 3.5e-4 of the wrong-key curve, so it is
# drawn for reference but left out of the legend, which the caption
# names instead; five long entries leave this figure no clear corner
@@ -295,10 +312,9 @@ def fig_snr():
ax.set_xlabel("SNR (dB)")
ax.set_ylabel("SER")
ax.set_xlim(min(x), max(x))
# the five-entry legend needs more clear space than the four-entry
# one did, so the axis opens a further decade below the data; the
# lower-left is empty because every curve decays
ax.set_ylim(bottom=2e-5)
# most of a decade below the data leaves the lower-left genuinely
# empty, which is what gives the legend a clear berth
ax.set_ylim(bottom=2e-4)
place_legend(ax)
save(fig, "fig_sec_snr")
@@ -310,14 +326,16 @@ def fig_keylen():
r = load("sec_keylen.csv")
x = col(r, "L", int)
fig, ax = plt.subplots()
ax.semilogy(x, col(r, "legit_ser"), color=C_LEGIT, marker="o", ls="-",
label=LBL["legit"])
ax.semilogy(x, col(r, "legit_ser"), **STY["km_str"], label=LBL["legit"])
rl = load("sec_keylen_learned.csv")
ax.semilogy(col(rl, "L", int), col(rl, "legit_ser"), **STY["km_lrn"], label=LBL["legit_learned"])
op = [(l, v) for l, v in zip(x, col(r, "oma")) if not math.isnan(v)]
ax.semilogy([p[0] for p in op], [p[1] for p in op], color=C_OMA,
marker="^", ls=":", label=LBL["oma"])
ax.semilogy(x, col(r, "eve_ser"), color=C_EVE, marker="s", ls="--",
label=LBL["eve_key"])
ax.semilogy([p[0] for p in op], [p[1] for p in op], **STY["oma"], label=LBL["oma"])
ax.semilogy(x, col(r, "eve_ser"), **STY["eve"], label=LBL["eve_key"])
ax.set_ylim(top=22.0) # headroom above the flat eavesdropper curve
# an error rate cannot exceed one, and the room below the data holds
# the legend, since every curve decays to the right
ax.set_ylim(top=1.4, bottom=1.2e-2)
ax.set_xlabel("Key length $L$")
ax.set_ylabel("SER")
ax.set_xscale("log", base=2)
@@ -335,14 +353,17 @@ def fig_jam():
x = col(r, "jsr_db")
me = max(1, len(x) // 8)
fig, ax = plt.subplots()
ax.plot(x, col(r, "matched"), color=C_MATCH, marker="P", ls="--",
rj = load("sec_jam_learned.csv")
ax.plot(col(rj, "jsr_db"), col(rj, "blind"), **STY["km_lrn"],
markevery=(1, me), label=LBL["legit_learned"])
ax.plot(x, col(r, "matched"), **STY["pub"],
markevery=me, label="Public masks")
ax.plot(x, col(r, "oma_targeted"), color=C_PUB, marker="^", ls=":",
ax.plot(x, col(r, "oma_targeted"), **STY["oma"],
markevery=me, label=LBL["oma"])
# the two blind curves agree to 0.002; deliberate layering
ax.plot(x, col(r, "blind"), color=C_LEGIT, marker="o", ls="-",
ax.plot(x, col(r, "blind"), **STY["km_str"],
markevery=(0, me), label=LBL["mask"], **UNDER)
ax.plot(x, col(r, "perm_blind"), color=C_EVE, marker="s", ls="-.",
ax.plot(x, col(r, "perm_blind"), **STY["perm"],
markevery=(me // 2, me), label=LBL["perm"], **OVER)
nojam = float(load("sec_jam.csv")[0]["nojam"])
# the unjammed reference is named in the caption rather than in the
@@ -367,11 +388,11 @@ def fig_sens():
r = load("sec_sens_cmp.csv")
x = col(r, "frac")
fig, ax = plt.subplots()
ax.plot(x, col(r, "ser_mask"), color=C_LEGIT, marker="o", ls="-",
ax.plot(x, col(r, "ser_mask"), **STY["km_str"],
markevery=(0, 3), label=LBL["mask"], **UNDER)
ax.plot(x, col(r, "ser_perm"), color=C_EVE, marker="s", ls="--",
ax.plot(x, col(r, "ser_perm"), **STY["perm"],
markevery=(1, 3), label=LBL["perm"], **OVER)
ax.plot(x, col(r, "ser_pad"), color=C_PUB, marker="v", ls="-.",
ax.plot(x, col(r, "ser_pad"), **STY["pad"],
markevery=(2, 3), lw=1.2, mfc="none", label=LBL["pad"])
# the chance level comes from the stored curve, not from a second
# copy of the configuration constants
@@ -379,7 +400,7 @@ def fig_sens():
ax.axhline(chance, color=C_CH, ls=":", lw=0.9, label=LBL["chance"])
# the narration reads these curves against the legitimate rate
ax.axhline(main_legit(), color=C_OMA, ls=(0, (4, 2)), lw=0.9,
label=LBL["legit"])
label=LBL["legit_ref"])
ax.set_xlabel("Fraction of the key recovered")
ax.set_ylabel("Eavesdropper SER")
ax.set_xlim(0, 1)
@@ -393,15 +414,15 @@ def fig_brute():
r = load("sec_brute_cmp.csv")
x = col(r, "K")
fig, ax = plt.subplots()
ax.semilogx(x, col(r, "ser_perm"), color=C_EVE, marker="s", ls="--",
ax.semilogx(x, col(r, "ser_perm"), **STY["perm"],
markevery=(0, 3), label=LBL["perm"], **UNDER)
ax.semilogx(x, col(r, "ser_pad"), color=C_PUB, marker="v", ls="-.",
ax.semilogx(x, col(r, "ser_pad"), **STY["pad"],
markevery=(1, 3), label=LBL["pad"], **OVER)
ax.semilogx(x, col(r, "ser_mask"), color=C_LEGIT, marker="o", ls="-",
ax.semilogx(x, col(r, "ser_mask"), **STY["km_str"],
markevery=(2, 3), label=LBL["mask"])
legit = main_legit()
ax.axhline(legit, color=C_OMA, ls=(0, (4, 2)), lw=0.9,
label=LBL["legit"])
label=LBL["legit_ref"])
ax.set_xlabel("Number of key guesses $K$")
ax.set_ylabel("Eavesdropper SER")
ax.set_ylim(0.0, 1.05) # keep the reference line off the spine
@@ -415,13 +436,13 @@ def fig_real():
fig, ax = plt.subplots()
# insider and outsider still nearly coincide and are layered; the
# legitimate and OMA curves are separate at this frame
ax.semilogy(x, col(r, "ter_legit"), color=C_LEGIT, marker="o", ls="-",
ax.semilogy(x, col(r, "ter_legit"), **STY["km_str"],
markevery=(0, 2), label=LBL["legit"], **UNDER)
ax.semilogy(x, col(r, "ter_oma"), color=C_OMA, marker="^", ls=":",
ax.semilogy(x, col(r, "ter_oma"), **STY["oma"],
markevery=(1, 2), label=LBL["oma"], **OVER)
ax.semilogy(x, col(r, "ter_insider"), color=C_PUB, marker="v", ls="-.",
ax.semilogy(x, col(r, "ter_insider"), **STY["insider"],
markevery=(0, 2), label=LBL["insider"], **UNDER)
ax.semilogy(x, col(r, "ter_eve"), color=C_EVE, marker="s", ls="--",
ax.semilogy(x, col(r, "ter_eve"), **STY["eve"],
markevery=(1, 2), label=LBL["outsider"], **OVER)
ax.set_xlabel("SNR (dB)")
ax.set_ylabel("TER")
@@ -444,7 +465,14 @@ def fig_kpa():
ser = [float(row["eve_ser"]) for row in rows]
ax.semilogx(n, ser, color=c, marker=mk, ls="-",
markevery=(off, 4), markerfacecolor="none" if off else c,
label=LBL["mask"] + f", {int(snr)} dB")
label=f"KM (str.), {int(snr)} dB")
if snr == 10.0:
kl = [q for q in load("kpa_learned.csv")
if float(q["snr_db"]) == snr]
ax.semilogx([float(q["n_frames"]) for q in kl],
[float(q["eve_ser"]) for q in kl], **STY["km_lrn"],
markevery=(2, 4),
label=f"KM (lrn.), {int(snr)} dB")
try:
p = load("pkpa.csv")
ax.semilogx(col(p, "n_frames"), col(p, "eve_ser"), color=C_MATCH,
@@ -458,7 +486,7 @@ def fig_kpa():
# scheme-comparison table
legit = main_legit()
ax.axhline(legit, color=C_OMA, ls=(0, (4, 2)), lw=0.9,
label=LBL["legit"])
label=LBL["legit_ref"])
ax.set_xlabel("Known-plaintext frames $N$")
ax.set_ylabel("Eavesdropper SER")
ax.set_xscale("log", base=2)
+2
View File
@@ -0,0 +1,2 @@
scheme,legit_ser,eve_out,eve_in,jam0_ser
proposed_learned,0.06358416667,0.9998083333,0.9999833333,0.4046066667
1 scheme legit_ser eve_out eve_in jam0_ser
2 proposed_learned 0.06358416667 0.9998083333 0.9999833333 0.4046066667
+43
View File
@@ -0,0 +1,43 @@
snr_db,n_frames,kappa,eve_ser
0,1,0.2127109103,0.993336
0,2,0.7559393242,0.666508
0,3,0.8627683729,0.392272125
0,4,0.9179756209,0.218212875
0,5,0.945390512,0.14425925
0,6,0.9590921029,0.107493
0,8,0.9725584686,0.086112625
0,10,0.9778045967,0.07933375
0,12,0.9831736788,0.07420325
0,16,0.9879393309,0.070712875
0,24,0.9925390184,0.067800375
0,32,0.9945808738,0.06649325
0,48,0.9965663388,0.065265
0,64,0.9975094497,0.065024875
10,1,0.3165432975,0.948993875
10,2,0.9290210679,0.19776825
10,3,0.9781143948,0.095876875
10,4,0.9896475986,0.070495125
10,5,0.9934410676,0.067297125
10,6,0.9953705788,0.06628575
10,8,0.9971551418,0.06520175
10,10,0.9979188025,0.064684875
10,12,0.9982561454,0.06454375
10,16,0.9987509355,0.06426625
10,24,0.9992754847,0.064091125
10,32,0.9994516179,0.06386675
10,48,0.9996520028,0.063819875
10,64,0.999746412,0.063847125
20,1,0.742194891,0.513137625
20,2,0.9947786465,0.06753025
20,3,0.9986294076,0.06438075
20,4,0.9992210969,0.064160375
20,5,0.9994008377,0.064080125
20,6,0.9995701849,0.063900375
20,8,0.9997365534,0.063852875
20,10,0.9998067141,0.063813
20,12,0.9998438716,0.06370225
20,16,0.9998808399,0.063670875
20,24,0.9999239221,0.06380125
20,32,0.9999452353,0.063820625
20,48,0.9999649763,0.063811
20,64,0.9999733046,0.06377525
1 snr_db n_frames kappa eve_ser
2 0 1 0.2127109103 0.993336
3 0 2 0.7559393242 0.666508
4 0 3 0.8627683729 0.392272125
5 0 4 0.9179756209 0.218212875
6 0 5 0.945390512 0.14425925
7 0 6 0.9590921029 0.107493
8 0 8 0.9725584686 0.086112625
9 0 10 0.9778045967 0.07933375
10 0 12 0.9831736788 0.07420325
11 0 16 0.9879393309 0.070712875
12 0 24 0.9925390184 0.067800375
13 0 32 0.9945808738 0.06649325
14 0 48 0.9965663388 0.065265
15 0 64 0.9975094497 0.065024875
16 10 1 0.3165432975 0.948993875
17 10 2 0.9290210679 0.19776825
18 10 3 0.9781143948 0.095876875
19 10 4 0.9896475986 0.070495125
20 10 5 0.9934410676 0.067297125
21 10 6 0.9953705788 0.06628575
22 10 8 0.9971551418 0.06520175
23 10 10 0.9979188025 0.064684875
24 10 12 0.9982561454 0.06454375
25 10 16 0.9987509355 0.06426625
26 10 24 0.9992754847 0.064091125
27 10 32 0.9994516179 0.06386675
28 10 48 0.9996520028 0.063819875
29 10 64 0.999746412 0.063847125
30 20 1 0.742194891 0.513137625
31 20 2 0.9947786465 0.06753025
32 20 3 0.9986294076 0.06438075
33 20 4 0.9992210969 0.064160375
34 20 5 0.9994008377 0.064080125
35 20 6 0.9995701849 0.063900375
36 20 8 0.9997365534 0.063852875
37 20 10 0.9998067141 0.063813
38 20 12 0.9998438716 0.06370225
39 20 16 0.9998808399 0.063670875
40 20 24 0.9999239221 0.06380125
41 20 32 0.9999452353 0.063820625
42 20 48 0.9999649763 0.063811
43 20 64 0.9999733046 0.06377525
+9
View File
@@ -0,0 +1,9 @@
block,legit_ser,eve_ser
0,0.06381666667,0.9999375
1,0.06395583333,0.9981941667
2,0.06397833333,0.999985
3,0.06386833333,0.9983758333
4,0.06338666667,0.9999908333
5,0.06366416667,0.9999133333
6,0.06398416667,0.9999433333
7,0.06390583333,0.9809091667
1 block legit_ser eve_ser
2 0 0.06381666667 0.9999375
3 1 0.06395583333 0.9981941667
4 2 0.06397833333 0.999985
5 3 0.06386833333 0.9983758333
6 4 0.06338666667 0.9999908333
7 5 0.06366416667 0.9999133333
8 6 0.06398416667 0.9999433333
9 7 0.06390583333 0.9809091667
+1
View File
@@ -2,3 +2,4 @@ scheme,legit,eve,entropy_bits
None (fixed key),0.05300666667,0.9997075,23.76910417
Fresh orthogonal keys,0.1215548611,0.9996535069,23.76910417
Invariant,0.05304121528,0.9995528819,364.5801064
"Invariant, learned keys",0.063800,0.997200,364.5801064
1 scheme legit eve entropy_bits
2 None (fixed key) 0.05300666667 0.9997075 23.76910417
3 Fresh orthogonal keys 0.1215548611 0.9996535069 23.76910417
4 Invariant 0.05304121528 0.9995528819 364.5801064
5 Invariant, learned keys 0.063800 0.997200 364.5801064
+1
View File
@@ -4,3 +4,4 @@ public_mask,0.0529425,0.0529425,0.0529425,0.83882
perm_key,0.0528525,0.9999925,0.0528525,0.36425
index_cipher,0.0529425,0.9999847412,0.9999847412,0.83882
oma_plain,0.08056383667,0.08056383667,0.08056383667,nan
proposed_learned,0.06358416667,0.9998083333,0.9999833333,0.4046066667
1 scheme legit_ser eve_out eve_in jam0_ser
4 perm_key 0.0528525 0.9999925 0.0528525 0.36425
5 index_cipher 0.0529425 0.9999847412 0.9999847412 0.83882
6 oma_plain 0.08056383667 0.08056383667 0.08056383667 nan
7 proposed_learned 0.06358416667 0.9998083333 0.9999833333 0.4046066667
+8
View File
@@ -0,0 +1,8 @@
jsr_db,blind,matched,nojam
-10,0.117582,0.40832,0.062852
-5,0.215158,0.657572,0.062852
0,0.404244,0.851282,0.062852
5,0.648786,0.94662,0.062852
10,0.839218,0.982652,0.062852
15,0.939304,0.994184,0.062852
20,0.979206,0.99818,0.062852
1 jsr_db blind matched nojam
2 -10 0.117582 0.40832 0.062852
3 -5 0.215158 0.657572 0.062852
4 0 0.404244 0.851282 0.062852
5 5 0.648786 0.94662 0.062852
6 10 0.839218 0.982652 0.062852
7 15 0.939304 0.994184 0.062852
8 20 0.979206 0.99818 0.062852
+9
View File
@@ -0,0 +1,9 @@
L,d,legit_ser,eve_ser,mask_xcorr,oma
8,32,0.9297855,0.9998735,0.007307400461,0.6849191155
12,48,0.416604,0.9997065,0.005153660662,nan
16,64,0.2762895,0.999912,0.007116591092,0.2747696909
20,80,0.2076175,0.999383,0.003162040841,0.2289444229
24,96,0.1829615,0.999894,0.002973971656,0.1961714033
32,128,0.131901,0.999616,0.005575809628,0.1524639978
48,192,0.090206,0.9994575,0.005743456539,0.1054308944
64,256,0.0635265,0.999637,0.006678360514,0.08056383667
1 L d legit_ser eve_ser mask_xcorr oma
2 8 32 0.9297855 0.9998735 0.007307400461 0.6849191155
3 12 48 0.416604 0.9997065 0.005153660662 nan
4 16 64 0.2762895 0.999912 0.007116591092 0.2747696909
5 20 80 0.2076175 0.999383 0.003162040841 0.2289444229
6 24 96 0.1829615 0.999894 0.002973971656 0.1961714033
7 32 128 0.131901 0.999616 0.005575809628 0.1524639978
8 48 192 0.090206 0.9994575 0.005743456539 0.1054308944
9 64 256 0.0635265 0.999637 0.006678360514 0.08056383667
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.