From d11f76c3beda3e669106270944367c7c7ed106f8 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Fri, 22 Sep 2023 12:51:12 +0100 Subject: [PATCH 1/3] feat: added test generator for vector commitment --- sage/testgen_ped_comm.sage | 238 +++++++++++++++++++++++++++++++++++ sage/testgen_scalar_mul.sage | 45 +------ sage/utils.sage | 74 +++++++++++ 3 files changed, 314 insertions(+), 43 deletions(-) create mode 100644 sage/testgen_ped_comm.sage create mode 100644 sage/utils.sage diff --git a/sage/testgen_ped_comm.sage b/sage/testgen_ped_comm.sage new file mode 100644 index 00000000..5d159abd --- /dev/null +++ b/sage/testgen_ped_comm.sage @@ -0,0 +1,238 @@ +#!/usr/bin/sage +# vim: syntax=python +# vim: set ts=2 sw=2 et: + +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +# ############################################################ +# +# Pedersen Commitment test generator +# +# ############################################################ + +# Imports +# --------------------------------------------------------- + +import os, json +import inspect, textwrap + +# Working directory +# --------------------------------------------------------- + +os.chdir(os.path.dirname(__file__)) + +# Sage imports +# --------------------------------------------------------- +# Accelerate arithmetic by accepting probabilistic proofs +from sage.structure.proof.all import arithmetic + +arithmetic(False) + +load("curves.sage") +load("utils.sage") + +# Generator +# --------------------------------------------------------- + +def gen_ped_comm_G1(curve_name, curve_config, count, seed, message_vector_len, scalarBits = None): + p = curve_config[curve_name]['field']['modulus'] + r = curve_config[curve_name]['field']['order'] + form = curve_config[curve_name]['curve']['form'] + a = curve_config[curve_name]['curve']['a'] + b = curve_config[curve_name]['curve']['b'] + + Fp = GF(p) + G1 = EllipticCurve(Fp, [0, b]) + cofactor = G1.order() // r + + out = { + 'curve': curve_name, + 'group': 'G1', + 'modulus': serialize_bigint(p), + 'order': serialize_bigint(r), + 'cofactor': serialize_bigint(cofactor), + 'form': form + } + if form == 'short_weierstrass': + out['a'] = serialize_bigint(a) + out['b'] = serialize_bigint(b) + + vectors = [] + set_random_seed(seed) + + for i in progressbar(range(count)): + v = {} + base_points = [G1.random_point() for _ in range(message_vector_len)] + # clearing cofactors + base_points = [i * cofactor for i in base_points] + r = 1 << scalarBits if scalarBits else r + messages = [randrange(r) for i in range(message_vector_len)] + scalar_muls = [ i * j for i, j in zip(messages, base_points)] + + commitment = 0 + for j in scalar_muls: + commitment =+ j + + v['id'] = i + v['base_points'] = [{f"G{i}" : serialize_EC_Fp(j)} for i, j in zip(range(message_vector_len), base_points)] + v['messages'] = [{f"a{i}" : serialize_bigint(j)} for i, j in zip(range(message_vector_len), messages)] + v['scalarBits'] = scalarBits if scalarBits else r.bit_length() + v['commitment'] = serialize_EC_Fp(commitment) + vectors.append(v) + + out['vectors'] = vectors + return out + +def gen_ped_comm_G2(curve_name, curve_config, count, seed, message_vector_len, scalarBits = None): + p = curve_config[curve_name]['field']['modulus'] + r = curve_config[curve_name]['field']['order'] + form = curve_config[curve_name]['curve']['form'] + a = curve_config[curve_name]['curve']['a'] + b = curve_config[curve_name]['curve']['b'] + embedding_degree = curve_config[curve_name]['tower']['embedding_degree'] + twist_degree = curve_config[curve_name]['tower']['twist_degree'] + twist = curve_config[curve_name]['tower']['twist'] + + G2_field_degree = embedding_degree // twist_degree + G2_field = f'Fp{G2_field_degree}' if G2_field_degree > 1 else 'Fp' + + if G2_field_degree == 2: + non_residue_fp = curve_config[curve_name]['tower']['QNR_Fp'] + elif G2_field_degree == 1: + if twist_degree == 6: + # Only for complete serialization + non_residue_fp = curve_config[curve_name]['tower']['SNR_Fp'] + else: + raise NotImplementedError() + else: + raise NotImplementedError() + + Fp = GF(p) + K. = PolynomialRing(Fp) + + if G2_field == 'Fp2': + Fp2. = Fp.extension(u^2 - non_residue_fp) + G2F = Fp2 + if twist_degree == 6: + non_residue_twist = curve_config[curve_name]['tower']['SNR_Fp2'] + else: + raise NotImplementedError() + elif G2_field == 'Fp': + G2F = Fp + if twist_degree == 6: + non_residue_twist = curve_config[curve_name]['tower']['SNR_Fp'] + else: + raise NotImplementedError() + else: + raise NotImplementedError() + + if twist == 'D_Twist': + G2 = EllipticCurve(G2F, [0, b/G2F(non_residue_twist)]) + elif twist == 'M_Twist': + G2 = EllipticCurve(G2F, [0, b*G2F(non_residue_twist)]) + else: + raise ValueError('G2 must be a D_Twist or M_Twist but found ' + twist) + + cofactor = G2.order() // r + + out = { + 'curve': curve_name, + 'group': 'G2', + 'modulus': serialize_bigint(p), + 'order': serialize_bigint(r), + 'cofactor': serialize_bigint(cofactor), + 'form': form, + 'twist_degree': int(twist_degree), + 'twist': twist, + 'non_residue_fp': int(non_residue_fp), + 'G2_field': G2_field, + 'non_residue_twist': [int(coord) for coord in non_residue_twist] if isinstance(non_residue_twist, list) else int(non_residue_twist) + } + if form == 'short_weierstrass': + out['a'] = serialize_bigint(a) + out['b'] = serialize_bigint(b) + + vectors = [] + set_random_seed(seed) + for i in progressbar(range(count)): + v = {} + base_points = [G2.random_point() for _ in range(message_vector_len)] + # clearing cofactors + base_points = [i * cofactor for i in base_points] + r = 1 << scalarBits if scalarBits else r + messages = [randrange(r) for i in range(message_vector_len)] + scalar_muls = [ i * j for i, j in zip(messages, base_points)] + + commitment = 0 + for j in scalar_muls: + commitment =+ j + + v['id'] = i + if G2_field == 'Fp2': + v['base_points'] = [{f"G{i}" : serialize_EC_Fp2(j)} for i, j in zip(range(message_vector_len), base_points)] + v['messages'] = [{f"a{i}" : serialize_bigint(j)} for i, j in zip(range(message_vector_len), messages)] + v['scalarBits'] = scalarBits if scalarBits else r.bit_length() + v['commitment'] = serialize_EC_Fp2(commitment) + elif G2_field == 'Fp': + v['base_points'] = [{f"G{i}" : serialize_EC_Fp(j)} for i, j in zip(range(message_vector_len), base_points)] + v['messages'] = [{f"a{i}" : serialize_bigint(j)} for i, j in zip(range(message_vector_len), messages)] + v['scalarBits'] = scalarBits if scalarBits else r.bit_length() + v['commitment'] = serialize_EC_Fp(commitment) + vectors.append(v) + + out['vectors'] = vectors + return out + +# CLI +# --------------------------------------------------------- + +if __name__ == "__main__": + # Usage + # BLS12-381 + # sage sage/testgen_ped_comm.sage BLS12_381 G1 {scalarBits: optional int} + + from argparse import ArgumentParser + + parser = ArgumentParser() + parser.add_argument("curve",nargs="+") + args = parser.parse_args() + + curve = args.curve[0] + group = args.curve[1] + scalarBits = None + if len(args.curve) > 2: + scalarBits = int(args.curve[2]) + + if curve not in Curves: + raise ValueError( + curve + + ' is not one of the available curves: ' + + str(Curves.keys()) + ) + elif group not in ['G1', 'G2']: + raise ValueError( + group + + ' is not a valid group, expected G1 or G2 instead' + ) + else: + bits = scalarBits if scalarBits else Curves[curve]['field']['order'].bit_length() + print(f'\nGenerating test vectors tv_{curve}_ped_comm_{group}_{bits}bit.json') + print('----------------------------------------------------\n') + + count = 40 + seed = 1337 + message_vector_len = 2 + + if group == 'G1': + out = gen_ped_comm_G1(curve, Curves, count, seed, message_vector_len, scalarBits) + elif group == 'G2': + out = gen_ped_comm_G2(curve, Curves, count, seed, message_vector_len, scalarBits) + + with open(f'tv_{curve}_ped_comm_{group}_{bits}bits.json', 'w') as f: + json.dump(out, f, indent=_sage_const_2 ) \ No newline at end of file diff --git a/sage/testgen_scalar_mul.sage b/sage/testgen_scalar_mul.sage index 0689bb83..51e0ef04 100644 --- a/sage/testgen_scalar_mul.sage +++ b/sage/testgen_scalar_mul.sage @@ -34,49 +34,7 @@ from sage.structure.proof.all import arithmetic arithmetic(False) load('curves.sage') - -# Utilities -# --------------------------------------------------------- - -def progressbar(it, prefix="", size=60, file=sys.stdout): - count = len(it) - def show(j): - x = int(size*j/count) - file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count)) - file.flush() - show(0) - for i, item in enumerate(it): - yield item - show(i+1) - file.write("\n") - file.flush() - -def serialize_bigint(x): - return '0x' + Integer(x).hex() - -def serialize_EC_Fp(P): - (Px, Py, Pz) = P - coords = { - 'x': serialize_bigint(Px), - 'y': serialize_bigint(Py) - } - return coords - -def serialize_EC_Fp2(P): - (Px, Py, Pz) = P - Px = vector(Px) - Py = vector(Py) - coords = { - 'x': { - 'c0': serialize_bigint(Px[0]), - 'c1': serialize_bigint(Px[1]) - }, - 'y': { - 'c0': serialize_bigint(Py[0]), - 'c1': serialize_bigint(Py[1]) - } - } - return coords +load('utils.sage') # Generator # --------------------------------------------------------- @@ -115,6 +73,7 @@ def genScalarMulG1(curve_name, curve_config, count, seed, scalarBits = None): Q = scalar * P v['id'] = i + print(i) v['P'] = serialize_EC_Fp(P) v['scalarBits'] = scalarBits if scalarBits else r.bit_length() v['scalar'] = serialize_bigint(scalar) diff --git a/sage/utils.sage b/sage/utils.sage new file mode 100644 index 00000000..20e3c44d --- /dev/null +++ b/sage/utils.sage @@ -0,0 +1,74 @@ +#!/usr/bin/sage +# vim: syntax=python +# vim: set ts=2 sw=2 et: + +# Constantine +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2020-Present Mamy André-Ratsimbazafy +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +# ############################################################ +# +# Utilities +# +# ############################################################ + +import inspect + +# Accelerate arithmetic by accepting probabilistic proofs +from sage.structure.proof.all import arithmetic +arithmetic(False) + +# Display Utilities +# --------------------------------------------------------- + +def progressbar(it, prefix="", size=60, file=sys.stdout): + count = len(it) + def show(j): + x = int(size*j/count) + file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count)) + file.flush() + show(0) + for i, item in enumerate(it): + yield item + show(i+1) + file.write("\n") + file.flush() + +# Conversion Utilities +# --------------------------------------------------------- + +def serialize_bigint(x): + return '0x' + Integer(x).hex() + +# Curve Utilities +# --------------------------------------------------------- + +def serialize_EC_Fp(P): + (Px, Py, Pz) = P + coords = { + 'x': serialize_bigint(Px), + 'y': serialize_bigint(Py) + } + return coords + +def serialize_EC_Fp2(P): + (Px, Py, Pz) = P + Px = vector(Px) + Py = vector(Py) + coords = { + 'x': { + 'c0': serialize_bigint(Px[0]), + 'c1': serialize_bigint(Px[1]) + }, + 'y': { + 'c0': serialize_bigint(Py[0]), + 'c1': serialize_bigint(Py[1]) + } + } + return coords + + From 9e10c6adb8da0130deb284d22aa5f64bf6bf2d05 Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Fri, 22 Sep 2023 12:56:40 +0100 Subject: [PATCH 2/3] feat: updated message vector length --- sage/testgen_ped_comm.sage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sage/testgen_ped_comm.sage b/sage/testgen_ped_comm.sage index 5d159abd..fc7b2a74 100644 --- a/sage/testgen_ped_comm.sage +++ b/sage/testgen_ped_comm.sage @@ -227,7 +227,7 @@ if __name__ == "__main__": count = 40 seed = 1337 - message_vector_len = 2 + message_vector_len = 100 if group == 'G1': out = gen_ped_comm_G1(curve, Curves, count, seed, message_vector_len, scalarBits) From 30703aa069a4218be841a2856c3bb3d97ff58bab Mon Sep 17 00:00:00 2001 From: Godspower Eze Date: Wed, 4 Oct 2023 22:56:16 +0100 Subject: [PATCH 3/3] feat: added banderwagon and bandersnatch --- sage/curves.sage | 22 ++++++++++++++++++++++ sage/testgen_ped_comm.sage | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/sage/curves.sage b/sage/curves.sage index 70ca5add..cccfe94d 100644 --- a/sage/curves.sage +++ b/sage/curves.sage @@ -174,5 +174,27 @@ Curves = { 'a': 0, 'b': 5 } + }, + 'Banderwagon' : { + 'field': { + 'modulus': Integer('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'), + 'order' : Integer('0x1cfb69d4ca675f520cce760202687600ff8f87007419047174fd06b52876e7e1') + }, + 'curve' : { + 'form': 'short_weierstrass', + 'a': −3763200000, + 'b': -7867596800000 + } + }, + 'Bandersnatch' : { + 'field': { + 'modulus': Integer('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'), + 'order' : Integer('0x1cfb69d4ca675f520cce760202687600ff8f87007419047174fd06b52876e7e1') + }, + 'curve' : { + 'form': 'short_weierstrass', + 'a': −3763200000, + 'b': -7867596800000 + } } } diff --git a/sage/testgen_ped_comm.sage b/sage/testgen_ped_comm.sage index fc7b2a74..a4b461f2 100644 --- a/sage/testgen_ped_comm.sage +++ b/sage/testgen_ped_comm.sage @@ -12,7 +12,7 @@ # ############################################################ # -# Pedersen Commitment test generator +# Pedersen Commitment + Inner Product Argument Test Generator # # ############################################################