1#!/usr/bin/env python2"""Generate tests/fixtures/ecdlp_instances.json for rho_engine.3410 generic prime-order curves for each of 20, 24, 28, 32 bits and 10 j = 0 curves (a = 0, p ≡ 1 mod 3)5for each of 24 and 32 bits, each with a random secret d and Q = dG, computed with the pure-Python6reference `wp34.ec` (point counting by PARI/GP `ellcard`). All integers are decimal strings.78Usage (from the repository root): PYTHONPATH=src .venv/bin/python experiments/synthetic_ecdlp/rho_engine/scripts/gen_fixtures.py [--seed 34] [--out tests/fixtures/ecdlp_instances.json]9"""10import argparse, json, random, pathlib, sys, time1112ROOT = pathlib.Path(__file__).resolve().parents[4]13sys.path.insert(0, str(ROOT / "src"))14from wp34.ec import random_prime_order_curve, cube_roots_of_unity, endomorphism_lambda # noqa: E402151617def main():18 ap = argparse.ArgumentParser()19 ap.add_argument("--seed", type=int, default=34)20 ap.add_argument("--out", default=str(ROOT / "tests" / "fixtures" / "ecdlp_instances.json"))21 ap.add_argument("--per-size", type=int, default=10)22 args = ap.parse_args()23 rng = random.Random(args.seed)24 plan = [(20, False), (24, False), (28, False), (32, False), (24, True), (32, True)]25 out = []26 t0 = time.time()27 for bits, j0 in plan:28 for i in range(args.per_size):29 E = random_prime_order_curve(bits, rng, j0=j0)30 d = rng.randrange(1, E.n)31 Q = E.mul(d, E.G)32 assert E.is_on_curve(Q) and Q is not None33 rec = {34 "label": f"{bits}b{'-j0' if j0 else ''}-{i:02d}",35 "bits": bits, "j0": j0,36 "p": str(E.p), "a": str(E.a), "b": str(E.b), "n": str(E.n),37 "gx": str(E.G[0]), "gy": str(E.G[1]), "qx": str(Q[0]), "qy": str(Q[1]),38 "d": str(d),39 }40 if j0:41 assert E.n % 3 == 1, "prime order n of a j=0 curve with p ≡ 1 mod 3 must be ≡ 1 mod 3"42 betas = cube_roots_of_unity(E.p, rng)43 beta = betas[0]44 lam = endomorphism_lambda(E, beta)45 assert (beta * E.G[0] % E.p, E.G[1]) == E.mul(lam, E.G)46 rec["beta"] = str(beta)47 rec["lambda"] = str(lam)48 out.append(rec)49 print(f"{rec['label']}: p={E.p} n={E.n} d={d}", file=sys.stderr)50 doc = {"generator": "experiments/synthetic_ecdlp/rho_engine/scripts/gen_fixtures.py", "seed": args.seed,51 "reference": "src/wp34/ec.py (random_prime_order_curve via PARI/GP ellcard)",52 "elapsed_s": round(time.time() - t0, 1), "instances": out}53 pathlib.Path(args.out).write_text(json.dumps(doc, indent=1) + "\n")54 print(f"wrote {len(out)} instances to {args.out}", file=sys.stderr)555657if __name__ == "__main__":58 main()59