diff options
Diffstat (limited to 'bip-0340/reference.py')
-rw-r--r-- | bip-0340/reference.py | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/bip-0340/reference.py b/bip-0340/reference.py index f2a944f..9b5592e 100644 --- a/bip-0340/reference.py +++ b/bip-0340/reference.py @@ -51,7 +51,7 @@ def bytes_from_int(x): def bytes_from_point(P): return bytes_from_int(x(P)) -def point_from_bytes(b): +def lift_x_square_y(b): x = int_from_bytes(b) if x >= p: return None @@ -61,6 +61,13 @@ def point_from_bytes(b): return None return [x, y] +def lift_x_even_y(b): + P = lift_x_square_y(b) + if P is None: + return None + else: + return [x(P), y(P) if y(P) % 2 == 0 else p - y(P)] + def int_from_bytes(b): return int.from_bytes(b, byteorder="big") @@ -73,6 +80,9 @@ def is_square(x): def has_square_y(P): return not is_infinity(P) and is_square(y(P)) +def has_even_y(P): + return y(P) % 2 == 0 + def pubkey_gen(seckey): x = int_from_bytes(seckey) if not (1 <= x <= n - 1): @@ -87,13 +97,13 @@ def schnorr_sign(msg, seckey0): if not (1 <= seckey0 <= n - 1): raise ValueError('The secret key must be an integer in the range 1..n-1.') P = point_mul(G, seckey0) - seckey = seckey0 if has_square_y(P) else n - seckey0 - k0 = int_from_bytes(tagged_hash("BIPSchnorrDerive", bytes_from_int(seckey) + msg)) % n + seckey = seckey0 if has_even_y(P) else n - seckey0 + k0 = int_from_bytes(tagged_hash("BIP340/nonce", bytes_from_int(seckey) + bytes_from_point(P) + msg)) % n if k0 == 0: raise RuntimeError('Failure. This happens only with negligible probability.') R = point_mul(G, k0) k = n - k0 if not has_square_y(R) else k0 - e = int_from_bytes(tagged_hash("BIPSchnorr", bytes_from_point(R) + bytes_from_point(P) + msg)) % n + e = int_from_bytes(tagged_hash("BIP340/challenge", bytes_from_point(R) + bytes_from_point(P) + msg)) % n return bytes_from_point(R) + bytes_from_int((k + e * seckey) % n) def schnorr_verify(msg, pubkey, sig): @@ -103,14 +113,14 @@ def schnorr_verify(msg, pubkey, sig): raise ValueError('The public key must be a 32-byte array.') if len(sig) != 64: raise ValueError('The signature must be a 64-byte array.') - P = point_from_bytes(pubkey) + P = lift_x_even_y(pubkey) if (P is None): return False r = int_from_bytes(sig[0:32]) s = int_from_bytes(sig[32:64]) if (r >= p or s >= n): return False - e = int_from_bytes(tagged_hash("BIPSchnorr", sig[0:32] + pubkey + msg)) % n + e = int_from_bytes(tagged_hash("BIP340/challenge", sig[0:32] + pubkey + msg)) % n R = point_add(point_mul(G, s), point_mul(P, n - e)) if R is None or not has_square_y(R) or x(R) != r: return False |