diff --git a/test/functional/test_framework/ellsq.py b/test/functional/test_framework/ellsq.py index 5e3427a2326e62..39c5ac8c42c9ab 100644 --- a/test/functional/test_framework/ellsq.py +++ b/test/functional/test_framework/ellsq.py @@ -5,6 +5,11 @@ keys, and is trivially vulnerable to side channel attacks. Do not use for anything but tests.""" +import random +import unittest + +from .key import modsqrt, SECP256K1, SECP256K1_G, SECP256K1_ORDER + class fe: """Prime field over 2^256 - 2^32 - 977""" p = 2**256 - 2**32 - 977 @@ -159,4 +164,44 @@ def SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p): [SECP256K1_GE_CONST(0x49a0dc06, 0x8c3f117a, 0xefdc842d, 0x3d358153, 0xf677f04c, 0x6dabc9c9, 0x1b09d452, 0xfef27b66, 0x7b944da4, 0x8a175dbc, 0x444ead8d, 0xb82eff66, 0xb081a8aa, 0xe6453fed, 0x2bca9720, 0xb44dd6e5), [SECP256K1_FE_CONST(0x7bf1e2b1, 0x720c1c44, 0x0db64687, 0xf16439fa, 0x41b39833, 0x8095f24e, 0xbeec0cfa, 0x88750dc9), SECP256K1_FE_CONST(0xdc97e26d, 0x3137445d, 0x6c1269b6, 0x1a765501, 0x0c19c36a, 0x2e361066, 0xe31e2bb1, 0x0403470b), SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000), SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000)]], [SECP256K1_GE_CONST(0xd09a4047, 0xf158fe52, 0xf96c661d, 0x02c68657, 0xc4c976ea, 0x96ea85ef, 0x46d6985b, 0xd540756b, 0xe793bfaa, 0xe9300f18, 0xe6f9b55a, 0xae263223, 0x68b61d51, 0xae5022ef, 0xe266c72d, 0x574178bc), [SECP256K1_FE_CONST(0x7e6175fd, 0xfbb9fb4f, 0xaf6e2b92, 0x5ef86c4a, 0x444d819a, 0xaa82dbee, 0x545d3d9b, 0x296375be), SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000), SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000), SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000)]], [SECP256K1_GE_CONST(0x34986625, 0x04b73c7c, 0x8cecb6c3, 0x3cd493bd, 0xfc190e0f, 0x87d913d7, 0xff9ad42e, 0x222bfe95, 0x245b3a61, 0xb8d46997, 0xf14f2fea, 0x28748996, 0x91eb3254, 0x2b9907d6, 0x5eb9d21d, 0x42454021), [SECP256K1_FE_CONST(0x7f556282, 0xc3dd9d26, 0x3390d6bb, 0xddada698, 0xab8fd7c7, 0xd1a06498, 0xf42b3043, 0x7c8361ad), SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000), SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000), SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000)]] -] \ No newline at end of file +] + +class TestFrameworkEllsq(unittest.TestCase): + def test_fe_to_ge_to_fe(self): + for i in range(100): + matches = 0 + t = fe(random.randrange(1, SECP256K1_ORDER)) + ge = f(t) + jac_ge = (ge[0].val, ge[1].val, 1) + assert(SECP256K1.on_curve(jac_ge)) + # t should appear exactly once in preimages + for j in range(1,5): + field_ele = r(ge[0], ge[1], j) + if field_ele is not None: + matches += (field_ele == t) + assert(matches == 1) + + def test_ge_to_fe_to_ge(self): + for i in range(100): + m = random.randrange(1, SECP256K1_ORDER) + A = SECP256K1.affine(SECP256K1.mul([(SECP256K1_G, m)])) + ge = (fe(A[0]), fe(A[1])) + preimages = [] + for j in range(1, 5): + field_ele = r(ge[0], ge[1], j) + if field_ele is not None: + preimages.append(field_ele) + group_ele = f(field_ele) + assert (ge[0] == group_ele[0] and ge[1] == group_ele[1]) + assert len(set(preimages)) == len(preimages) + + def test_ellsq_mapping(self): + for test_vector in ellsq_tests: + ge = test_vector[0] + fe = test_vector[1] + for j in range(1, 5): + field_ele = r(ge[0], ge[1], j) + if field_ele is not None: + assert(field_ele == fe[j-1]) + group_ele = f(field_ele) + assert (ge[0] == group_ele[0] and ge[1] == group_ele[1]) \ No newline at end of file