BIP461: add test vectors and reference implementation (#2328)

All vectors were tested against libsecp256k1, and
all verification vectors were checked against OpenSSL.
A check was also added to the `verify` specification
to reject pubkeys with x or y coordinates greater than
or equal to `p`.
This commit is contained in:
Liam Gilligan authored and GitHub committed 2026-11-03 14:23:55 -08:00
1 parent 21bfd24d6e
commit 5bbeeae962
7 files changed
+512

No files matched your search

+59
View File
@@ -0,0 +1,59 @@
"""Run the low-R grinding test vectors."""
import csv
import os
import sys
import reference
FILENAME_SIGN_TEST = os.path.join(sys.path[0], 'sign_test_vectors.csv')
FILENAME_VERIFY_TEST = os.path.join(sys.path[0], 'verify_test_vectors.csv')
def sig_from_hex(s):
"""Parse a compact signature into the integer pair (r, s)."""
b = bytes.fromhex(s)
assert len(b) == 64
return (int.from_bytes(b[:32], 'big'), int.from_bytes(b[32:], 'big'))
def sig_hex(sig):
return (reference.bytes_from_int(sig[0]) + reference.bytes_from_int(sig[1])).hex()
def pubkey_from_hex(s):
"""Parse an uncompressed SEC 1 public key into a point."""
b = bytes.fromhex(s)
if b == b'\x00':
return None
assert len(b) == 65 and b[0] == 0x04
return (int.from_bytes(b[1:33], 'big'), int.from_bytes(b[33:], 'big'))
def result_from_str(s):
assert s in ('TRUE', 'FALSE')
return s == 'TRUE'
with open(FILENAME_SIGN_TEST, newline='', encoding='utf-8') as csvfile:
print(f"Running {FILENAME_SIGN_TEST} tests...")
reader = csv.DictReader(csvfile)
for row in reader:
seckey = bytes.fromhex(row['seckey'])
msghash = bytes.fromhex(row['msghash'])
if row['sig'] == '':
# An empty signature means signing must fail for this secret key.
raised = False
try:
reference.deterministic_sign(seckey, msghash)
except ValueError:
raised = True
assert raised
continue
sig = reference.deterministic_sign(seckey, msghash)
assert reference.is_low_r(sig)
assert row['sig'] == sig_hex(sig)
with open(FILENAME_VERIFY_TEST, newline='', encoding='utf-8') as csvfile:
print(f"Running {FILENAME_VERIFY_TEST} tests...")
reader = csv.DictReader(csvfile)
for row in reader:
pubkey = pubkey_from_hex(row['pubkey'])
msghash = bytes.fromhex(row['msghash'])
sig = sig_from_hex(row['sig'])
assert reference.verify(sig, pubkey, msghash) == result_from_str(row['result'])