#!/usr/bin/env python """Generate tests/fixtures/ecdlp_instances.json for rho_engine. 10 generic prime-order curves for each of 20, 24, 28, 32 bits and 10 j = 0 curves (a = 0, p ≡ 1 mod 3) for each of 24 and 32 bits, each with a random secret d and Q = dG, computed with the pure-Python reference `wp34.ec` (point counting by PARI/GP `ellcard`). All integers are decimal strings. Usage (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] """ import argparse, json, random, pathlib, sys, time ROOT = pathlib.Path(__file__).resolve().parents[4] sys.path.insert(0, str(ROOT / "src")) from wp34.ec import random_prime_order_curve, cube_roots_of_unity, endomorphism_lambda # noqa: E402 def main(): ap = argparse.ArgumentParser() ap.add_argument("--seed", type=int, default=34) ap.add_argument("--out", default=str(ROOT / "tests" / "fixtures" / "ecdlp_instances.json")) ap.add_argument("--per-size", type=int, default=10) args = ap.parse_args() rng = random.Random(args.seed) plan = [(20, False), (24, False), (28, False), (32, False), (24, True), (32, True)] out = [] t0 = time.time() for bits, j0 in plan: for i in range(args.per_size): E = random_prime_order_curve(bits, rng, j0=j0) d = rng.randrange(1, E.n) Q = E.mul(d, E.G) assert E.is_on_curve(Q) and Q is not None rec = { "label": f"{bits}b{'-j0' if j0 else ''}-{i:02d}", "bits": bits, "j0": j0, "p": str(E.p), "a": str(E.a), "b": str(E.b), "n": str(E.n), "gx": str(E.G[0]), "gy": str(E.G[1]), "qx": str(Q[0]), "qy": str(Q[1]), "d": str(d), } if j0: assert E.n % 3 == 1, "prime order n of a j=0 curve with p ≡ 1 mod 3 must be ≡ 1 mod 3" betas = cube_roots_of_unity(E.p, rng) beta = betas[0] lam = endomorphism_lambda(E, beta) assert (beta * E.G[0] % E.p, E.G[1]) == E.mul(lam, E.G) rec["beta"] = str(beta) rec["lambda"] = str(lam) out.append(rec) print(f"{rec['label']}: p={E.p} n={E.n} d={d}", file=sys.stderr) doc = {"generator": "experiments/synthetic_ecdlp/rho_engine/scripts/gen_fixtures.py", "seed": args.seed, "reference": "src/wp34/ec.py (random_prime_order_curve via PARI/GP ellcard)", "elapsed_s": round(time.time() - t0, 1), "instances": out} pathlib.Path(args.out).write_text(json.dumps(doc, indent=1) + "\n") print(f"wrote {len(out)} instances to {args.out}", file=sys.stderr) if __name__ == "__main__": main()