Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/schnorr.py
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | def jacobi(a, n): | ||||
assert n & 1 == 1 | assert n & 1 == 1 | ||||
a = a % n | a = a % n | ||||
if a == 0: | if a == 0: | ||||
return 0 | return 0 | ||||
if a == 1: | if a == 1: | ||||
return 1 | return 1 | ||||
a1, e = a, 0 | a1, e = a, 0 | ||||
while a1 & 1 == 0: | while a1 & 1 == 0: | ||||
a1, e = a1 >> 1, e+1 | a1, e = a1 >> 1, e + 1 | ||||
if e & 1 == 0 or n & 7 == 1 or n & 7 == 7: | if e & 1 == 0 or n & 7 == 1 or n & 7 == 7: | ||||
s = 1 | s = 1 | ||||
else: | else: | ||||
s = -1 | s = -1 | ||||
if a1 == 1: | if a1 == 1: | ||||
return s | return s | ||||
if n & 3 == 3 and a1 & 3 == 3: | if n & 3 == 3 and a1 & 3 == 3: | ||||
s = -s | s = -s | ||||
return s * jacobi(n % a1, a1) | return s * jacobi(n % a1, a1) | ||||
def nonce_function_rfc6979(privkeybytes, msg32, algo16=b'', ndata=b''): | def nonce_function_rfc6979(privkeybytes, msg32, algo16=b'', ndata=b''): | ||||
# RFC6979 deterministic nonce generation, done in libsecp256k1 style. | # RFC6979 deterministic nonce generation, done in libsecp256k1 style. | ||||
# see nonce_function_rfc6979() in secp256k1.c; and details in hash_impl.h | # see nonce_function_rfc6979() in secp256k1.c; and details in hash_impl.h | ||||
assert len(privkeybytes) == 32 | assert len(privkeybytes) == 32 | ||||
assert len(msg32) == 32 | assert len(msg32) == 32 | ||||
assert len(algo16) in (0, 16) | assert len(algo16) in (0, 16) | ||||
assert len(ndata) in (0, 32) | assert len(ndata) in (0, 32) | ||||
V = b'\x01'*32 | V = b'\x01' * 32 | ||||
K = b'\x00'*32 | K = b'\x00' * 32 | ||||
blob = bytes(privkeybytes) + msg32 + ndata + algo16 | blob = bytes(privkeybytes) + msg32 + ndata + algo16 | ||||
# initialize | # initialize | ||||
K = hmac.HMAC(K, V+b'\x00'+blob, 'sha256').digest() | K = hmac.HMAC(K, V + b'\x00' + blob, 'sha256').digest() | ||||
V = hmac.HMAC(K, V, 'sha256').digest() | V = hmac.HMAC(K, V, 'sha256').digest() | ||||
K = hmac.HMAC(K, V+b'\x01'+blob, 'sha256').digest() | K = hmac.HMAC(K, V + b'\x01' + blob, 'sha256').digest() | ||||
V = hmac.HMAC(K, V, 'sha256').digest() | V = hmac.HMAC(K, V, 'sha256').digest() | ||||
# loop forever until an in-range k is found | # loop forever until an in-range k is found | ||||
k = 0 | k = 0 | ||||
while True: | while True: | ||||
# see RFC6979 3.2.h.2 : we take a shortcut and don't build T in | # see RFC6979 3.2.h.2 : we take a shortcut and don't build T in | ||||
# multiple steps since the first step is always the right size for | # multiple steps since the first step is always the right size for | ||||
# our purpose. | # our purpose. | ||||
V = hmac.HMAC(K, V, 'sha256').digest() | V = hmac.HMAC(K, V, 'sha256').digest() | ||||
T = V | T = V | ||||
assert len(T) >= 32 | assert len(T) >= 32 | ||||
k = int.from_bytes(T, 'big') | k = int.from_bytes(T, 'big') | ||||
if k > 0 and k < SECP256K1_ORDER: | if k > 0 and k < SECP256K1_ORDER: | ||||
break | break | ||||
K = hmac.HMAC(K, V+b'\x00', 'sha256').digest() | K = hmac.HMAC(K, V + b'\x00', 'sha256').digest() | ||||
V = hmac.HMAC(K, V, 'sha256').digest() | V = hmac.HMAC(K, V, 'sha256').digest() | ||||
return k | return k | ||||
def sign(privkeybytes, msg32): | def sign(privkeybytes, msg32): | ||||
"""Create Schnorr signature (BIP-Schnorr convention).""" | """Create Schnorr signature (BIP-Schnorr convention).""" | ||||
assert len(privkeybytes) == 32 | assert len(privkeybytes) == 32 | ||||
assert len(msg32) == 32 | assert len(msg32) == 32 | ||||
Show All 34 Lines | if jacobi(Ry, SECP256K1_FIELDSIZE) == -1: | ||||
k = SECP256K1_ORDER - k | k = SECP256K1_ORDER - k | ||||
rbytes = Rbuf[1:33] # x coord big-endian | rbytes = Rbuf[1:33] # x coord big-endian | ||||
e = int.from_bytes(hashlib.sha256( | e = int.from_bytes(hashlib.sha256( | ||||
rbytes + pubkeybuf + msg32).digest(), 'big') | rbytes + pubkeybuf + msg32).digest(), 'big') | ||||
privkey = int.from_bytes(privkeybytes, 'big') | privkey = int.from_bytes(privkeybytes, 'big') | ||||
s = (k + e*privkey) % SECP256K1_ORDER | s = (k + e * privkey) % SECP256K1_ORDER | ||||
return rbytes + s.to_bytes(32, 'big') | return rbytes + s.to_bytes(32, 'big') | ||||
def getpubkey(privkeybytes, compressed=True): | def getpubkey(privkeybytes, compressed=True): | ||||
assert len(privkeybytes) == 32 | assert len(privkeybytes) == 32 | ||||
encoding = POINT_CONVERSION_COMPRESSED if compressed else POINT_CONVERSION_UNCOMPRESSED | encoding = POINT_CONVERSION_COMPRESSED if compressed else POINT_CONVERSION_UNCOMPRESSED | ||||
▲ Show 20 Lines • Show All 42 Lines • Show Last 20 Lines |