gECC/scripts/constants_generator.py
2025-10-15 13:44:34 +02:00

360 lines
13 KiB
Python

import field
import ec
import ec_ops
import ccgen
import argparse
import pathlib
import random
import math
class CRepr:
width = 64
def repr_list(self, lst):
return '{' + ','.join(lst) + '}'
def fp(self, n):
b = []
while n > 0:
b.append(n & ((
~(
(0xFFFFFFFFFFFFFFFF << self.width) & 0xFFFFFFFFFFFFFFFF
)
) & 0xFFFFFFFFFFFFFFFF))
n >>= self.width
return self.repr_list(map(str, b))
def fp2(self, x):
a, b = x
return self.repr_list([self.fp(a), self.fp(b)])
def fp_array(self, ns):
return self.repr_list(map(self.fp, ns))
def fp2_array(self, ns):
return self.repr_list(map(self.fp2, ns))
def ec_component(self, c):
if type(c) is not tuple:
c = (c,)
return self.repr_list(map(self.fp, c))
def ec_point(self, p):
return self.repr_list(map(self.ec_component, p))
def ec_array(self, points):
return self.repr_list(map(self.ec_point, points))
def fp_constant(self, f):
return '''static constexpr FpConstant {name} {{
.bits = {bits},
.rexp = {rexp},
.pinv = {pinv}u,
.p = {p},
.p_minus_2 = {p_minus_2},
.pp = {pp},
.r = {r},
.r2 = {r2},
.adicity2 = {adicity2},
.generator={generator},
.inv2={inv2},
}};'''.format(
name=f.name,
bits=f.bits,
rexp=f.rexp,
pinv=f.pinv(f.width),
p=self.fp(f.p),
p_minus_2=self.fp(f.p - 2),
pp=self.fp(f.pp),
r=self.fp(f.r),
r2=self.fp(f.r2),
adicity2=f.adicity2,
generator=self.fp(f.generator),
inv2=self.fp(f.inv2),
)
@staticmethod
def fp2_constant(f):
return '''static constexpr Fp2Constant {name} {{
.alpha = {alpha},
}};'''.format(
name=f.name,
alpha=f.alpha,
)
# @staticmethod
def ec_constant(self, e):
return '''static constexpr ECConstant {name} {{
.a = {a},
.a_mont = {a_mont},
}};'''.format(
name=e.name,
a=e.a,
a_mont=self.fp(e.field.to_mont(e.a)),
)
@staticmethod
def ec2_constant(e):
assert e.a[1] == 0
return '''static constexpr ECConstant {name} {{
.a = {a},
}};'''.format(
name=e.name,
a=e.a[0],
)
# @staticmethod
def ecdsa_constant(self, ec):
k = math.ceil(math.log(ec.field.bits, 2))
n = 1 << k
p = ec.generator
sig_affine = [None] * (n)
for i in range(n):
sig_affine[i] = p
p = ec.affine_double(p)
return '''static constexpr ECDSAConstant G1_1_{name} {{
.K = {K},
.SIG_AFF = {SIG_AFF},
}};'''.format(
name=ec.name,
K=k,
SIG_AFF=self.ec_array(map(ec.to_mont, sig_affine)),
)
def generate_fp_test(out, name, f, k, width):
n = 1 << k
a = [random.randint(0, f.p - 1) for i in range(n)]
b = [random.randint(0, f.p - 1) for i in range(n)]
crepr = CRepr()
crepr.width = width
out.write('namespace {}_fp_test {{\n'.format(name))
out.write('static const size_t N = {};\n'.format(n))
out.write('static const uint64_t A[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(a)))
out.write('static const uint64_t B[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(b)))
out.write('static const uint64_t SUM[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array([(a[i] + b[i]) % f.p for i in range(n)])))
out.write('static const uint64_t PROD[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array([a[i] * b[i] % f.p for i in range(n)])))
# out.write('static const uint64_t PROD[{}][MAX_LIMBS] = {};\n'.format(
# n, crepr.fp_array([f.to_mont(a[i] * b[i] % f.p) for i in range(n)])))
out.write('}}\n\n'.format(name))
# pass test
# print(f.to_bytes(f.to_mont(a[0])))
# print(f.to_bytes(f.to_mont(b[0])))
# f.mont_mul(f.to_bytes(f.to_mont(a[0])), f.to_bytes(f.to_mont(b[0])), f.to_bytes(f.p))
def generate_ecdsa_test(out, f, width):
e = 0x10D51CB90C0C0522E94875A2BEA7AB72299EBE7192E64EFE0573B1C77110E5C9
priv_key = 0x128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263
k = 0xE11F5909F947D5BE08C84A22CE9F7C338F7CF4A5B941B9268025495D7D433071
s = 0xE11F5909F947D5BE08C84A22CE9F7C338F7CF4A5B941B9268025495D7D433071
r = 0x23B20B796AAAFEAAA3F1592CB9B4A93D5A8D279843E1C57980E64E0ABC5F5B05
# r = 0x23B20B796AAAFEAAA3F1592CB9B4A93D5A8D279843E1C57980E64E0ABC5F5B96
key_x = 0xD5548C7825CBB56150A3506CD57464AF8A1AE0519DFAF3C58221DC810CAF28DD
key_y = 0x921073768FE3D59CE54E79A49445CF73FED23086537027264D168946D479533E
n = 3972
random_r = [random.randint(0, f.p - 1) for i in range(n)]
random_s = [random.randint(0, f.p - 1) for i in range(n)]
random_e = [random.randint(0, f.p - 1) for i in range(n)]
random_priv_key = [random.randint(0, f.p - 1) for i in range(n)]
random_k = [random.randint(0, f.p - 1) for i in range(n)]
random_key_x = [random.randint(0, f.p - 1) for i in range(n)]
random_key_y = [random.randint(0, f.p - 1) for i in range(n)]
crepr = CRepr()
crepr.width = width
out.write('static const uint64_t E[MAX_LIMBS] = {};\n'.format(
crepr.fp(e)))
out.write('static const uint64_t PRIV_KEY[MAX_LIMBS] = {};\n'.format(
crepr.fp(priv_key)))
out.write('static const uint64_t K[MAX_LIMBS] = {};\n'.format(
crepr.fp(k)))
out.write('static const uint64_t S[MAX_LIMBS] = {};\n'.format(
crepr.fp(s)))
out.write('static const uint64_t R[MAX_LIMBS] = {};\n'.format(
crepr.fp(r)))
out.write('static const uint64_t KEY_X[MAX_LIMBS] = {};\n'.format(
crepr.fp(key_x)))
out.write('static const uint64_t KEY_Y[MAX_LIMBS] = {};\n'.format(
crepr.fp(key_y)))
out.write('static const uint64_t RANDOM_R[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(random_r)))
out.write('static const uint64_t RANDOM_S[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(random_s)))
out.write('static const uint64_t RANDOM_E[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(random_e)))
out.write('static const uint64_t RANDOM_PRIV_KEY[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(random_priv_key)))
out.write('static const uint64_t RANDOM_K[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(random_k)))
out.write('static const uint64_t RANDOM_KEY_X[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(random_key_x)))
out.write('static const uint64_t RANDOM_KEY_Y[{}][MAX_LIMBS] = {};\n'.format(
n, crepr.fp_array(random_key_y)))
# def generate_ecdsa_test(out, f, ec, width):
# e = 0x10D51CB90C0C0522E94875A2BEA7AB72299EBE7192E64EFE0573B1C77110E5C9
# priv_key = 0x128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263
# k = 0xE11F5909F947D5BE08C84A22CE9F7C338F7CF4A5B941B9268025495D7D433071
# s = 0xE11F5909F947D5BE08C84A22CE9F7C338F7CF4A5B941B9268025495D7D433071
# r = 0x23B20B796AAAFEAAA3F1592CB9B4A93D5A8D279843E1C57980E64E0ABC5F5B05
# key_x = 0xD5548C7825CBB56150A3506CD57464AF8A1AE0519DFAF3C58221DC810CAF28DD
# key_y = 0x921073768FE3D59CE54E79A49445CF73FED23086537027264D168946D479533E
# n = 1 << 10
# random_r = [random.randint(0, f.p - 1) for i in range(n)]
# random_s = [random.randint(0, f.p - 1) for i in range(n)]
# random_e = [random.randint(0, f.p - 1) for i in range(n)]
# random_priv_key = [random.randint(0, f.p - 1) for i in range(n)]
# random_k = [random.randint(0, f.p - 1) for i in range(n)]
# distinct_bases = 1<<6
# base_aff = [
# ec.random_element()
# for _ in range(distinct_bases)
# ]
# base_id = [random.randint(0, distinct_bases - 1) for i in range(n)]
# random_key_x = []
# random_key_y = []
# for i in range(n):
# x, y = base_aff[base_id[i]]
# random_key_x.append(x)
# random_key_y.append(y)
# crepr = CRepr()
# crepr.width = width
# out.write('static const uint64_t E[MAX_LIMBS] = {};\n'.format(
# crepr.fp(e)))
# out.write('static const uint64_t PRIV_KEY[MAX_LIMBS] = {};\n'.format(
# crepr.fp(priv_key)))
# out.write('static const uint64_t K[MAX_LIMBS] = {};\n'.format(
# crepr.fp(k)))
# out.write('static const uint64_t S[MAX_LIMBS] = {};\n'.format(
# crepr.fp(s)))
# out.write('static const uint64_t R[MAX_LIMBS] = {};\n'.format(
# crepr.fp(r)))
# out.write('static const uint64_t KEY_X[MAX_LIMBS] = {};\n'.format(
# crepr.fp(key_x)))
# out.write('static const uint64_t KEY_Y[MAX_LIMBS] = {};\n'.format(
# crepr.fp(key_y)))
# out.write('static const uint64_t RANDOM_R[{}][MAX_LIMBS] = {};\n'.format(
# n, crepr.fp_array(random_r)))
# out.write('static const uint64_t RANDOM_S[{}][MAX_LIMBS] = {};\n'.format(
# n, crepr.fp_array(random_s)))
# out.write('static const uint64_t RANDOM_E[{}][MAX_LIMBS] = {};\n'.format(
# n, crepr.fp_array(random_e)))
# out.write('static const uint64_t RANDOM_PRIV_KEY[{}][MAX_LIMBS] = {};\n'.format(
# n, crepr.fp_array(random_priv_key)))
# out.write('static const uint64_t RANDOM_K[{}][MAX_LIMBS] = {};\n'.format(
# n, crepr.fp_array(random_k)))
# out.write('static const uint64_t RANDOM_KEY_X[{}][MAX_LIMBS] = {};\n'.format(
# n, crepr.fp_array(random_key_x)))
# out.write('static const uint64_t RANDOM_KEY_Y[{}][MAX_LIMBS] = {};\n'.format(
# n, crepr.fp_array(random_key_y)))
random.seed(233)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--out', type=str, required=True)
args = parser.parse_args()
root = pathlib.Path(args.out)
root.mkdir(exist_ok=True)
with open(root / 'fp_constants.h', 'w') as f:
crepr_64 = CRepr()
crepr_64.width = 64
f.write(crepr_64.fp_constant(field.Fq_SECP256K1) + '\n')
f.write(crepr_64.fp_constant(field.Fq_SECP256K1_n) + '\n')
with open(root / 'ec_constants.h', 'w') as f:
crepr_64 = CRepr()
crepr_64.width = 64
f.write(crepr_64.ec_constant(ec.G1_SECP256K1) + '\n')
# f.write(crepr_64.ec_constant(ec.G1_ECDSA_VERIFY) + '\n')
with open(root / 'ecdsa_constants.h', 'w') as f:
crepr_64 = CRepr()
crepr_64.width = 64
f.write(crepr_64.ecdsa_constant(ec.G1_SECP256K1) + '\n')
# f.write(crepr_64.ecdsa_constant(ec.G1_ECDSA_VERIFY) + '\n')
with open(root / 'fp_ops_cc_details.h', 'w') as f:
for limbs_per_lane in range(1, 17):
f.write(ccgen.gen(64, limbs_per_lane))
for limbs_per_lane in range(1, 33):
f.write(ccgen.gen(32, limbs_per_lane))
with open(root / 'ec_ops_add_details.h', 'w') as f:
f.write(ec_ops.EC_ADD.cucode() + '\n')
with open(root / 'ec_ops_add_details_with_reduce.h', 'w') as f:
f.write(ec_ops.EC_ADD.cucode_with_reduce() + '\n')
with open(root / 'ec_ops_dbl_details.h', 'w') as f:
f.write(ec_ops.EC_DBL.cucode() + '\n')
with open(root / 'ec_ops_dbl_details_with_reduce.h', 'w') as f:
f.write(ec_ops.EC_DBL.cucode_with_reduce() + '\n')
with open(root / 'ec_ops_dbl_1_details.h', 'w') as f:
f.write(ec_ops.EC_DBL_1.cucode() + '\n')
with open(root / 'ec_ops_dbl_1_details_with_reduce.h', 'w') as f:
f.write(ec_ops.EC_DBL_1.cucode_with_reduce() + '\n')
with open(root / 'ec_ops_dbl_2_details.h', 'w') as f:
f.write(ec_ops.EC_DBL_2.cucode() + '\n')
with open(root / 'ec_ops_dbl_2_details_with_reduce.h', 'w') as f:
f.write(ec_ops.EC_DBL_2.cucode_with_reduce() + '\n')
with open(root / 'ec_ops_mixed_add_details.h', 'w') as f:
f.write(ec_ops.EC_MIXED_ADD.cucode() + '\n')
with open(root / 'ec_ops_mixed_add_details_with_reduce.h', 'w') as f:
f.write(ec_ops.EC_MIXED_ADD.cucode_with_reduce() + '\n')
with open(root / 'ec_ops_affine_dbl_details.h', 'w') as f:
f.write(ec_ops.EC_AFF_DBL.cucode() + '\n')
with open(root / 'ec_ops_affine_dbl_details_with_reduce.h', 'w') as f:
f.write(ec_ops.EC_AFF_DBL.cucode_with_reduce() + '\n')
with open(root / 'affine_ops_dbl_details.h', 'w') as f:
f.write(ec_ops.AFF_DBL.cucode(0) + '\n')
with open(root / 'affine_ops_dbl_details_with_reduce.h', 'w') as f:
f.write(ec_ops.AFF_DBL.cucode_with_reduce(0) + '\n')
with open(root / 'affine_ops_add_details.h', 'w') as f:
f.write(ec_ops.AFF_ADD.cucode(0) + '\n')
with open(root / 'affine_ops_add_details_with_reduce.h', 'w') as f:
f.write(ec_ops.AFF_ADD.cucode_with_reduce(0) + '\n')
# tests
with open(root / 'fp_test_constants.h', 'w') as f:
generate_fp_test(f, field.Fq_SECP256K1.name, field.Fq_SECP256K1, 6, field.Fq_SECP256K1.width)
generate_fp_test(f, field.Fq_SECP256K1_n.name, field.Fq_SECP256K1_n, 6, field.Fq_SECP256K1_n.width)
with open(root / 'ecdsa_test_constants.h', 'w') as f:
generate_ecdsa_test(
f, field.Fq_SECP256K1_n, field.Fq_SECP256K1_n.width)
# generate_ecdsa_test(
# f, field.Fq_SECP256K1, ec.G1_SECP256K1, field.Fq_SECP256K1.width)