SPB Git

spb/wp34_uqo

Public
3.2 KB · 71 lines python
1"""Gate: signatures produced by the Rust engines (libsecp256k1 via rust-secp256k1, RustCrypto k256)2must verify under the pure-Python exact-arithmetic references src/wp34/{ecdsa,schnorr}.py, and the3Python references must re-derive the same deterministic signatures byte for byte.45The triples are written by experiments/signature_benchmarks/sigbench (--crosscheck-out) through6run_bench.py into results/signature_benchmarks/crosscheck_triples_<host>.json. If no such file7exists the test builds the crate and generates a small set itself.8"""9import json, pathlib, subprocess, sys1011import pytest1213ROOT = pathlib.Path(__file__).resolve().parents[1]14sys.path.insert(0, str(ROOT / "src"))15sys.path.insert(0, str(ROOT / "experiments" / "signature_benchmarks"))16from python_crosscheck import crosscheck  # noqa: E40217from wp34 import schnorr as B  # noqa: E4021819RESULTS = ROOT / "results" / "signature_benchmarks"20CRATE = ROOT / "experiments" / "signature_benchmarks" / "sigbench"212223def _triples_file(tmp_path_factory) -> pathlib.Path:24    files = sorted(RESULTS.glob("crosscheck_triples_*.json")) if RESULTS.exists() else []25    if files:26        return files[0]27    binary = CRATE / "target" / "release" / "sigbench"28    if not binary.exists():29        subprocess.run(["cargo", "build", "--release"], cwd=CRATE, check=True)30    out = tmp_path_factory.mktemp("sig") / "triples.json"31    subprocess.run([str(binary), "--vectors", str(ROOT / "data/vectors/bip340_test_vectors.csv"),32                    "--reps", "1", "--batch-ops", "50", "--batch-min-sigs", "50", "--batch-sizes", "1,4",33                    "--crosscheck-n", "40", "--python-crosscheck-n", "40", "--bootstrap", "10",34                    "--crosscheck-out", str(out)], check=True, capture_output=True)35    return out363738@pytest.fixture(scope="module")39def triples(tmp_path_factory):40    return _triples_file(tmp_path_factory)414243def test_rust_signatures_verify_under_python_reference(triples):44    c = crosscheck(triples, resign=True)45    n = c["n"]46    assert n >= 4047    assert c["ecdsa_k256_sig_verified_by_python"] == n48    assert c["ecdsa_libsecp_sig_verified_by_python"] == n49    assert c["schnorr_k256_sig_verified_by_python"] == n50    assert c["schnorr_libsecp_sig_verified_by_python"] == n51    # deterministic nonces: RFC 6979 (ECDSA) and BIP340 aux-rand nonce derivation -> identical bytes52    assert c["ecdsa_python_resign_identical"] == n53    assert c["schnorr_python_resign_identical"] == n54    # negative control: one flipped bit must be rejected by the reference55    assert c["tampered_sig_rejected_by_python"] == n56    assert c["all_pass"]575859def test_bip340_vectors_python_reference():60    """The Python reference itself must agree with the official BIP340 vectors (independent of Rust)."""61    rows = (ROOT / "data/vectors/bip340_test_vectors.csv").read_text().splitlines()[1:]62    n_checked = 063    for row in rows:64        f = row.split(",")65        pk, msg, sig, expected = bytes.fromhex(f[2]), bytes.fromhex(f[4]), bytes.fromhex(f[5]), f[6] == "TRUE"66        assert B.verify(msg, pk, sig) == expected, f"vector {f[0]}: {f[7]}"67        if f[1]:68            assert B.sign(msg, bytes.fromhex(f[1]), bytes.fromhex(f[3])) == sig, f"vector {f[0]} sign"69        n_checked += 170    assert n_checked == 1971
Files · main
Menu

Theme