Skip to content

Commit 8e7aef0

Browse files
committed
Fix point_from_bytes accepting out-of-range pubkeys and add test vector
1 parent 1bb025a commit 8e7aef0

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

bip-schnorr/reference.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ def bytes_from_point(P):
5353

5454
def point_from_bytes(b):
5555
x = int_from_bytes(b)
56+
if x >= p:
57+
return None
5658
y_sq = (pow(x, 3, p) + 7) % p
5759
y = pow(y_sq, (p + 1) // 4, p)
5860
if pow(y, 2, p) != y_sq:

bip-schnorr/test-vectors.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,14 @@ def vector4():
6969
default_seckey = bytes_from_int(0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF)
7070
default_msg = bytes_from_int(0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89)
7171

72+
# Public key is not on the curve
7273
def vector5():
74+
# This creates a dummy signature that doesn't have anything to do with the
75+
# public key.
7376
seckey = default_seckey
7477
msg = default_msg
7578
sig = schnorr_sign(msg, seckey)
7679

77-
# Public key is not on the curve
7880
pubkey = bytes_from_int(0xEEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34)
7981
assert(point_from_bytes(pubkey) is None)
8082

@@ -185,6 +187,27 @@ def vector13():
185187

186188
return (None, pubkey_gen(seckey), msg, sig, "FALSE", "sig[32:64] is equal to curve order")
187189

190+
# Test out of range pubkey
191+
# It's cryptographically impossible to create a test vector that fails if run
192+
# in an implementation which accepts out of range pubkeys because we can't find
193+
# a secret key for such a public key and therefore can not create a signature.
194+
# This test vector just increases test coverage.
195+
def vector14():
196+
# This creates a dummy signature that doesn't have anything to do with the
197+
# public key.
198+
seckey = default_seckey
199+
msg = default_msg
200+
sig = schnorr_sign(msg, seckey)
201+
202+
pubkey_int = p + 1
203+
pubkey = bytes_from_int(pubkey_int)
204+
assert(point_from_bytes(pubkey) is None)
205+
# If an implementation would reduce a given public key modulo p then the
206+
# pubkey would be valid
207+
assert(point_from_bytes(bytes_from_int(pubkey_int % p)) is not None)
208+
209+
return (None, pubkey, msg, sig, "FALSE", "public key is not a valid X coordinate because it exceeds the field size")
210+
188211
vectors = [
189212
vector0(),
190213
vector1(),
@@ -200,6 +223,7 @@ def vector13():
200223
vector11(),
201224
vector12(),
202225
vector13(),
226+
vector14()
203227
]
204228

205229
# Converts the byte strings of a test vector into hex strings

0 commit comments

Comments
 (0)