diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index df67778c..006892ff 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -81,6 +81,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10 with: sarif_file: results.sarif diff --git a/README.md b/README.md index eedb0e95..477d0482 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Supported platforms: - [base](yacl/base/): some basic types and utils in yacl. - [crypto](yacl/crypto/): **crypto algorithms** without [link](yacl/link/). -- [kernels](yacl/kernels/): **crypto kernels** that includes [link](yacl/link/) with multi-thread support, i.e. OT, DPF. +- [kernel](yacl/kernel/): **crypto kernel** that includes [link](yacl/link/) with multi-thread support, i.e. OT, DPF. - [io](yacl/io/): a simple streaming-based io library. - [link](yacl/link/): a simple rpc-based MPI framework, providing the [SPMD](https://en.wikipedia.org/wiki/SPMD) parallel programming capability. diff --git a/bazel/FourQlib.BUILD b/bazel/FourQlib.BUILD new file mode 100644 index 00000000..18e7f161 --- /dev/null +++ b/bazel/FourQlib.BUILD @@ -0,0 +1,51 @@ +# Copyright 2024 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@rules_foreign_cc//foreign_cc:defs.bzl", "make") + +filegroup( + name = "all_srcs", + srcs = glob(["**"]), +) + +config_setting( + name = "linux_x64", + constraint_values = [ + "@platforms//os:linux", + "@platforms//cpu:x86_64", + ], +) + +config_setting( + name = "linux_arm64", + constraint_values = [ + "@platforms//os:linux", + "@platforms//cpu:aarch64", + ], +) + +make( + name = "FourQlib", + args = ["-C FourQ_64bit_and_portable"], + env = select({ + ":linux_x64": {"ARCH": "x64", "AVX": "TRUE", "AVX2": "FALSE"}, + ":linux_arm64": {"ARCH": "ARM64"}, + "@platforms//os:macos": {"ARCH": "x64", "GENERIC": "TRUE"}, # still work on macos M1 + }), + defines = ["__LINUX__", "_ARM64_"], # still work on macos and x64 + lib_source = ":all_srcs", + out_static_libs = ["libFourQ.a"], + targets = ["libFourQ", "install"], + visibility = ["//visibility:public"], +) diff --git a/bazel/lib25519.BUILD b/bazel/lib25519.BUILD new file mode 100644 index 00000000..2d3adabd --- /dev/null +++ b/bazel/lib25519.BUILD @@ -0,0 +1,294 @@ +# Copyright 2024 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@rules_cc//cc:defs.bzl", "cc_library") + +genrule( + name = "crypto_uint64_h", + srcs = ["inttypes/crypto_uintN.h"], + outs = ["include-build/crypto_uint64.h"], + cmd = "sed -e 's/N/64/g' $(<) > $(@)", +) + +genrule( + name = "crypto_verify_c", + srcs = ["crypto_verify/32/ref/verify.c"], + outs = ["crypto_verify.c"], + cmd = "cat $(<) > $(@)", +) + +genrule( + name = "crypto_verify_h", + outs = ["include-build/crypto_verify.h"], + cmd = """ +cat > $@ << EOF +#ifndef crypto_verify_h +#define crypto_verify_h + +#define crypto_verify CRYPTO_NAMESPACE(verify) + +#define crypto_verify_32_BYTES 32 +#define crypto_verify_BYTES 32 + +extern int crypto_verify(const unsigned char *,const unsigned char *); + +#endif + +EOF""", +) + +genrule( + name = "ge25519_unpack_c", + srcs = ["crypto_multiscalar/ed25519/amd64-maax-p3/ge25519_unpack.c"], + outs = ["ge25519_unpack.c"], + cmd = "sed -e 's/crypto_verify_32/crypto_verify/g' $(<) > $(@)", +) + +genrule( + name = "ge25519_sub_h", + outs = ["include-build/ge25519_sub.h"], + cmd = """ +cat > $@ << EOF +#ifndef ge25519_sub_h +#define ge25519_sub_h + +#include "ge25519.h" + +#define ge25519_sub CRYPTO_NAMESPACE(ge25519_sub) + +extern void ge25519_sub(ge25519 *r, const ge25519 *p, const ge25519 *q); + +#endif + +EOF""", +) + +genrule( + name = "ge25519_sub_c", + outs = ["ge25519_sub.c"], + cmd = """ +cat > $@ << EOF +#include "ge25519_sub.h" + +void ge25519_sub(ge25519 *r, const ge25519 *p, const ge25519 *q) +{ + ge25519_p3 qneg; + fe25519_neg(&qneg.x,&q->x); + fe25519_neg(&qneg.t,&q->t); + qneg.y = q->y; + qneg.z = q->z; + ge25519_add(r,p,&qneg); +} + +EOF""", +) + +genrule( + name = "ge25519_scalarmult_h", + outs = ["include-build/ge25519_scalarmult.h"], + cmd = """ +cat > $@ << EOF +#ifndef ge25519_scalarmult_h +#define ge25519_scalarmult_h + +#include "ge25519.h" + +#define ge25519_scalarmult CRYPTO_NAMESPACE(ge25519_scalarmult) + +extern void ge25519_scalarmult(ge25519 *r, const ge25519 *p, const sc25519 *s); + +#endif + +EOF""", +) + +genrule( + name = "ge25519_scalarmult_c", + outs = ["ge25519_scalarmult.c"], + cmd = """ +cat > $@ << EOF +#include "ge25519_scalarmult.h" +#include "ge25519_sub.h" + +// warning: these constants are not encapsulated +#define P_WINDOWSIZE 5 +#define P_MULTIPLES (1<<(P_WINDOWSIZE-2)) +static void ge25519_p3_0(ge25519_p3 *r) +{ + fe25519_setint(&r->x,0); + fe25519_setint(&r->y,1); + fe25519_setint(&r->z,1); + fe25519_setint(&r->t,0); +} +static void ge25519_multi_scalarmult_precompute(ge25519_p3 *cP, const ge25519_p3 *P, unsigned long long multiples) +{ + __attribute__ ((aligned(32))) ge25519_p3 twoP; + ge25519_double(&twoP,P); + cP[0] = *P; + for (long long i = 0;i < multiples-1;++i) + ge25519_add(&cP[i+1],&twoP,&cP[i]); +} +static void ge25519_multi_scalarmult_process(ge25519_p3 *r, const signed char nslide[256], const ge25519_p3 cP[P_MULTIPLES]) +{ + int maybenonzero = 0; + ge25519_p3_0(r); + for (long long i = 255;i >= 0;--i) { + if (maybenonzero) + ge25519_double(r,r); + signed char c = nslide[i]; + if (c != 0) { + maybenonzero = 1; + if (c > 0) + ge25519_add(r,r,&cP[c/2]); + else + ge25519_sub(r,r,&cP[-c/2]); + } + } +} +void ge25519_scalarmult(ge25519 *r, const ge25519 *p, const sc25519 *s) { + signed char nslide[256]; + ge25519_p3 cP[P_MULTIPLES]; /* P,3P,5P,7P,9P,11P,13P,15P */ + sc25519_slide(nslide,s,P_WINDOWSIZE); + ge25519_multi_scalarmult_precompute(cP,p,P_MULTIPLES); + ge25519_multi_scalarmult_process(r,nslide,cP); +} + +EOF""", +) + +genrule( + name = "ge25519_is_on_curve_h", + outs = ["include-build/ge25519_is_on_curve.h"], + cmd = """ +cat > $@ << EOF +#ifndef ge25519_is_on_curve_h +#define ge25519_is_on_curve_h + +#include "ge25519.h" + +#define ge25519_is_on_curve CRYPTO_NAMESPACE(ge25519_is_on_curve) + +extern int ge25519_is_on_curve(const ge25519 *p); + +#endif + +EOF""", +) + +genrule( + name = "ge25519_is_on_curve_c", + outs = ["ge25519_is_on_curve.c"], + cmd = """ +cat > $@ << EOF +#include "ge25519_is_on_curve.h" + +/* d */ +static const fe25519 ecd = {{0x75EB4DCA135978A3, 0x00700A4D4141D8AB, 0x8CC740797779E898, 0x52036CEE2B6FFE73}}; + +static const fe25519 zero = {{0,0,0,0}}; + +int ge25519_is_on_curve(const ge25519_p3 *p) +{ + fe25519 x2; + fe25519 y2; + fe25519 z2; + fe25519 z4; + fe25519 t0; + fe25519 t1; + + fe25519_square(&x2, &p->x); + fe25519_square(&y2, &p->y); + fe25519_square(&z2, &p->z); + fe25519_sub(&t0, &y2, &x2); + fe25519_mul(&t0, &t0, &z2); + + fe25519_mul(&t1, &x2, &y2); + fe25519_mul(&t1, &t1, &ecd); + fe25519_square(&z4, &z2); + fe25519_add(&t1, &t1, &z4); + fe25519_sub(&t0, &t0, &t1); + + return fe25519_iseq_vartime(&t0, &zero) != 0; +} + +EOF""", +) + +cc_library( + name = "25519", + srcs = [ + "crypto_mGnP/ed25519/amd64-maax/ge25519_pack.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_add.S", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_freeze.S", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_getparity.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_iseq.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_mul.S", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_neg.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_pack.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_pow2523.c", # referenced by ge25519_unpack + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_setint.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_sub.S", + "crypto_multiscalar/ed25519/amd64-maax-p3/fe25519_unpack.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/ge25519_add.S", + "crypto_multiscalar/ed25519/amd64-maax-p3/ge25519_double.S", + "crypto_multiscalar/ed25519/amd64-maax-p3/sc25519_from32bytes.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/sc25519_slide.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/sc25519_to32bytes.c", + "crypto_multiscalar/ed25519/amd64-maax-p3/shared-consts.c", + "crypto_nG/merged25519/amd64-maax/fe25519_cmov.c", + "crypto_nG/merged25519/amd64-maax/ge25519_base.S", + "crypto_nG/merged25519/amd64-maax/ge25519_scalarmult_base.c", + "crypto_nG/merged25519/amd64-maax/sc25519_window4.c", + "crypto_nG/merged25519/amd64-maax/shared-base-data.c", + "crypto_pow/inv25519/amd64-maax/fe25519_invert.c", + "crypto_pow/inv25519/amd64-maax/fe25519_nsquare.S", + "crypto_pow/inv25519/amd64-maax/fe25519_square.S", + "crypto_verify.c", + "ge25519_is_on_curve.c", + "ge25519_scalarmult.c", + "ge25519_sub.c", + "ge25519_unpack.c", + "include-build/crypto_asm_hidden.h", + "include-build/crypto_uint64.h", + "include-build/crypto_verify.h", + ], + hdrs = [ + "crypto_multiscalar/ed25519/amd64-maax-p3/ge25519_unpack.h", + "crypto_multiscalar/ed25519/amd64-maax-p3/sc25519.h", + "crypto_nG/merged25519/amd64-maax/fe25519.h", + "crypto_nG/merged25519/amd64-maax/ge25519.h", + "crypto_nG/merged25519/amd64-maax/ge25519_base_niels.data", + "include-build/ge25519_is_on_curve.h", + "include-build/ge25519_scalarmult.h", + "include-build/ge25519_sub.h", + ], + copts = ["-fvisibility=hidden"], + defines = [ + "CRYPTO_NAMESPACE(name)=crypto_##name", + "_CRYPTO_NAMESPACE(name)=_crypto_##name", + "CRYPTO_SHARED_NAMESPACE(name)=crypto_shared_##name", + "_CRYPTO_SHARED_NAMESPACE(name)=_crypto_shared_##name", + ], + includes = [ + "crypto_multiscalar/ed25519/amd64-maax-p3", + "crypto_nG/merged25519/amd64-maax", + "include-build", + ], + linkstatic = True, + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + ], + visibility = ["//visibility:public"], +) diff --git a/bazel/mcl.BUILD b/bazel/mcl.BUILD index 614023d3..03b222a2 100644 --- a/bazel/mcl.BUILD +++ b/bazel/mcl.BUILD @@ -13,6 +13,8 @@ # limitations under the License. load("@yacl//bazel:yacl.bzl", "yacl_cmake_external") +load("@rules_foreign_cc//foreign_cc:defs.bzl", "make") +load("@bazel_skylib//lib:selects.bzl", "selects") package(default_visibility = ["//visibility:public"]) @@ -28,6 +30,14 @@ config_setting( visibility = ["//visibility:private"], ) +selects.config_setting_group( + name = "mac_x86", + match_all = [ + "@platforms//os:macos", + "@platforms//cpu:x86_64", + ], +) + default_config = { "MCL_BUILD_TESTING": "OFF", # remove dependency on libgmp @@ -46,8 +56,10 @@ android_config = { "CMAKE_ANDROID_ARCH_ABI": "arm64-v8a", } +# bad for mac intel +# https://github.com/herumi/mcl/issues/174 yacl_cmake_external( - name = "mcl", + name = "mcl-cmake", build_args = ["-j"], cache_entries = select({ ":cpu_arm64_v8a": android_config, @@ -60,3 +72,34 @@ yacl_cmake_external( ], alwayslink = True, ) + +make( + name = "mcl-make", + args = [ + "-j", + "MCL_USE_GMP=0", + "DEBUG=0", + ], + env = select({ + "@platforms//os:macos": { + "AR": "ar", + }, + "//conditions:default": { + }, + }), + lib_source = ":source", + out_static_libs = [ + "libmcl.a", + ], + targets = [ + "install", + ], +) + +cc_library( + name = "mcl", + deps = select({ + ":mac_x86": [":mcl-make"], + "//conditions:default": [":mcl-cmake"], + }), +) diff --git a/bazel/openssl.BUILD b/bazel/openssl.BUILD index 15210084..37442510 100644 --- a/bazel/openssl.BUILD +++ b/bazel/openssl.BUILD @@ -59,7 +59,6 @@ yacl_configure_make( }), lib_name = "openssl", lib_source = ":all_srcs", - linkopts = ["-ldl"], # Note that for Linux builds, libssl must come before libcrypto on the linker command-line. # As such, libssl must be listed before libcrypto out_static_libs = [ diff --git a/bazel/patches/FourQlib.patch b/bazel/patches/FourQlib.patch new file mode 100644 index 00000000..cf721b69 --- /dev/null +++ b/bazel/patches/FourQlib.patch @@ -0,0 +1,126 @@ +diff --git a/FourQ_64bit_and_portable/FourQ_internal.h b/FourQ_64bit_and_portable/FourQ_internal.h +index 30d4387..5104320 100644 +--- a/FourQ_64bit_and_portable/FourQ_internal.h ++++ b/FourQ_64bit_and_portable/FourQ_internal.h +@@ -128,15 +128,15 @@ static __inline unsigned int is_digit_lessthan_ct(digit_t x, digit_t y) + + // 64x64-bit multiplication + #define MUL128(multiplier, multiplicand, product) \ +- mp_mul((digit_t*)&(multiplier), (digit_t*)&(multiplicand), (digit_t*)&(product), NWORDS_FIELD/2); ++ FourQlib_mp_mul((digit_t*)&(multiplier), (digit_t*)&(multiplicand), (digit_t*)&(product), NWORDS_FIELD/2); + + // 128-bit addition, inputs < 2^127 + #define ADD128(addend1, addend2, addition) \ +- mp_add((digit_t*)(addend1), (digit_t*)(addend2), (digit_t*)(addition), NWORDS_FIELD); ++ FourQlib_mp_add((digit_t*)(addend1), (digit_t*)(addend2), (digit_t*)(addition), NWORDS_FIELD); + + // 128-bit addition with output carry + #define ADC128(addend1, addend2, carry, addition) \ +- (carry) = mp_add((digit_t*)(addend1), (digit_t*)(addend2), (digit_t*)(addition), NWORDS_FIELD); ++ (carry) = FourQlib_mp_add((digit_t*)(addend1), (digit_t*)(addend2), (digit_t*)(addition), NWORDS_FIELD); + + #elif (TARGET == TARGET_AMD64 && OS_TARGET == OS_WIN) + +@@ -228,10 +228,10 @@ static __inline unsigned int is_digit_lessthan_ct(digit_t x, digit_t y) + bool is_zero_ct(digit_t* a, unsigned int nwords); + + // Multiprecision addition, c = a+b. Returns the carry bit +-unsigned int mp_add(digit_t* a, digit_t* b, digit_t* c, unsigned int nwords); ++unsigned int FourQlib_mp_add(digit_t* a, digit_t* b, digit_t* c, unsigned int nwords); + + // Schoolbook multiprecision multiply, c = a*b +-void mp_mul(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords); ++void FourQlib_mp_mul(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords); + + // Multiprecision subtraction, c = a-b. Returns the borrow bit + #if defined (GENERIC_IMPLEMENTATION) +diff --git a/FourQ_64bit_and_portable/generic/fp.h b/FourQ_64bit_and_portable/generic/fp.h +index 3083c06..e51997d 100644 +--- a/FourQ_64bit_and_portable/generic/fp.h ++++ b/FourQ_64bit_and_portable/generic/fp.h +@@ -183,7 +183,7 @@ void mod1271(felm_t a) + } + + +-void mp_mul(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords) ++void FourQlib_mp_mul(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords) + { // Schoolbook multiprecision multiply, c = a*b + unsigned int i, j; + digit_t u, v, UV[2]; +@@ -206,7 +206,7 @@ void mp_mul(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int n + } + + +-unsigned int mp_add(digit_t* a, digit_t* b, digit_t* c, unsigned int nwords) ++unsigned int FourQlib_mp_add(digit_t* a, digit_t* b, digit_t* c, unsigned int nwords) + { // Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit + unsigned int i, carry = 0; + +@@ -270,14 +270,14 @@ void fpinv1271(felm_t a) + static __inline void multiply(const digit_t* a, const digit_t* b, digit_t* c) + { // Schoolbook multiprecision multiply, c = a*b + +- mp_mul(a, b, c, NWORDS_ORDER); ++ FourQlib_mp_mul(a, b, c, NWORDS_ORDER); + } + + + static __inline unsigned int add(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords) + { // Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit + +- return mp_add((digit_t*)a, (digit_t*)b, c, (unsigned int)nwords); ++ return FourQlib_mp_add((digit_t*)a, (digit_t*)b, c, (unsigned int)nwords); + } + + +diff --git a/FourQ_64bit_and_portable/makefile b/FourQ_64bit_and_portable/makefile +index 7b6fd07..c35c47d 100644 +--- a/FourQ_64bit_and_portable/makefile ++++ b/FourQ_64bit_and_portable/makefile +@@ -92,9 +92,13 @@ ifeq "$(SERIAL_PUSH)" "TRUE" + endif + + SHARED_LIB_TARGET=libFourQ.so ++STATIC_LIB_TARGET=libFourQ.a + ifeq "$(SHARED_LIB)" "TRUE" + DO_MAKE_SHARED_LIB=-fPIC + SHARED_LIB_O=$(SHARED_LIB_TARGET) ++else ++ DO_MAKE_SHARED_LIB=-fPIC ++ STATIC_LIB_O=$(STATIC_LIB_TARGET) + endif + + cc=$(COMPILER) +@@ -116,8 +120,11 @@ OBJECTS_ALL=$(OBJECTS) $(OBJECTS_FP_TEST) $(OBJECTS_ECC_TEST) $(OBJECTS_CRYPTO_T + all: crypto_test ecc_test fp_test $(SHARED_LIB_O) + + ifeq "$(SHARED_LIB)" "TRUE" +- $(SHARED_LIB_O): $(OBJECTS) ++ libFourQ: $(OBJECTS) + $(CC) -shared -o $(SHARED_LIB_O) $(OBJECTS) ++else ++ libFourQ: $(OBJECTS) ++ ar rcs $(STATIC_LIB_O) $(OBJECTS) + endif + + crypto_test: $(OBJECTS_CRYPTO_TEST) +@@ -186,3 +193,6 @@ fp_tests.o: tests/fp_tests.c + clean: + rm -rf $(SHARED_LIB_TARGET) crypto_test ecc_test fp_test *.o AMD64/consts.s + ++install: ++ cp $(STATIC_LIB_O) $(SHARED_LIB_O) $(PREFIX)/lib ++ cp FourQ.h FourQ_api.h FourQ_internal.h $(PREFIX)/include +diff --git a/FourQ_64bit_and_portable/schnorrq.c b/FourQ_64bit_and_portable/schnorrq.c +index da89f86..099f4eb 100644 +--- a/FourQ_64bit_and_portable/schnorrq.c ++++ b/FourQ_64bit_and_portable/schnorrq.c +@@ -14,7 +14,7 @@ + #include "FourQ_params.h" + #include "../random/random.h" + #include "../sha512/sha512.h" +-#include ++#include + #include + + diff --git a/bazel/patches/mcl.patch b/bazel/patches/mcl.patch index 4647481c..bc9d6712 100644 --- a/bazel/patches/mcl.patch +++ b/bazel/patches/mcl.patch @@ -43,3 +43,17 @@ index 2b54b261..5c1f14c7 100644 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) add_custom_target(gen_base.o SOURCES ${BASE_OBJ}) +diff --git a/Makefile b/Makefile +index a60dbf59..0d27036b 100644 +--- a/Makefile ++++ b/Makefile +@@ -3,7 +3,8 @@ LIB_DIR?=lib + OBJ_DIR?=obj + EXE_DIR?=bin + MCL_SIZEOF_UNIT?=$(shell expr $(BIT) / 8) +-CLANG?=clang++$(LLVM_VER) ++# CLANG?=clang++$(LLVM_VER) ++CLANG=$(CXX) + SRC_SRC=fp.cpp bn_c256.cpp bn_c384.cpp bn_c384_256.cpp bn_c512.cpp she_c256.cpp + TEST_SRC=fp_test.cpp ec_test.cpp fp_util_test.cpp window_method_test.cpp elgamal_test.cpp fp_tower_test.cpp gmp_test.cpp bn_test.cpp bn384_test.cpp glv_test.cpp paillier_test.cpp she_test.cpp vint_test.cpp bn512_test.cpp conversion_test.cpp + TEST_SRC+=bn_c256_test.cpp bn_c384_test.cpp bn_c384_256_test.cpp bn_c512_test.cpp diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index f2adb6d0..6d6e8640 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -40,6 +40,8 @@ def yacl_deps(): _com_github_libsodium() _com_github_libtom_libtommath() _com_github_herumi_mcl() + _com_github_microsoft_FourQlib() + _lib25519() _simplest_ot() _org_interconnection() @@ -286,6 +288,23 @@ def _com_github_libsodium(): ], ) +def _com_github_microsoft_FourQlib(): + maybe( + http_archive, + name = "com_github_microsoft_FourQlib", + type = "tar.gz", + strip_prefix = "FourQlib-1031567f23278e1135b35cc04e5d74c2ac88c029", + sha256 = "7417c829d7933facda568c7a08924dfefb0c83dd1dab411e597af4c0cc0417f0", + patch_args = ["-p1"], + patches = [ + "@yacl//bazel:patches/FourQlib.patch", + ], + build_file = "@yacl//bazel:FourQlib.BUILD", + urls = [ + "https://github.com/microsoft/FourQlib/archive/1031567f23278e1135b35cc04e5d74c2ac88c029.tar.gz", + ], + ) + def _com_github_google_cpu_features(): maybe( http_archive, @@ -373,3 +392,16 @@ def _com_github_herumi_mcl(): ], urls = ["https://github.com/herumi/mcl/archive/refs/tags/v1.88.tar.gz"], ) + +def _lib25519(): + maybe( + http_archive, + name = "lib25519", + strip_prefix = "lib25519-20240321", + sha256 = "d010baea719153fe3f012789b5a1de27d91fbbcfc65559e7eee5d802bf91eadd", + type = "tar.gz", + build_file = "@yacl//bazel:lib25519.BUILD", + urls = [ + "https://lib25519.cr.yp.to/lib25519-20240321.tar.gz", + ], + ) diff --git a/examples/psu/BUILD.bazel b/examples/psu/BUILD.bazel index cab47525..64954c26 100644 --- a/examples/psu/BUILD.bazel +++ b/examples/psu/BUILD.bazel @@ -30,9 +30,9 @@ yacl_cc_library( "//yacl/base:int128", "//yacl/crypto/hash:hash_utils", "//yacl/crypto/rand", - "//yacl/kernels/algorithms:base_ot", - "//yacl/kernels/algorithms:iknp_ote", - "//yacl/kernels/algorithms:kkrt_ote", + "//yacl/kernel/algorithms:base_ot", + "//yacl/kernel/algorithms:kkrt_ote", + "//yacl/kernel/algorithms:softspoken_ote", "//yacl/link", "//yacl/math/f2k", "@com_google_absl//absl/types:span", diff --git a/examples/psu/krtw19_psu.cc b/examples/psu/krtw19_psu.cc index 6ae2873c..42063602 100644 --- a/examples/psu/krtw19_psu.cc +++ b/examples/psu/krtw19_psu.cc @@ -15,10 +15,9 @@ #include "examples/psu/krtw19_psu.h" #include -#include +#include #include -#include -#include +#include #include "yacl/utils/serialize.h" @@ -29,23 +28,22 @@ namespace { // reference: https://eprint.iacr.org/2019/1234.pdf (Figure 2) constexpr float kZeta{0.06f}; constexpr size_t kBinSize{64ul}; // m+1 -constexpr uint128_t kBot{}; +constexpr uint128_t kBot{0}; constexpr size_t kNumBinsPerBatch{16ul}; constexpr size_t kBatchSize{kNumBinsPerBatch * kBinSize}; -constexpr size_t kNumBaseOT{128ul}; constexpr size_t kNumInkpOT{512ul}; static auto HashToSizeT = [](const uint128_t& x) { - auto hash = yacl::crypto::Blake3_128({&x, sizeof x}); + auto hash = yacl::crypto::Blake3_128({&x, sizeof(x)}); size_t ret; - std::memcpy(&ret, &hash, sizeof ret); + std::memcpy(&ret, &hash, sizeof(ret)); return ret; }; auto HashInputs(const std::vector& elem_hashes, size_t count) { size_t num_bins = std::ceil(count * kZeta); std::vector> hashing(num_bins); - for (auto elem : elem_hashes) { + for (const auto& elem : elem_hashes) { auto hash = HashToSizeT(elem); hashing[hash % num_bins].emplace_back(elem); } @@ -53,33 +51,33 @@ auto HashInputs(const std::vector& elem_hashes, size_t count) { } uint64_t Evaluate(const std::vector& coeffs, uint64_t x) { - uint64_t y{coeffs.back()}; + uint64_t y = coeffs.back(); for (auto it = std::next(coeffs.rbegin()); it != coeffs.rend(); ++it) { y = yacl::GfMul64(y, x) ^ *it; } return y; } -auto Interpolate(const std::vector& xs, - const std::vector& ys) { +std::vector Interpolate(const std::vector& xs, + const std::vector& ys) { YACL_ENFORCE_EQ(xs.size(), ys.size(), "Sizes mismatch."); size_t size{xs.size()}; std::vector L_coeffs(size); - for (size_t i{}; i != size; ++i) { + for (size_t i = 0; i != size; ++i) { std::vector Li_coeffs(size); Li_coeffs[0] = ys[i]; - uint64_t prod{1}; - for (size_t j{}; j != size; ++j) { + uint64_t prod = 1; + for (size_t j = 0; j != size; ++j) { if (xs[i] != xs[j]) { prod = yacl::GfMul64(prod, xs[i] ^ xs[j]); - uint64_t sum{}; - for (size_t k{}; k != size; ++k) { + uint64_t sum = 0; + for (size_t k = 0; k != size; ++k) { sum = std::exchange(Li_coeffs[k], yacl::GfMul64(Li_coeffs[k], xs[j]) ^ sum); } } } - for (size_t k{}; k != size; ++k) { + for (size_t k = 0; k != size; ++k) { L_coeffs[k] ^= yacl::GfMul64(Li_coeffs[k], yacl::GfInv64(prod)); } } @@ -103,50 +101,61 @@ void KrtwPsuSend(const std::shared_ptr& ctx, // Step 2. Prepares OPRF yacl::crypto::KkrtOtExtReceiver receiver; - size_t num_ot{hashing.size() * kBinSize}; - auto choice = yacl::crypto::RandBits(kNumBaseOT); - auto base_ot = yacl::crypto::BaseOtRecv(ctx, choice, kNumBaseOT); - auto store = yacl::crypto::IknpOtExtSend(ctx, base_ot, kNumInkpOT); + const size_t num_ot = hashing.size() * kBinSize; + auto ss_sender = yacl::crypto::SoftspokenOtExtSender(); + auto store = ss_sender.GenRot(ctx, kNumInkpOT); + receiver.Init(ctx, store, num_ot); receiver.SetBatchSize(kBatchSize); std::vector elems; elems.reserve(num_ot); - size_t oprf_idx{}; - for (size_t bin_idx{}; bin_idx != hashing.size(); ++bin_idx) { - if (bin_idx % kNumBinsPerBatch == 0) { - receiver.SendCorrection( - ctx, std::min(kBatchSize, (hashing.size() - bin_idx) * kBinSize)); - } + size_t oprf_idx = 0; + for (size_t bin_idx = 0; bin_idx != hashing.size(); ++bin_idx) { hashing[bin_idx].resize(kBinSize); std::sort(hashing[bin_idx].begin(), hashing[bin_idx].end()); + std::vector evals(kBinSize); + + // Encode inputs before SendCorrection + // More details could be found in `yacl/kernel/algorithms/kkrt_ote_test.cc` + std::transform(hashing[bin_idx].cbegin(), hashing[bin_idx].cend(), + evals.begin(), [&](uint128_t input) { + uint64_t result; + receiver.Encode( + oprf_idx, HashToSizeT(input), + {reinterpret_cast(&result), sizeof(result)}); + oprf_idx++; + return result; + }); + receiver.SendCorrection(ctx, kBinSize); + // Step 3. For each bin element, invokes PSU(1, m+1) - for (auto elem : hashing[bin_idx]) { + for (size_t i = 0; i < hashing[bin_idx].size(); ++i) { + auto elem = hashing[bin_idx][i]; elems.emplace_back(elem); - uint64_t eval; - receiver.Encode(oprf_idx++, elem, - {reinterpret_cast(&eval), sizeof eval}); + uint64_t eval = evals[i]; std::vector coeffs(kBinSize); auto buf = ctx->Recv(ctx->PrevRank(), "Receive coefficients"); + + YACL_ENFORCE(buf.size() == kBinSize * sizeof(uint64_t)); std::memcpy(coeffs.data(), buf.data(), buf.size()); + auto y = Evaluate(coeffs, HashToSizeT(elem)) ^ eval; - ctx->SendAsync(ctx->NextRank(), yacl::SerializeUint128(y), + ctx->SendAsync(ctx->NextRank(), + yacl::SerializeUint128(yacl::MakeUint128(0, y)), "Send evaluation"); } } // Step 4. Sends new elements through OT - std::vector> keys(num_ot); - choice = yacl::crypto::SecureRandBits(kNumBaseOT); - base_ot = yacl::crypto::BaseOtRecv(ctx, choice, kNumBaseOT); - yacl::crypto::IknpOtExtSend(ctx, base_ot, absl::MakeSpan(keys)); + auto keys = ss_sender.GenRot(ctx, num_ot); std::vector ciphers(num_ot); - for (size_t i{}; i != num_ot; ++i) { - ciphers[i] = elems[i] ^ keys[i][0]; + for (size_t i = 0; i != num_ot; ++i) { + ciphers[i] = elems[i] ^ keys.GetBlock(i, 0); } ctx->SendAsync(ctx->NextRank(), - yacl::Buffer{reinterpret_cast(ciphers.data()), - ciphers.size() * sizeof(uint128_t)}, + yacl::ByteContainerView(ciphers.data(), + ciphers.size() * sizeof(uint128_t)), "Send ciphertexts"); } @@ -165,55 +174,58 @@ std::vector KrtwPsuRecv( auto hashing = HashInputs(elem_hashes, count); // Step 2. Prepares OPRF + const size_t num_ot = hashing.size() * kBinSize; + auto ss_receiver = yacl::crypto::SoftspokenOtExtReceiver(); + auto store = ss_receiver.GenRot(ctx, kNumInkpOT); + yacl::crypto::KkrtOtExtSender sender; - size_t num_ot{hashing.size() * kBinSize}; - auto base_ot = yacl::crypto::BaseOtSend(ctx, kNumBaseOT); - auto choice = yacl::crypto::RandBits(kNumInkpOT); - auto store = yacl::crypto::IknpOtExtRecv(ctx, base_ot, choice, kNumInkpOT); sender.Init(ctx, store, num_ot); sender.SetBatchSize(kBatchSize); auto oprf = sender.GetOprf(); - yacl::dynamic_bitset<> ot_choice(num_ot); - size_t oprf_idx{}; + yacl::dynamic_bitset ot_choice(num_ot); + size_t oprf_idx = 0; // Step 3. For each bin, invokes PSU(1, m+1) - for (size_t bin_idx{}; bin_idx != hashing.size(); ++bin_idx) { - if (bin_idx % kNumBinsPerBatch == 0) { - sender.RecvCorrection( - ctx, std::min(kBatchSize, (hashing.size() - bin_idx) * kBinSize)); - } + for (size_t bin_idx = 0; bin_idx != hashing.size(); ++bin_idx) { + sender.RecvCorrection(ctx, kBinSize); + auto bin_size = hashing[bin_idx].size(); - for (size_t elem_idx{}; elem_idx != kBinSize; ++elem_idx, ++oprf_idx) { + for (size_t elem_idx = 0; elem_idx != kBinSize; ++elem_idx, ++oprf_idx) { auto seed = yacl::crypto::FastRandU64(); std::vector xs(kBinSize), ys(kBinSize); - for (size_t i{}; i != kBinSize; ++i) { + for (size_t i = 0; i != kBinSize; ++i) { xs[i] = (i < bin_size ? HashToSizeT(hashing[bin_idx][i]) : i > bin_size ? yacl::crypto::FastRandU64() : kBot); - ys[i] = oprf->Eval(oprf_idx, xs[i]) ^ seed; + oprf->Eval(oprf_idx, xs[i], reinterpret_cast(&ys[i]), + sizeof(ys[i])); + ys[i] ^= seed; } - auto coeffs = Interpolate(xs, ys); - yacl::Buffer buf(coeffs.data(), coeffs.size() * sizeof(uint64_t)); - ctx->SendAsync(ctx->NextRank(), buf, "Send coefficients"); + std::vector coeffs = Interpolate(xs, ys); + ctx->SendAsync(ctx->NextRank(), + yacl::ByteContainerView(coeffs.data(), + coeffs.size() * sizeof(uint64_t)), + "Send coefficients"); auto eval = yacl::DeserializeUint128( ctx->Recv(ctx->PrevRank(), "Receive evaluation")); - ot_choice[oprf_idx] = eval == seed; + ot_choice[oprf_idx] = (eval == yacl::MakeUint128(0, seed)); } } // Step 4. Receives new elements through OT - std::vector keys(num_ot); - base_ot = yacl::crypto::BaseOtSend(ctx, kNumBaseOT); - yacl::crypto::IknpOtExtRecv(ctx, base_ot, ot_choice, absl::MakeSpan(keys)); + auto keys = ss_receiver.GenRot(ctx, ot_choice); std::vector ciphers(num_ot); auto buf = ctx->Recv(ctx->PrevRank(), "Receive ciphertexts"); + YACL_ENFORCE(buf.size() == int64_t(num_ot * sizeof(uint128_t))); std::memcpy(ciphers.data(), buf.data(), buf.size()); - std::unordered_set set_union( - elem_hashes.begin(), elem_hashes.end(), count, HashToSizeT); - for (size_t i{}; i != num_ot; ++i) { + + std::set set_union(elem_hashes.begin(), elem_hashes.end()); + + for (size_t i = 0; i != num_ot; ++i) { if (!ot_choice[i]) { - if (auto new_elem = ciphers[i] ^ keys[i]; new_elem != kBot) { - set_union.emplace(ciphers[i] ^ keys[i]); + auto new_elem = ciphers[i] ^ keys.GetBlock(i); + if (new_elem != kBot) { + set_union.emplace(new_elem); } } } diff --git a/examples/psu/krtw19_psu.h b/examples/psu/krtw19_psu.h index 3acdf41a..1026894f 100644 --- a/examples/psu/krtw19_psu.h +++ b/examples/psu/krtw19_psu.h @@ -25,9 +25,9 @@ /* submodules */ #include "yacl/crypto/hash/hash_utils.h" #include "yacl/crypto/rand/rand.h" -#include "yacl/kernels/algorithms/base_ot.h" -#include "yacl/kernels/algorithms/iknp_ote.h" -#include "yacl/kernels/algorithms/kkrt_ote.h" +#include "yacl/kernel/algorithms/base_ot.h" +#include "yacl/kernel/algorithms/kkrt_ote.h" +#include "yacl/kernel/algorithms/softspoken_ote.h" /* security parameter declaration */ YACL_MODULE_DECLARE("krtw_psu", SecParam::C::k128, SecParam::S::k40); @@ -37,10 +37,11 @@ namespace examples::psu { // Scalable Private Set Union from Symmetric-Key Techniques // https://eprint.iacr.org/2019/776.pdf (Figure 10) -void KrtwPsuSend(const std::shared_ptr&, - const std::vector&); +void KrtwPsuSend(const std::shared_ptr& ctx, + const std::vector& elem_hashes); -std::vector KrtwPsuRecv(const std::shared_ptr&, - const std::vector&); +std::vector KrtwPsuRecv( + const std::shared_ptr& ctx, + const std::vector& elem_hashes); } // namespace examples::psu diff --git a/yacl/math/galois_field/mcl_field/BUILD.bazel b/examples/zkp/BUILD.bazel similarity index 52% rename from yacl/math/galois_field/mcl_field/BUILD.bazel rename to examples/zkp/BUILD.bazel index aae18b5f..3e39f291 100644 --- a/yacl/math/galois_field/mcl_field/BUILD.bazel +++ b/examples/zkp/BUILD.bazel @@ -1,4 +1,4 @@ -# Copyright 2023 Ant Group Co., Ltd. +# Copyright 2022 Ant Group Co., Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,36 +13,27 @@ # limitations under the License. load("//bazel:yacl.bzl", "yacl_cc_library", "yacl_cc_test") -load("@bazel_skylib//lib:selects.bzl", "selects") package(default_visibility = ["//visibility:public"]) yacl_cc_library( - name = "field", - srcs = [ - "mcl_field.cc", + name = "sigma", + srcs = ["sigma.cc"], + hdrs = [ + "sigma.h", ], - hdrs = ["mcl_field.h"], - defines = selects.with_or({ - ("@yacl//bazel:yacl_build_as_debug", "@yacl//bazel:yacl_build_as_fast"): [ - # !Only for test and don't use this in production! - "MCL_FIELD_YACL_TEST", - ], - "//conditions:default": [], - }), deps = [ - "//yacl/crypto/ecc/mcl:util", - "//yacl/crypto/pairing/mcl:pairing_header", - "//yacl/math/galois_field:sketch", + "//yacl/crypto/tools:ro", + "//yacl/crypto/zkp:sigma_owh", + "//yacl/utils:parallel", ], ) yacl_cc_test( - name = "field_test", - srcs = ["mcl_field_test.cc"], + name = "sigma_test", + srcs = ["sigma_test.cc"], deps = [ - ":field", - "//yacl/crypto/pairing/mcl:pairing", + ":sigma", "//yacl/crypto/rand", ], ) diff --git a/yacl/crypto/zkp/sigma.cc b/examples/zkp/sigma.cc similarity index 71% rename from yacl/crypto/zkp/sigma.cc rename to examples/zkp/sigma.cc index 247f6fbe..af1e5a96 100644 --- a/yacl/crypto/zkp/sigma.cc +++ b/examples/zkp/sigma.cc @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/crypto/zkp/sigma.h" +#include "examples/zkp/sigma.h" #include "yacl/crypto/tools/ro.h" +#include "yacl/utils/parallel.h" -namespace yacl::crypto { +namespace examples::zkp { SigmaProtocol::SigmaProtocol(SigmaType type, const std::shared_ptr& group, @@ -43,17 +44,18 @@ SigmaProtocol::SigmaProtocol(const SigmaConfig& config, SigmaProtocol::SigmaProtocol(SigmaType type, const std::shared_ptr& group, - ByteContainerView serialized_generators) + yacl::ByteContainerView serialized_generators) : SigmaProtocol(GetSigmaConfig(type), group, serialized_generators) {} SigmaProtocol::SigmaProtocol(const SigmaConfig& config, const std::shared_ptr& group, - ByteContainerView serialized_generators) + yacl::ByteContainerView serialized_generators) : config_(config), group_ref_(group) { CheckParms(); - const auto kGroupLen = static_cast( - group_ref_->SerializePoint(group_ref_->GetGenerator()).size()); - for (uint64_t i = 0; i < serialized_generators.size(); i++) { + const auto kGroupLen = group_ref_->GetSerializeLength(); + YACL_ENFORCE(serialized_generators.size() % kGroupLen == 0); + const auto n = serialized_generators.size() / kGroupLen; + for (uint64_t i = 0; i < n; i++) { auto tmp = group_ref_->DeserializePoint( {serialized_generators.data() + kGroupLen * i, kGroupLen}); YACL_ENFORCE( @@ -121,7 +123,8 @@ bool SigmaProtocol::Verify(const SigmaStatement& statement, SigmaBatchProof SigmaProtocol::ProveBatchable( const SigmaStatement& statement, const std::vector& witness, - const std::vector& rnd_witness, ByteContainerView other_info) const { + const std::vector& rnd_witness, + yacl::ByteContainerView other_info) const { SigmaBatchProof ret_proof; // compute first message : rnd_statement ret_proof.rnd_statement = ToStatement(rnd_witness); @@ -136,7 +139,7 @@ SigmaBatchProof SigmaProtocol::ProveBatchable( bool SigmaProtocol::VerifyBatchable(const SigmaStatement& statement, const SigmaBatchProof& proof, - ByteContainerView other_info) const { + yacl::ByteContainerView other_info) const { MPInt challenge = GenChallenge(generators_, statement, proof.rnd_statement, other_info); return Verify(statement, proof.rnd_statement, challenge, proof.proof); @@ -144,7 +147,8 @@ bool SigmaProtocol::VerifyBatchable(const SigmaStatement& statement, SigmaShortProof SigmaProtocol::ProveCompact( const SigmaStatement& statement, const std::vector& witness, - const std::vector& rnd_witness, ByteContainerView other_info) const { + const std::vector& rnd_witness, + yacl::ByteContainerView other_info) const { SigmaShortProof ret_proof; std::vector rnd_statement; @@ -159,18 +163,14 @@ SigmaShortProof SigmaProtocol::ProveCompact( bool SigmaProtocol::VerifyCompact(const std::vector& statement, const SigmaShortProof& proof, - ByteContainerView other_info) const { + yacl::ByteContainerView other_info) const { YACL_ENFORCE(statement.size() == config_.num_statement); // Check if we could re-generate a same challenge by // generators||statement||rnd_statement||other_info auto p_stm = ToStatement(proof.proof); - SigmaStatement rnd_stm; // Compute rnd_statement - for (uint32_t i = 0; i < config_.num_statement; i++) { - rnd_stm.emplace_back( - VerifyOp(group_ref_, statement[i], p_stm[i], proof.challenge)); - } + auto rnd_stm = VerifyOp(group_ref_, statement, p_stm, proof.challenge); // compute challenge MPInt challenge = GenChallenge(generators_, statement, rnd_stm, other_info); return challenge == proof.challenge; @@ -188,14 +188,13 @@ Witness SigmaProtocol::GenRandomWitness() const { SigmaGenerator SigmaProtocol::GetGenerators() const { return generators_; } -Buffer SigmaProtocol::GeneratorsSerialize() const { - auto g0_buf = group_ref_->SerializePoint(generators_[0]); - const auto kGroupLen = static_cast(g0_buf.size()); - Buffer buf(kGroupLen * generators_.size()); +yacl::Buffer SigmaProtocol::GeneratorsSerialize() const { + const auto kGroupLen = group_ref_->GetSerializeLength(); + yacl::Buffer buf(kGroupLen * generators_.size()); std::memset(buf.data(), 0, buf.size()); - for (uint64_t i = 1; i < generators_.size(); i++) { - Buffer temp{buf.data() + i * kGroupLen, kGroupLen, [](void*) {}}; - group_ref_->SerializePoint(generators_[i], &temp); + for (uint64_t i = 0; i < generators_.size(); i++) { + group_ref_->SerializePoint(generators_[i], + buf.data() + i * kGroupLen, kGroupLen); } return buf; } @@ -209,45 +208,42 @@ Challenge SigmaProtocol::GenChallenge() const { MPInt SigmaProtocol::GenChallenge(const SigmaGenerator& generators, const std::vector& statement, const std::vector& rnd_statement, - ByteContainerView other_info) const { + yacl::ByteContainerView other_info) const { return GenChallenge(group_ref_, generators, statement, rnd_statement, - other_info, config_.ro_type); + other_info, config_.ro_type, config_.point_format); } -MPInt SigmaProtocol::GenChallenge(const std::shared_ptr& group, - const SigmaGenerator& generators, - const std::vector& statement, - const std::vector& rnd_statement, - ByteContainerView other_info, - HashAlgorithm ro_type) { +MPInt SigmaProtocol::GenChallenge( + const std::shared_ptr& group, yacl::ByteContainerView prefix, + const SigmaGenerator& generators, const std::vector& statement, + const std::vector& rnd_statement, + yacl::ByteContainerView other_info, HashAlgorithm ro_type, + PointOctetFormat point_format, yacl::Endian endianness) { auto order = group->GetOrder(); RandomOracle ro(ro_type, (order.BitCount() + 7) / 8); std::string buf_str; - + if (!prefix.empty()) { + buf_str.append(std::begin(prefix), std::end(prefix)); + } for (uint32_t i = 0; i < generators.size(); i++) { - buf_str.append(group->SerializePoint(generators[i])); + buf_str.append(group->SerializePoint(generators[i], point_format)); } for (uint32_t i = 0; i < statement.size(); i++) { - buf_str.append(group->SerializePoint(statement[i])); + buf_str.append(group->SerializePoint(statement[i], point_format)); } for (uint32_t i = 0; i < rnd_statement.size(); i++) { - buf_str.append(group->SerializePoint(rnd_statement[i])); + buf_str.append(group->SerializePoint(rnd_statement[i], point_format)); } buf_str.append(other_info); - // RO(gens||statements||rnd_statements||other_info) + // RO(prefix||gens||statements||rnd_statements||other_info) auto out = ro.Gen(buf_str); MPInt ret; - ret.FromMagBytes(out); + ret.FromMagBytes(out, endianness); return ret % order; } -MPInt SigmaProtocol::ProofOp(const MPInt& witness, const MPInt& rnd_witness, - const Challenge& challenge, const MPInt& order) { - return rnd_witness.SubMod(challenge.MulMod(witness, order), order); -} - SigmaProof SigmaProtocol::Prove(const SigmaConfig& config, const Witness& witness, const Witness& rnd_witness, @@ -256,12 +252,26 @@ SigmaProof SigmaProtocol::Prove(const SigmaConfig& config, YACL_ENFORCE(witness.size() == config.num_witness); YACL_ENFORCE(rnd_witness.size() == config.num_rnd_witness); - SigmaProof proofs; - // witness size = n - for (size_t i = 0; i < config.num_witness; i++) { - proofs.emplace_back(ProofOp(witness[i], rnd_witness[i], challenge, order)); - } - return proofs; + return ProofOp(witness, rnd_witness, challenge, order); +} + +MPInt SigmaProtocol::ProofOp(const MPInt& witness, const MPInt& rnd_witness, + const Challenge& challenge, const MPInt& order) { + return rnd_witness.SubMod(challenge.MulMod(witness, order), order); +} + +std::vector SigmaProtocol::ProofOp(const std::vector& witness, + const std::vector& rnd_witness, + const Challenge& challenge, + const MPInt& order) { + YACL_ENFORCE(witness.size() == rnd_witness.size()); + std::vector result(witness.size()); + yacl::parallel_for(0, witness.size(), [&](int64_t beg, int64_t end) { + for (auto i = beg; i < end; i++) { + result[i] = (rnd_witness[i] - (challenge * witness[i] % order)) % order; + } + }); + return result; } EcPoint SigmaProtocol::VerifyOp(const std::shared_ptr& group, @@ -272,4 +282,18 @@ EcPoint SigmaProtocol::VerifyOp(const std::shared_ptr& group, return ret; } -} // namespace yacl::crypto +std::vector SigmaProtocol::VerifyOp( + const std::shared_ptr& group, const std::vector& stm, + const std::vector& proof_stm, const Challenge& challenge) { + YACL_ENFORCE(proof_stm.size() == stm.size()); + + std::vector rtm(stm.size()); + yacl::parallel_for(0, stm.size(), [&](int64_t beg, int64_t end) { + for (auto i = beg; i < end; i++) { + rtm[i] = group->Add(group->Mul(stm[i], challenge), proof_stm[i]); + } + }); + return rtm; +} + +} // namespace examples::zkp diff --git a/yacl/crypto/zkp/sigma.h b/examples/zkp/sigma.h similarity index 66% rename from yacl/crypto/zkp/sigma.h rename to examples/zkp/sigma.h index a51f4683..2bfcf0c3 100644 --- a/yacl/crypto/zkp/sigma.h +++ b/examples/zkp/sigma.h @@ -17,7 +17,10 @@ #include "yacl/crypto/zkp/sigma_config.h" #include "yacl/crypto/zkp/sigma_owh.h" -namespace yacl::crypto { +namespace examples::zkp { + +using namespace yacl::crypto; +using yacl::math::MPInt; // We abide an unifying view to implment the common Sigma-type zero-knowledge // proof (ZKP) schemes, in which we view the ZKP schemes as proof of knowledge @@ -83,10 +86,10 @@ class SigmaProtocol { const SigmaGenerator& generators); explicit SigmaProtocol(SigmaType type, const std::shared_ptr& group, - ByteContainerView serialized_generators); + yacl::ByteContainerView serialized_generators); explicit SigmaProtocol(const SigmaConfig& config, const std::shared_ptr& group, - ByteContainerView serialized_generators); + yacl::ByteContainerView serialized_generators); SigmaStatement ToStatement(const Witness& witness) const; @@ -119,10 +122,10 @@ class SigmaProtocol { SigmaBatchProof ProveBatchable(const SigmaStatement& statement, const std::vector& witness, const std::vector& rnd_witness, - ByteContainerView other_info = {}) const; + yacl::ByteContainerView other_info = {}) const; bool VerifyBatchable(const SigmaStatement& statement, const SigmaBatchProof& proof, - ByteContainerView other_info = {}) const; + yacl::ByteContainerView other_info = {}) const; // // Non-interactive version, Compact @@ -130,10 +133,10 @@ class SigmaProtocol { SigmaShortProof ProveCompact(const SigmaStatement& statement, const std::vector& witness, const std::vector& rnd_witness, - ByteContainerView other_info = {}) const; + yacl::ByteContainerView other_info = {}) const; bool VerifyCompact(const std::vector& statement, const SigmaShortProof& proof, - ByteContainerView other_info = {}) const; + yacl::ByteContainerView other_info = {}) const; // // Tool Functions @@ -141,27 +144,72 @@ class SigmaProtocol { Challenge GenChallenge() const; Witness GenRandomWitness() const; SigmaGenerator GetGenerators() const; - Buffer GeneratorsSerialize() const; - - static MPInt GenChallenge(const std::shared_ptr& group, - const SigmaGenerator& generators, - const std::vector& statement, - const std::vector& rnd_statement, - ByteContainerView other_info = {}, - HashAlgorithm ro_type = HashAlgorithm::BLAKE3); + yacl::Buffer GeneratorsSerialize() const; + + // ro_type, the Random Oracle instance + // point_format, Group Point Serialization Mode + // endianness, Scalar Deserialization Mode to generate the final challenge + // Return the challenge AS: + // DeserScalar(endianness, + // RO( + // ro_type, + // prefix + // ||SerPoints(point_format, generators) + // ||SerPoints(point_format,statement) + // ||SerPoints(point_format, rnd_statement) + // ||other_info + // ) + // ) + static MPInt GenChallenge( + const std::shared_ptr& group, yacl::ByteContainerView prefix, + const SigmaGenerator& generators, const std::vector& statement, + const std::vector& rnd_statement, + yacl::ByteContainerView other_info = {}, + HashAlgorithm ro_type = HashAlgorithm::BLAKE3, + PointOctetFormat point_format = PointOctetFormat::Autonomous, + yacl::Endian endianness = yacl::Endian::big); + static MPInt GenChallenge( + const std::shared_ptr& group, const SigmaGenerator& generators, + const std::vector& statement, + const std::vector& rnd_statement, + yacl::ByteContainerView other_info = {}, + HashAlgorithm ro_type = HashAlgorithm::BLAKE3, + PointOctetFormat point_format = PointOctetFormat::Autonomous, + yacl::Endian endianness = yacl::Endian::big) { + return GenChallenge(group, "", generators, statement, rnd_statement, + other_info, ro_type, point_format, endianness); + } + static MPInt GenChallenge( + const std::shared_ptr& group, yacl::ByteContainerView prefix, + const std::vector& statement, + yacl::ByteContainerView other_info = {}, + HashAlgorithm ro_type = HashAlgorithm::BLAKE3, + PointOctetFormat point_format = PointOctetFormat::Autonomous, + yacl::Endian endianness = yacl::Endian::big) { + return GenChallenge(group, prefix, statement, {}, {}, other_info, ro_type, + point_format, endianness); + } // rnd_witness - challenge * witness static MPInt ProofOp(const MPInt& witness, const MPInt& rnd_witness, const Challenge& challenge, const MPInt& order); + static std::vector ProofOp(const std::vector& witness, + const std::vector& rnd_witness, + const Challenge& challenge, + const MPInt& order); // proof_stm( = g^proof) + statement * challenge static EcPoint VerifyOp(const std::shared_ptr& group, const EcPoint& stm, const EcPoint& proof_stm, const Challenge& challenge); + static std::vector VerifyOp(const std::shared_ptr& group, + const std::vector& stm, + const std::vector& proof_stm, + const Challenge& challenge); private: MPInt GenChallenge(const SigmaGenerator& generators, const std::vector& statement, const std::vector& rnd_statement, - ByteContainerView other_info = {}) const; + yacl::ByteContainerView other_info = {}) const; void CheckParms() const; SigmaConfig config_; @@ -169,4 +217,4 @@ class SigmaProtocol { SigmaGenerator generators_; }; -} // namespace yacl::crypto +} // namespace examples::zkp diff --git a/yacl/crypto/zkp/sigma_test.cc b/examples/zkp/sigma_test.cc similarity index 95% rename from yacl/crypto/zkp/sigma_test.cc rename to examples/zkp/sigma_test.cc index acca6719..28b4b722 100644 --- a/yacl/crypto/zkp/sigma_test.cc +++ b/examples/zkp/sigma_test.cc @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/crypto/zkp/sigma.h" +#include "examples/zkp/sigma.h" #include "gtest/gtest.h" #include "yacl/crypto/rand/rand.h" -namespace yacl::crypto { +namespace examples::zkp { namespace { @@ -128,7 +128,8 @@ class Secp256k1SigmaTest : public SigmaTest { void SetUp() override { std::string lib_name; std::tie(lib_name, config_) = GetParam(); - group_ = EcGroupFactory::Instance().Create(kSigmaEcName, ArgLib = lib_name); + group_ = EcGroupFactory::Instance().Create(kSigmaEcName, + yacl::ArgLib = lib_name); } }; @@ -151,4 +152,4 @@ TEST_P(Secp256k1SigmaTest, SigmaOWH) { TestSigma(); } -} // namespace yacl::crypto +} // namespace examples::zkp diff --git a/yacl/base/aligned_vector.h b/yacl/base/aligned_vector.h index a2f8dd29..529e32ec 100644 --- a/yacl/base/aligned_vector.h +++ b/yacl/base/aligned_vector.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include diff --git a/yacl/crypto/commitment/BUILD.bazel b/yacl/crypto/commitment/BUILD.bazel new file mode 100644 index 00000000..b9190549 --- /dev/null +++ b/yacl/crypto/commitment/BUILD.bazel @@ -0,0 +1,36 @@ +# Copyright 2022 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:yacl.bzl", "yacl_cc_library", "yacl_cc_test") + +package(default_visibility = ["//visibility:public"]) + +yacl_cc_library( + name = "pedersen_commit", + hdrs = [ + "pedersen_commit.h", + ], + deps = [ + "//yacl/crypto/hash:hash_utils", + "//yacl/crypto/zkp:sigma_owh", + ], +) + +yacl_cc_test( + name = "pedersen_commit_test", + srcs = ["pedersen_commit_test.cc"], + deps = [ + ":pedersen_commit", + ], +) diff --git a/yacl/crypto/zkp/pedersen_commit.h b/yacl/crypto/commitment/pedersen_commit.h similarity index 100% rename from yacl/crypto/zkp/pedersen_commit.h rename to yacl/crypto/commitment/pedersen_commit.h diff --git a/yacl/crypto/zkp/pedersen_commit_test.cc b/yacl/crypto/commitment/pedersen_commit_test.cc similarity index 97% rename from yacl/crypto/zkp/pedersen_commit_test.cc rename to yacl/crypto/commitment/pedersen_commit_test.cc index 81502c67..e05d6d8f 100644 --- a/yacl/crypto/zkp/pedersen_commit_test.cc +++ b/yacl/crypto/commitment/pedersen_commit_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/crypto/zkp/pedersen_commit.h" +#include "yacl/crypto/commitment/pedersen_commit.h" #include "gtest/gtest.h" diff --git a/yacl/crypto/ecc/BUILD.bazel b/yacl/crypto/ecc/BUILD.bazel index 0ce5416d..9c29047d 100644 --- a/yacl/crypto/ecc/BUILD.bazel +++ b/yacl/crypto/ecc/BUILD.bazel @@ -19,6 +19,8 @@ package(default_visibility = ["//visibility:public"]) yacl_cc_library( name = "ecc", deps = [ + "//yacl/crypto/ecc/FourQlib", + "//yacl/crypto/ecc/lib25519", "//yacl/crypto/ecc/libsodium", "//yacl/crypto/ecc/mcl:ecc", "//yacl/crypto/ecc/openssl", diff --git a/yacl/math/galois_field/mpint_field/BUILD.bazel b/yacl/crypto/ecc/FourQlib/BUILD.bazel similarity index 57% rename from yacl/math/galois_field/mpint_field/BUILD.bazel rename to yacl/crypto/ecc/FourQlib/BUILD.bazel index 8ab366b7..df3d2941 100644 --- a/yacl/math/galois_field/mpint_field/BUILD.bazel +++ b/yacl/crypto/ecc/FourQlib/BUILD.bazel @@ -1,4 +1,4 @@ -# Copyright 2023 Ant Group Co., Ltd. +# Copyright 2024 Ant Group Co., Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,33 +12,31 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("//bazel:yacl.bzl", "yacl_cc_binary", "yacl_cc_library", "yacl_cc_test") +load("//bazel:yacl.bzl", "yacl_cc_library", "yacl_cc_test") package(default_visibility = ["//visibility:public"]) yacl_cc_library( - name = "mpint_field", - srcs = ["mpint_field.cc"], - hdrs = ["mpint_field.h"], - deps = [ - "//yacl/math/galois_field:sketch", - ], + name = "FourQlib", + srcs = ["FourQ_factory.cc"], + deps = ["FourQ_group"], alwayslink = 1, ) -yacl_cc_test( - name = "mpint_field_test", - srcs = ["mpint_field_test.cc"], +yacl_cc_library( + name = "FourQ_group", + srcs = ["FourQ_group.cc"], + hdrs = ["FourQ_group.h"], deps = [ - ":mpint_field", + "//yacl/crypto/ecc:spi", + "@com_github_microsoft_FourQlib//:FourQlib", ], ) -yacl_cc_binary( - name = "bench", - srcs = ["mpint_field_bench.cc"], +yacl_cc_test( + name = "FourQ_test", + srcs = ["FourQ_test.cc"], deps = [ - "//yacl/math/galois_field", - "@com_github_google_benchmark//:benchmark", + ":FourQlib", ], ) diff --git a/yacl/crypto/ecc/FourQlib/FourQ_factory.cc b/yacl/crypto/ecc/FourQlib/FourQ_factory.cc new file mode 100644 index 00000000..69441909 --- /dev/null +++ b/yacl/crypto/ecc/FourQlib/FourQ_factory.cc @@ -0,0 +1,37 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "yacl/crypto/ecc/FourQlib/FourQ_group.h" + +namespace yacl::crypto::FourQ { + +namespace { + +const std::string kLibName = "FourQlib"; + +std::unique_ptr Create(const CurveMeta &meta) { + YACL_ENFORCE(meta.LowerName() == "fourq", "curve {} not supported", + meta.name); + return std::make_unique(meta); +} + +bool IsSupported(const CurveMeta &meta) { return meta.LowerName() == "fourq"; } + +REGISTER_EC_LIBRARY(kLibName, 1500, IsSupported, Create); + +} // namespace + +std::string FourQGroup::GetLibraryName() const { return kLibName; } + +} // namespace yacl::crypto::FourQ diff --git a/yacl/crypto/ecc/FourQlib/FourQ_group.cc b/yacl/crypto/ecc/FourQlib/FourQ_group.cc new file mode 100644 index 00000000..5dbd287c --- /dev/null +++ b/yacl/crypto/ecc/FourQlib/FourQ_group.cc @@ -0,0 +1,350 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "yacl/crypto/ecc/FourQlib/FourQ_group.h" + +namespace yacl::crypto::FourQ { + +// Elements (a+b*i) over GF(p^2), where a and b are defined over GF(p), are +// encoded as a||b, with a in the least significant position. +MPInt F2elm2MPInt(const f2elm_t f2elm) { + MPInt r(0, 256); + r.FromMagBytes(yacl::ByteContainerView(f2elm, 32), Endian::little); + return r; +} + +// Reverse operation of F2elm2MPInt +void MPIntToF2elm(const MPInt& x, f2elm_t f2elm) { + memset(f2elm, 0, 32); + x.ToMagBytes(reinterpret_cast(f2elm), 32, Endian::little); +} + +FourQGroup::FourQGroup(const CurveMeta& meta) : EcGroupSketch(meta) { + n_ = + MPInt("0x29CBC14E5E0A72F05397829CBC14E5DFBD004DFE0F79992FB2540EC7768CE7"); + h_ = MPInt("0x188"); + + g_ = MulBase(1_mp); +} + +void FourQGroup::MPIntToDigits(const MPInt& scalar, digit_t* out, + unsigned int nwords) const { + auto s = scalar.Mod(n_); + unsigned int size = sizeof(digit_t) * nwords; + memset(out, 0, size); + s.ToMagBytes(reinterpret_cast(out), size, Endian::little); +} + +MPInt FourQGroup::GetCofactor() const { return h_; } + +MPInt FourQGroup::GetField() const { YACL_THROW("not impl"); } + +MPInt FourQGroup::GetOrder() const { return n_; } + +EcPoint FourQGroup::GetGenerator() const { return g_; } + +std::string FourQGroup::ToString() const { + return fmt::format("Curve {} from {}", GetCurveName(), GetLibraryName()); +} + +EcPoint FourQGroup::Add(const EcPoint& p1, const EcPoint& p2) const { + point_extproj_precomp_t p1_r2; + R1_to_R2(const_cast(CastR1(p1)), p1_r2); + + point_extproj_precomp_t p2_r3; + R1_to_R3(const_cast(CastR1(p2)), p2_r3); + + EcPoint r(std::in_place_type); + eccadd_core(p1_r2, p2_r3, CastR1(r)); + + return r; +} + +void FourQGroup::AddInplace(EcPoint* p1, const EcPoint& p2) const { + point_extproj_precomp_t p2_r3; + R1_to_R2(const_cast(CastR1(p2)), p2_r3); + + eccadd(p2_r3, CastR1(*p1)); +} + +EcPoint FourQGroup::Double(const EcPoint& p) const { + auto r = p; + eccdouble(CastR1(r)); + + return r; +} + +void FourQGroup::DoubleInplace(EcPoint* p) const { eccdouble(CastR1(*p)); } + +EcPoint FourQGroup::Mul(const EcPoint& point, const MPInt& scalar) const { + digit_t digits[NWORDS_ORDER]; + MPIntToDigits(scalar, digits, NWORDS_ORDER); + point_t p; + point_t q; + auto point_cpy = point; + eccnorm(CastR1(point_cpy), p); + ecc_mul(p, digits, q, false); + + EcPoint r(std::in_place_type); + point_setup(q, CastR1(r)); + + return r; +} + +void FourQGroup::MulInplace(EcPoint* point, const MPInt& scalar) const { + digit_t digits[NWORDS_ORDER]; + MPIntToDigits(scalar, digits, NWORDS_ORDER); + point_t p; + eccnorm(CastR1(*point), p); + ecc_mul(p, digits, p, false); + + point_setup(p, CastR1(*point)); +} + +EcPoint FourQGroup::MulBase(const MPInt& scalar) const { + digit_t digits[NWORDS_ORDER]; + MPIntToDigits(scalar, digits, NWORDS_ORDER); + + point_t q; + ecc_mul_fixed(digits, q); + + EcPoint r(std::in_place_type); + point_setup(q, CastR1(r)); + + return r; +} + +EcPoint FourQGroup::MulDoubleBase(const MPInt& s1, const MPInt& s2, + const EcPoint& p2) const { + digit_t s1_digits[NWORDS_ORDER], s2_digits[NWORDS_ORDER]; + MPIntToDigits(s1, s1_digits, NWORDS_ORDER); + MPIntToDigits(s2, s2_digits, NWORDS_ORDER); + + point_t p; + point_t q; + auto p2_cpy = p2; + eccnorm(CastR1(p2_cpy), p); + + ecc_mul_double(s1_digits, p, s2_digits, q); + + EcPoint r(std::in_place_type); + point_setup(q, CastR1(r)); + + return r; +} + +EcPoint FourQGroup::Negate(const EcPoint& point) const { + if (IsInfinity(point)) { + return point; + } + + auto r = point; + auto* p = CastR1(r); + + fp2neg1271(p->y); + fp2neg1271(p->z); + + return r; +} + +void FourQGroup::NegateInplace(EcPoint* point) const { + if (IsInfinity(*point)) { + return; + } + + auto* p = CastR1(*point); + fp2neg1271(p->y); + fp2neg1271(p->z); +} + +EcPoint FourQGroup::CopyPoint(const EcPoint& point) const { + if (std::holds_alternative(point)) { + return point; + } + + if (std::holds_alternative(point)) { + AffinePoint p = std::get(point); + + point_t q; + MPIntToF2elm(p.x, q->x); + MPIntToF2elm(p.y, q->y); + + EcPoint r(std::in_place_type); + point_setup(q, CastR1(r)); + + YACL_ENFORCE(IsInCurveGroup(r), "Illegal affine point {}, not in ec group", + p); + + return r; + } + + YACL_THROW("Unsupported EcPoint type {}", point.index()); +} + +AffinePoint FourQGroup::GetAffinePoint(const EcPoint& point) const { + point_t p; + auto point_cpy = point; + eccnorm(CastR1(point_cpy), p); + + return {F2elm2MPInt(p->x), F2elm2MPInt(p->y)}; +} + +uint64_t FourQGroup::GetSerializeLength(PointOctetFormat format) const { + YACL_ENFORCE(format == PointOctetFormat::Autonomous, + "{} only support Autonomous format, given={}", GetLibraryName(), + (int)format); + return 32; +} + +Buffer FourQGroup::SerializePoint(const EcPoint& point, + PointOctetFormat format) const { + YACL_ENFORCE(format == PointOctetFormat::Autonomous, + "{} only support Autonomous format, given={}", GetLibraryName(), + (int)format); + + auto point_cpy = point; + point_t p; + eccnorm(CastR1(point_cpy), p); + + Buffer buf(32); + encode(p, buf.data()); + + return buf; +} + +void FourQGroup::SerializePoint(const EcPoint& point, PointOctetFormat format, + Buffer* buf) const { + *buf = SerializePoint(point, format); +} + +void FourQGroup::SerializePoint(const EcPoint& point, PointOctetFormat format, + uint8_t* buf, uint64_t buf_size) const { + YACL_ENFORCE(format == PointOctetFormat::Autonomous, + "{} only support Autonomous format, given={}", GetLibraryName(), + (int)format); + YACL_ENFORCE(buf_size >= 32, "buf size is small than needed 32"); + + auto point_cpy = point; + point_t p; + eccnorm(CastR1(point_cpy), p); + encode(p, buf); +} + +EcPoint FourQGroup::DeserializePoint(ByteContainerView buf, + PointOctetFormat format) const { + YACL_ENFORCE(format == PointOctetFormat::Autonomous, + "{} only support Autonomous format, given={}", GetLibraryName(), + (int)format); + + point_t p; + auto status = decode(buf.data(), p); + YACL_ENFORCE(status == ECCRYPTO_SUCCESS, FourQ_get_error_message(status)); + + EcPoint r(std::in_place_type); + point_setup(p, CastR1(r)); + + return r; +} + +EcPoint FourQGroup::HashToCurve(HashToCurveStrategy, std::string_view) const { + YACL_THROW("not impl"); +} + +size_t FourQGroup::HashPoint(const EcPoint& point) const { + auto* p = const_cast(CastR1(point)); + f2elm_t x; + f2elm_t z; + + fp2copy1271(p->z, z); + fp2inv1271(z); + fp2mul1271(p->x, z, x); + mod1271(x[0]); + mod1271(x[1]); + + digit_t* buf = reinterpret_cast(x); + + // Assume digit_t size of 64 bits + std::hash h; + // h(buf[0]) ^ ... ^ h(buf[3]) produce the same hash value for P and -P, while + // h(buf[0]) ^ ... ^ h(buf[2]) does not + return h(buf[0]) ^ h(buf[1]) ^ h(buf[2]); // ^ h(buf[3]) +} + +bool FourQGroup::PointEqual(const EcPoint& p1, const EcPoint& p2) const { + if (IsInfinity(p1) && IsInfinity(p2)) { + return true; + } + + auto* p1p = const_cast(CastR1(p1)); + auto* p2p = const_cast(CastR1(p2)); + + // p1 = (X1/Z1, Y1/Z1) = ((X1*Z2)/(Z1*Z2), (Y1*Z2)/(Z1*Z2)); + // P2 = (X2/Z2, Y2/Z2) = ((Z1*X2)/(Z1*Z2), (Z1*Y2)/(Z1*Z2)); + f2elm_t a; + f2elm_t b; + fp2mul1271(p1p->x, p2p->z, a); + fp2mul1271(p1p->z, p2p->x, b); + auto* pa = reinterpret_cast(a); + auto* pb = reinterpret_cast(b); + for (size_t i = 0; i < 2 * NWORDS_FIELD; ++i) { + if (pa[i] != pb[i]) { + return false; + } + } + + fp2mul1271(p1p->y, p2p->z, a); + fp2mul1271(p1p->z, p2p->y, b); + pa = reinterpret_cast(a); + pb = reinterpret_cast(b); + for (size_t i = 0; i < 2 * NWORDS_FIELD; ++i) { + if (pa[i] != pb[i]) { + return false; + } + } + + return true; +} + +bool FourQGroup::IsInCurveGroup(const EcPoint& point) const { + // point must be in affine coordinates (that is: z == 1) + auto p = point; + point_t q; + eccnorm(CastR1(p), q); + point_setup(q, CastR1(p)); // make z = 1 + + return ecc_point_validate(CastR1(p)); +} + +bool FourQGroup::IsInfinity(const EcPoint& point) const { + auto* x = + const_cast(reinterpret_cast(CastR1(point)->x)); + auto* z = + const_cast(reinterpret_cast(CastR1(point)->z)); + + return is_zero_ct(x, 2 * NWORDS_FIELD) || is_zero_ct(z, 2 * NWORDS_FIELD); +} + +const point_extproj* FourQGroup::CastR1(const EcPoint& p) { + YACL_ENFORCE(std::holds_alternative(p), + "Illegal EcPoint, expected Array160, real={}", p.index()); + return reinterpret_cast(std::get(p).data()); +} + +point_extproj* FourQGroup::CastR1(EcPoint& p) { + YACL_ENFORCE(std::holds_alternative(p), + "Illegal EcPoint, expected Array160, real={}", p.index()); + return reinterpret_cast(std::get(p).data()); +} + +} // namespace yacl::crypto::FourQ \ No newline at end of file diff --git a/yacl/crypto/ecc/FourQlib/FourQ_group.h b/yacl/crypto/ecc/FourQlib/FourQ_group.h new file mode 100644 index 00000000..116d287a --- /dev/null +++ b/yacl/crypto/ecc/FourQlib/FourQ_group.h @@ -0,0 +1,84 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "FourQ_internal.h" + +#include "yacl/crypto/ecc/group_sketch.h" + +namespace yacl::crypto::FourQ { + +class FourQGroup : public EcGroupSketch { + public: + explicit FourQGroup(const CurveMeta& meta); + std::string GetLibraryName() const override; + + MPInt GetCofactor() const override; + MPInt GetField() const override; + MPInt GetOrder() const override; + EcPoint GetGenerator() const override; + std::string ToString() const override; + + EcPoint Add(const EcPoint& p1, const EcPoint& p2) const override; + void AddInplace(EcPoint* p1, const EcPoint& p2) const override; + + EcPoint Double(const EcPoint& p) const override; + void DoubleInplace(EcPoint* p) const override; + + EcPoint Mul(const EcPoint& point, const MPInt& scalar) const override; + void MulInplace(EcPoint* point, const MPInt& scalar) const override; + + EcPoint MulBase(const MPInt& scalar) const override; + EcPoint MulDoubleBase(const MPInt& s1, const MPInt& s2, + const EcPoint& p2) const override; + + EcPoint Negate(const EcPoint& point) const override; + void NegateInplace(EcPoint* point) const override; + + EcPoint CopyPoint(const EcPoint& point) const override; + + AffinePoint GetAffinePoint(const EcPoint& point) const override; + + uint64_t GetSerializeLength(PointOctetFormat format) const override; + + Buffer SerializePoint(const EcPoint& point, + PointOctetFormat format) const override; + void SerializePoint(const EcPoint& point, PointOctetFormat format, + Buffer* buf) const override; + void SerializePoint(const EcPoint& point, PointOctetFormat format, + uint8_t* buf, uint64_t buf_size) const override; + EcPoint DeserializePoint(ByteContainerView buf, + PointOctetFormat format) const override; + + EcPoint HashToCurve(HashToCurveStrategy strategy, + std::string_view str) const override; + + size_t HashPoint(const EcPoint& point) const override; + bool PointEqual(const EcPoint& p1, const EcPoint& p2) const override; + bool IsInCurveGroup(const EcPoint& point) const override; + bool IsInfinity(const EcPoint& point) const override; + + private: + static const point_extproj* CastR1(const EcPoint& p); + static point_extproj* CastR1(EcPoint& p); + + void MPIntToDigits(const MPInt& x, digit_t* out, unsigned int nwords) const; + + EcPoint g_; // generator + MPInt n_; // order + MPInt h_; // cofactor +}; + +} // namespace yacl::crypto::FourQ \ No newline at end of file diff --git a/yacl/crypto/ecc/FourQlib/FourQ_test.cc b/yacl/crypto/ecc/FourQlib/FourQ_test.cc new file mode 100644 index 00000000..33195fc4 --- /dev/null +++ b/yacl/crypto/ecc/FourQlib/FourQ_test.cc @@ -0,0 +1,133 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gtest/gtest.h" + +#include "yacl/crypto/ecc/FourQlib/FourQ_group.h" +#include "yacl/crypto/ecc/ec_point.h" +#include "yacl/crypto/ecc/ecc_spi.h" +#include "yacl/utils/spi/spi_factory.h" + +namespace yacl::crypto::FourQ { + +extern MPInt F2elm2MPInt(const f2elm_t f2elm); +extern void MPIntToF2elm(const MPInt& x, f2elm_t f2elm); + +} // namespace yacl::crypto::FourQ + +namespace yacl::crypto::FourQ::test { + +std::ostream& operator<<(std::ostream& os, const EcPoint& p) { + const auto* r1 = + reinterpret_cast(std::get(p).data()); + + return os << fmt::format("[X={}, Y={}, Z={}, Ta={}, Tb={}]", + F2elm2MPInt(r1->x), F2elm2MPInt(r1->y), + F2elm2MPInt(r1->z), F2elm2MPInt(r1->ta), + F2elm2MPInt(r1->tb)); +} + +class FourQTest : public ::testing::Test { + protected: + std::unique_ptr ec_ = + EcGroupFactory::Instance().Create("FourQ", ArgLib = "FourQlib"); +}; + +TEST_F(FourQTest, DISABLED_CopyPointWorks) { + // Convert function + f2elm_t f; + MPIntToF2elm(123456789_mp, f); + EXPECT_EQ(F2elm2MPInt(f), 123456789_mp); + + // CopyPoint: point_extproj -> point_extproj + auto ecp1 = ec_->MulBase(852_mp); + auto ecp2 = ec_->CopyPoint(ecp1); + EXPECT_TRUE(ec_->PointEqual(ecp1, ecp2)); + + // check is deep copy + ec_->AddInplace(&ecp1, ec_->GetGenerator()); + EXPECT_FALSE(ec_->PointEqual(ecp1, ecp2)); + + auto ecp3 = ec_->MulBase(853_mp); + EXPECT_TRUE(ec_->PointEqual(ecp1, ecp3)); + + // CopyPoint: affine_point -> point_extproj + auto ap = ec_->GetAffinePoint(ecp1); + EXPECT_TRUE(ec_->PointEqual(ecp1, ec_->CopyPoint(ap))); +} + +TEST_F(FourQTest, DISABLED_AffinePointWorks) { + ASSERT_EQ(ec_->GetLibraryName(), "FourQlib"); + + AffinePoint ap_g{ + "0x1E1F553F2878AA9C96869FB360AC77F61A3472237C2FB305286592AD7B3833AA"_mp, + "0x6E1C4AF8630E024249A7C344844C8B5C0E3FEE9BA120785AB924A2462BCBB287"_mp}; + auto g = ec_->GetAffinePoint(ec_->GetGenerator()); + EXPECT_EQ(ap_g, g); + + EcPoint new_g = ec_->CopyPoint(ap_g); + EXPECT_TRUE(ec_->PointEqual(new_g, ec_->GetGenerator())); + + auto inf = ec_->GetAffinePoint(ec_->MulBase(0_mp)); + EXPECT_EQ(inf, AffinePoint(0_mp, 1_mp)) << inf; + EXPECT_TRUE(ec_->PointEqual(ec_->CopyPoint(inf), ec_->MulBase(0_mp))); + + auto any_p = ec_->MulBase(123456_mp); + auto any_ap = ec_->GetAffinePoint(any_p); + EXPECT_TRUE(ec_->PointEqual(ec_->CopyPoint(any_ap), any_p)); +} + +TEST_F(FourQTest, DISABLED_InfWorks) { + auto g = ec_->GetGenerator(); + EXPECT_TRUE(ec_->IsInCurveGroup(g)); + + auto inf = ec_->MulBase(0_mp); + auto inf2 = ec_->CopyPoint(inf); + EXPECT_TRUE(ec_->PointEqual(inf, inf2)); + EXPECT_FALSE(ec_->PointEqual(inf, g)); + EXPECT_TRUE(ec_->IsInfinity(inf2)); + EXPECT_TRUE(ec_->IsInCurveGroup(inf2)); + + ec_->AddInplace(&inf, ec_->GetGenerator()); + EXPECT_FALSE(ec_->PointEqual(inf, inf2)); + EXPECT_TRUE(ec_->PointEqual(inf, g)); + + inf = ec_->MulBase(0_mp); + inf2 = ec_->CopyPoint(AffinePoint(0_mp, 1_mp)); + EXPECT_EQ(ec_->HashPoint(inf), ec_->HashPoint(inf2)); + EXPECT_TRUE(ec_->PointEqual(inf, inf2)); +} + +TEST_F(FourQTest, DISABLED_NegateWorks) { + // simple works + auto g = ec_->MulBase(1_mp); + EXPECT_TRUE(ec_->PointEqual(g, ec_->GetGenerator())); + auto g2 = ec_->MulBase(2_mp); + EXPECT_TRUE(ec_->PointEqual(g2, ec_->Add(g, g))); + + EcPoint ng = ec_->Negate(ec_->GetGenerator()); + EXPECT_TRUE(ec_->PointEqual(ng, ec_->MulBase(-1_mp))); + EXPECT_TRUE(ec_->PointEqual(ng, ec_->Sub(g, g2))); + auto inf = ec_->Add(ng, ec_->GetGenerator()); + EXPECT_TRUE(ec_->IsInfinity(inf)); + ec_->NegateInplace(&inf); + EXPECT_TRUE(ec_->IsInfinity(inf)); + EXPECT_EQ(ec_->GetAffinePoint(inf), AffinePoint(0_mp, 1_mp)); + + EXPECT_TRUE(ec_->PointEqual(ec_->MulBase(-2_mp), ec_->Add(ng, ng))); + EXPECT_TRUE(ec_->PointEqual(ec_->MulBase(-1000_mp), + ec_->Negate(ec_->MulBase(1000_mp)))); +} + +} // namespace yacl::crypto::FourQ::test \ No newline at end of file diff --git a/yacl/crypto/ecc/curve_meta.cc b/yacl/crypto/ecc/curve_meta.cc index a3e3d710..ebe80872 100644 --- a/yacl/crypto/ecc/curve_meta.cc +++ b/yacl/crypto/ecc/curve_meta.cc @@ -647,6 +647,14 @@ std::vector kPredefinedCurves = { {"bn190", {}, CurveForm::Weierstrass, FieldType::Prime, 80}, {"bn222", {}, CurveForm::Weierstrass, FieldType::Prime, 80}, {"bn254", {"Fp254BNb"}, CurveForm::Weierstrass, FieldType::Prime, 100}, + // BN_SNARK, used by Ethereum as the built-in curve on Solidity for Smart + // Contract, Zcash and etc. + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-196.md + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-197.md + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1108.md + // Curve named listed by + // https://docs.google.com/spreadsheets/d/1t6ibmx_BqCxyovP18RfGEUUtKrl2d5MD + {"bn_snark1", {}, CurveForm::Weierstrass, FieldType::Prime, 100}, {"bn286", {}, CurveForm::Weierstrass, FieldType::Prime, 100}, {"bn318", {}, CurveForm::Weierstrass, FieldType::Prime, 100}, {"bn350", {}, CurveForm::Weierstrass, FieldType::Prime, 100}, @@ -822,6 +830,7 @@ std::vector kPredefinedCurves = { {"brainpoolP384t1", {}, CurveForm::Weierstrass, FieldType::Prime, 192}, {"brainpoolP512r1", {}, CurveForm::Weierstrass, FieldType::Prime, 256}, {"brainpoolP512t1", {}, CurveForm::Weierstrass, FieldType::Prime, 256}, + {"FourQ", {}, CurveForm::TwistedEdwards, FieldType::Extension, 128}, }; CurveName CurveMeta::LowerName() const { return absl::AsciiStrToLower(name); } diff --git a/yacl/crypto/ecc/ec_point.h b/yacl/crypto/ecc/ec_point.h index 907299b8..fbd00e72 100644 --- a/yacl/crypto/ecc/ec_point.h +++ b/yacl/crypto/ecc/ec_point.h @@ -84,12 +84,13 @@ struct AffinePoint { // Feel free to add more storage types if you need. // Here are some examples: using Array32 = std::array; // exactly 256bits +using Array128 = std::array; using Array160 = std::array; // enough to store four 40B points // The storage format inside EcPoint is explained by each curve itself, here is // a black box -using EcPoint = std::variant; +using EcPoint = std::variant; inline auto format_as(const AffinePoint &ap) { return fmt::streamed(ap); } diff --git a/yacl/crypto/ecc/ecc_test.cc b/yacl/crypto/ecc/ecc_test.cc index d0eaf358..754ada2d 100644 --- a/yacl/crypto/ecc/ecc_test.cc +++ b/yacl/crypto/ecc/ecc_test.cc @@ -182,9 +182,11 @@ class EcCurveTest : public ::testing::TestWithParam { ASSERT_TRUE( ec_->PointEqual(ec_->DeserializePoint(buf), ec_->GetGenerator())); - // todo: X962 support in libsodium + // todo: X962 support in libsodium and lib25519 if (ec_->GetLibraryName() == "Toy" || - ec_->GetLibraryName() == "libsodium") { + ec_->GetLibraryName() == "libsodium" || + ec_->GetLibraryName() == "lib25519" || + ec_->GetLibraryName() == "FourQlib") { return; // The toy lib does not support X9.62 format } @@ -365,6 +367,28 @@ TEST_P(Ed25519CurveTest, SpiTest) { RunAllTests(); } +class FourQCurveTest : public EcCurveTest { + protected: + void SetUp() override { + ec_ = EcGroupFactory::Instance().Create("FourQ", ArgLib = GetParam()); + } +}; + +INSTANTIATE_TEST_SUITE_P( + FourQTest, FourQCurveTest, + ::testing::ValuesIn(EcGroupFactory::Instance().ListLibraries("FourQ"))); + +TEST_P(FourQCurveTest, DISABLED_SpiTest) { + EXPECT_STRCASEEQ(ec_->GetCurveName().c_str(), "FourQ"); + EXPECT_EQ(ec_->GetCurveForm(), CurveForm::TwistedEdwards); + EXPECT_EQ(ec_->GetFieldType(), FieldType::Extension); + EXPECT_EQ(ec_->GetSecurityStrength(), 128); + EXPECT_FALSE(ec_->ToString().empty()); + + // Run Other tests + RunAllTests(); +} + class Secp256k1CurveTest : public EcCurveTest { protected: void SetUp() override { diff --git a/yacl/crypto/ecc/lib25519/BUILD.bazel b/yacl/crypto/ecc/lib25519/BUILD.bazel new file mode 100644 index 00000000..03d08e76 --- /dev/null +++ b/yacl/crypto/ecc/lib25519/BUILD.bazel @@ -0,0 +1,86 @@ +# Copyright 2024 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:yacl.bzl", "yacl_cc_library", "yacl_cc_test") + +package(default_visibility = ["//visibility:public"]) + +yacl_cc_library( + name = "lib25519", + deps = select({ + "@platforms//cpu:x86_64": [ + ":lib25519_factory", + ], + "//conditions:default": [], + }), +) + +yacl_cc_library( + name = "lib25519_factory", + srcs = [ + "lib25519_factory.cc", + ], + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + ], + deps = [ + ":ed25519_group", + ], + alwayslink = 1, +) + +yacl_cc_library( + name = "ed25519_group", + srcs = ["ed25519_group.cc"], + hdrs = ["ed25519_group.h"], + linkstatic = True, + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + ], + deps = [ + ":lib25519_group", + ], +) + +yacl_cc_library( + name = "lib25519_group", + srcs = ["lib25519_group.cc"], + hdrs = [ + "lib25519_group.h", + "lib25519_private.h", + ], + linkstatic = True, + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + ], + deps = [ + "//yacl/crypto/ecc:spi", + "@lib25519//:25519", + ], +) + +yacl_cc_test( + name = "ed25519_test", + srcs = ["ed25519_test.cc"], + target_compatible_with = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + ], + deps = [ + ":lib25519", + ], +) diff --git a/yacl/crypto/ecc/lib25519/ed25519_group.cc b/yacl/crypto/ecc/lib25519/ed25519_group.cc new file mode 100644 index 00000000..22694477 --- /dev/null +++ b/yacl/crypto/ecc/lib25519/ed25519_group.cc @@ -0,0 +1,166 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "yacl/crypto/ecc/lib25519/ed25519_group.h" + +namespace yacl::crypto::lib25519 { + +MPInt Fe25519ToMPInt(const fe25519& x) { + // TODO: whether to freeze x first? + MPInt r(0, 255); + r.FromMagBytes(yacl::ByteContainerView(&x, 32), Endian::little); + return r; +} + +Ed25519Group::Ed25519Group(const CurveMeta& meta, const CurveParam& param) + : Lib25519Group(meta, param) { + static_assert(sizeof(ge25519_p3) <= sizeof(Array128)); + + g_ = Ed25519Group::MulBase(1_mp); + inf_ = Ed25519Group::Sub(g_, g_); +} + +bool Ed25519Group::MPInt2Scalar(const MPInt& mp, sc25519* scalar) const { + auto s = mp.Mod(param_.n); + Array32 buf; + s.ToBytes(buf.data(), 32, Endian::little); + sc25519_from32bytes(scalar, buf.data()); + return s.IsPositive(); +} + +EcPoint Ed25519Group::GetGenerator() const { return g_; } + +EcPoint Ed25519Group::Add(const EcPoint& p1, const EcPoint& p2) const { + EcPoint r(std::in_place_type); + ge25519_add(CastP3(r), CastP3(p1), CastP3(p2)); + + return r; +} + +void Ed25519Group::AddInplace(EcPoint* p1, const EcPoint& p2) const { + ge25519_add(CastP3(*p1), CastP3(*p1), CastP3(p2)); +} + +EcPoint Ed25519Group::Sub(const EcPoint& p1, const EcPoint& p2) const { + EcPoint r(std::in_place_type); + ge25519_sub(CastP3(r), CastP3(p1), CastP3(p2)); + + return r; +} + +void Ed25519Group::SubInplace(EcPoint* p1, const EcPoint& p2) const { + ge25519_sub(CastP3(*p1), CastP3(*p1), CastP3(p2)); +} + +EcPoint Ed25519Group::Double(const EcPoint& p) const { + EcPoint r(std::in_place_type); + ge25519_double(CastP3(r), CastP3(p)); + + return r; +} + +void Ed25519Group::DoubleInplace(EcPoint* p) const { + ge25519_double(CastP3(*p), CastP3(*p)); +} + +EcPoint Ed25519Group::MulBase(const MPInt& scalar) const { + sc25519 s; + if (!MPInt2Scalar(scalar, &s)) { + return inf_; + }; + + EcPoint r(std::in_place_type); + ge25519_scalarmult_base(CastP3(r), &s); + + return r; +} + +EcPoint Ed25519Group::Mul(const EcPoint& point, const MPInt& scalar) const { + sc25519 s; + if (!MPInt2Scalar(scalar, &s) || IsInfinity(point)) { + return inf_; + }; + + EcPoint r(std::in_place_type); + ge25519_scalarmult(CastP3(r), CastP3(point), &s); + + return r; +} + +void Ed25519Group::MulInplace(EcPoint* point, const MPInt& scalar) const { + sc25519 s; + if (!MPInt2Scalar(scalar, &s) || IsInfinity(*point)) { + *point = inf_; + } else { + ge25519_scalarmult(CastP3(*point), CastP3(*point), &s); + } +} + +EcPoint Ed25519Group::MulDoubleBase(const MPInt& s1, const MPInt& s2, + const EcPoint& p2) const { + auto r = MulBase(s1); + AddInplace(&r, Mul(p2, s2)); + return r; +} + +EcPoint Ed25519Group::Negate(const EcPoint& point) const { + if (IsInfinity(point)) { + return point; + } + + auto p3 = CastP3(point); + EcPoint r(std::in_place_type); + auto r3 = CastP3(r); + + r3->x = p3->x; + fe25519_neg(&r3->y, &p3->y); + fe25519_neg(&r3->z, &p3->z); + r3->t = p3->t; + return r; +} + +void Ed25519Group::NegateInplace(EcPoint* point) const { + if (IsInfinity(*point)) { + return; + } + + auto* p3 = CastP3(*point); + fe25519_neg(&p3->y, &p3->y); + fe25519_neg(&p3->z, &p3->z); +} + +AffinePoint Ed25519Group::GetAffinePoint(const EcPoint& point) const { + const auto* p3 = CastP3(point); + fe25519 recip; + fe25519 x; + fe25519 y; + + fe25519_invert(&recip, &p3->z); + fe25519_mul(&x, &p3->x, &recip); + fe25519_mul(&y, &p3->y, &recip); + + return {Fe25519ToMPInt(x), Fe25519ToMPInt(y)}; +} + +bool Ed25519Group::IsInCurveGroup(const EcPoint& point) const { + return IsInfinity(point) || ge25519_is_on_curve(CastP3(point)) != 0; +} + +bool Ed25519Group::IsInfinity(const EcPoint& point) const { + static const fe25519 zero = {{0, 0, 0, 0}}; + return fe25519_iseq_vartime(&CastP3(point)->x, &zero) != 0 || + fe25519_iseq_vartime(&CastP3(point)->z, &zero) != 0; +} + +} // namespace yacl::crypto::lib25519 diff --git a/yacl/crypto/ecc/lib25519/ed25519_group.h b/yacl/crypto/ecc/lib25519/ed25519_group.h new file mode 100644 index 00000000..1ed4c20e --- /dev/null +++ b/yacl/crypto/ecc/lib25519/ed25519_group.h @@ -0,0 +1,56 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "yacl/crypto/ecc/lib25519/lib25519_group.h" + +namespace yacl::crypto::lib25519 { + +class Ed25519Group : public Lib25519Group { + public: + Ed25519Group(const CurveMeta& meta, const CurveParam& param); + EcPoint GetGenerator() const override; + + EcPoint Add(const EcPoint& p1, const EcPoint& p2) const override; + void AddInplace(EcPoint* p1, const EcPoint& p2) const override; + + EcPoint Sub(const EcPoint& p1, const EcPoint& p2) const override; + void SubInplace(EcPoint* p1, const EcPoint& p2) const override; + + EcPoint Double(const EcPoint& p) const override; + void DoubleInplace(EcPoint* p) const override; + + EcPoint Mul(const EcPoint& point, const MPInt& scalar) const override; + void MulInplace(EcPoint* point, const MPInt& scalar) const override; + + EcPoint MulBase(const MPInt& scalar) const override; + EcPoint MulDoubleBase(const MPInt& s1, const MPInt& s2, + const EcPoint& p2) const override; + EcPoint Negate(const EcPoint& point) const override; + void NegateInplace(EcPoint* point) const override; + + AffinePoint GetAffinePoint(const EcPoint& point) const override; + + bool IsInCurveGroup(const EcPoint& point) const override; + bool IsInfinity(const EcPoint& point) const override; + + private: + bool MPInt2Scalar(const MPInt& mp, sc25519* scalar) const; + + EcPoint g_; + EcPoint inf_; +}; + +} // namespace yacl::crypto::lib25519 diff --git a/yacl/crypto/ecc/lib25519/ed25519_test.cc b/yacl/crypto/ecc/lib25519/ed25519_test.cc new file mode 100644 index 00000000..318e7667 --- /dev/null +++ b/yacl/crypto/ecc/lib25519/ed25519_test.cc @@ -0,0 +1,131 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "fmt/format.h" +#include "gtest/gtest.h" + +#include "yacl/crypto/ecc/ec_point.h" +#include "yacl/crypto/ecc/ecc_spi.h" +#include "yacl/crypto/ecc/lib25519/ed25519_group.h" +#include "yacl/utils/spi/spi_factory.h" + +namespace yacl::crypto::lib25519 { +extern MPInt Fe25519ToMPInt(const fe25519& x); +void MPIntToFe25519(const MPInt& x, fe25519* out); +} // namespace yacl::crypto::lib25519 + +namespace yacl::crypto::lib25519::test { + +std::ostream& operator<<(std::ostream& os, const EcPoint& p) { + const auto* p3 = + reinterpret_cast(std::get(p).data()); + + return os << fmt::format("[X={}, Y={}, Z={}, T={}]", Fe25519ToMPInt(p3->x), + Fe25519ToMPInt(p3->y), Fe25519ToMPInt(p3->z), + Fe25519ToMPInt(p3->t)); +} + +class Lib25519Test : public ::testing::Test { + protected: + std::unique_ptr ec_ = + EcGroupFactory::Instance().Create("ed25519", ArgLib = "lib25519"); +}; + +TEST_F(Lib25519Test, CopyPointWorks) { + // Convert function + fe25519 f; + MPIntToFe25519(123456789_mp, &f); + EXPECT_EQ(Fe25519ToMPInt(f), 123456789_mp); + + // CopyPoint: ge25519_p3 -> ge25519_p3 + auto ecp1 = ec_->MulBase(852_mp); + auto ecp2 = ec_->CopyPoint(ecp1); + EXPECT_TRUE(ec_->PointEqual(ecp1, ecp2)); + + // check is deep copy + ec_->AddInplace(&ecp1, ec_->GetGenerator()); + EXPECT_FALSE(ec_->PointEqual(ecp1, ecp2)); + + // CopyPoint: affine_point -> ge25519_p3 + auto ap = ec_->GetAffinePoint(ecp1); + EXPECT_TRUE(ec_->PointEqual(ecp1, ec_->CopyPoint(ap))); + + // TODO: compressed point -> ge25519_p3 +} + +TEST_F(Lib25519Test, AffinePointWorks) { + ASSERT_EQ(ec_->GetLibraryName(), "lib25519"); + + AffinePoint ap_g{ + "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"_mp, + "0x6666666666666666666666666666666666666666666666666666666666666658"_mp}; + auto g = ec_->GetAffinePoint(ec_->GetGenerator()); + EXPECT_EQ(ap_g, g); + + EcPoint new_g = ec_->CopyPoint(ap_g); + EXPECT_TRUE(ec_->PointEqual(new_g, ec_->GetGenerator())); + + auto inf = ec_->GetAffinePoint(ec_->MulBase(0_mp)); + EXPECT_TRUE(ec_->PointEqual(ec_->CopyPoint(inf), ec_->MulBase(0_mp))); + + auto any_p = ec_->MulBase(123456_mp); + auto any_ap = ec_->GetAffinePoint(any_p); + EXPECT_TRUE(ec_->PointEqual(ec_->CopyPoint(any_ap), any_p)); +} + +TEST_F(Lib25519Test, InfWorks) { + auto g = ec_->GetGenerator(); + EXPECT_TRUE(ec_->IsInCurveGroup(g)); + + auto inf = ec_->MulBase(0_mp); + auto inf2 = ec_->CopyPoint(inf); + EXPECT_TRUE(ec_->PointEqual(inf, inf2)); + EXPECT_FALSE(ec_->PointEqual(inf, g)); + EXPECT_TRUE(ec_->IsInfinity(inf2)); + EXPECT_TRUE(ec_->IsInCurveGroup(inf2)); + + ec_->AddInplace(&inf, ec_->GetGenerator()); + EXPECT_FALSE(ec_->PointEqual(inf, inf2)); + EXPECT_TRUE(ec_->PointEqual(inf, g)); + + inf = ec_->MulBase(0_mp); + inf2 = ec_->CopyPoint(AffinePoint(0_mp, 1_mp)); + EXPECT_EQ(ec_->HashPoint(inf), ec_->HashPoint(inf2)); + EXPECT_TRUE(ec_->PointEqual(inf, inf2)); +} + +TEST_F(Lib25519Test, NegateWorks) { + // simple works + auto g = ec_->MulBase(1_mp); + EXPECT_TRUE(ec_->PointEqual(g, ec_->GetGenerator())); + auto g2 = ec_->MulBase(2_mp); + EXPECT_TRUE(ec_->PointEqual(g2, ec_->Add(g, g))); + + EcPoint ng = ec_->Negate(ec_->GetGenerator()); + EXPECT_TRUE(ec_->PointEqual(ng, ec_->MulBase(-1_mp))); + EXPECT_TRUE(ec_->PointEqual(ng, ec_->Sub(g, g2))); + auto inf = ec_->Add(ng, ec_->GetGenerator()); + EXPECT_TRUE(ec_->IsInfinity(inf)); + ec_->NegateInplace(&inf); + EXPECT_TRUE(ec_->IsInfinity(inf)); + + EXPECT_TRUE(ec_->PointEqual(ec_->MulBase(-2_mp), ec_->Add(ng, ng))); + EXPECT_TRUE(ec_->PointEqual(ec_->MulBase(-1000_mp), + ec_->Negate(ec_->MulBase(1000_mp)))); +} + +} // namespace yacl::crypto::lib25519::test diff --git a/yacl/crypto/ecc/lib25519/lib25519_factory.cc b/yacl/crypto/ecc/lib25519/lib25519_factory.cc new file mode 100644 index 00000000..e4327e0a --- /dev/null +++ b/yacl/crypto/ecc/lib25519/lib25519_factory.cc @@ -0,0 +1,52 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "yacl/crypto/ecc/lib25519/ed25519_group.h" + +namespace yacl::crypto::lib25519 { + +namespace { +const std::string kLibName = "lib25519"; + +std::map kPredefinedCurves = { + {"ed25519", + { + (2_mp).Pow(255) - 19_mp, // p = 2^255 - 19 + (2_mp).Pow(252) + "0x14def9dea2f79cd65812631a5cf5d3ed"_mp, // n + "8"_mp // h + }}}; + +std::unique_ptr Create(const CurveMeta &meta) { + YACL_ENFORCE(kPredefinedCurves.count(meta.LowerName()) > 0, + "curve {} not supported", meta.name); + auto conf = kPredefinedCurves.at(meta.LowerName()); + + if (meta.LowerName() == "ed25519") { + return std::make_unique(meta, conf); + } else { + YACL_THROW("unexpected curve {}", meta.name); + } +} + +bool IsSupported(const CurveMeta &meta) { + return kPredefinedCurves.count(meta.LowerName()) > 0; +} + +REGISTER_EC_LIBRARY(kLibName, 1000, IsSupported, Create); + +} // namespace + +std::string Lib25519Group::GetLibraryName() const { return kLibName; } + +} // namespace yacl::crypto::lib25519 diff --git a/yacl/crypto/ecc/lib25519/lib25519_group.cc b/yacl/crypto/ecc/lib25519/lib25519_group.cc new file mode 100644 index 00000000..46712a1a --- /dev/null +++ b/yacl/crypto/ecc/lib25519/lib25519_group.cc @@ -0,0 +1,173 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "yacl/crypto/ecc/lib25519/lib25519_group.h" + +namespace yacl::crypto::lib25519 { + +void MPIntToFe25519(const MPInt& x, fe25519* out) { + Array32 buf; + memset(buf.data(), 0, sizeof(buf)); + x.ToMagBytes(buf.data(), buf.size(), Endian::little); + fe25519_unpack(out, buf.data()); +} + +Lib25519Group::Lib25519Group(CurveMeta meta, CurveParam param) + : EcGroupSketch(std::move(meta)), param_(std::move(param)) { + static_assert(sizeof(ge25519_p3) <= sizeof(Array128)); +} + +MPInt Lib25519Group::GetCofactor() const { return param_.h; } + +MPInt Lib25519Group::GetField() const { return param_.p; } + +MPInt Lib25519Group::GetOrder() const { return param_.n; } + +std::string Lib25519Group::ToString() const { + return fmt::format("Curve {} from {}", GetCurveName(), GetLibraryName()); +} + +EcPoint Lib25519Group::CopyPoint(const EcPoint& point) const { + if (std::holds_alternative(point)) { + return point; + } + + if (std::holds_alternative(point)) { + // Convert affine_point to ge25519_p3 + AffinePoint p = std::get(point); + EcPoint r(std::in_place_type); + auto* p3 = CastP3(r); + // ge25519_p3: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT + MPIntToFe25519(p.x, &p3->x); + MPIntToFe25519(p.y, &p3->y); + fe25519_setint(&p3->z, 1); + fe25519_mul(&p3->t, &p3->x, &p3->y); + YACL_ENFORCE(IsInCurveGroup(r), "Illegal affine point {}, not in ec group", + p); + return r; + } + + // TODO: if (std::holds_alternative(point)) ... + + YACL_THROW("Unsupported EcPoint type {}", point.index()); +} + +uint64_t Lib25519Group::GetSerializeLength(PointOctetFormat format) const { + YACL_ENFORCE(format == PointOctetFormat::Autonomous, + "{} only support Autonomous format, given={}", GetLibraryName(), + (int)format); + return 32; +} + +Buffer Lib25519Group::SerializePoint(const EcPoint& point, + PointOctetFormat format) const { + YACL_ENFORCE(format == PointOctetFormat::Autonomous, + "{} only support Autonomous format, given={}", GetLibraryName(), + (int)format); + + Buffer buf(32); + ge25519_pack(buf.data(), CastP3(point)); + return buf; +} + +void Lib25519Group::SerializePoint(const EcPoint& point, + PointOctetFormat format, Buffer* buf) const { + *buf = SerializePoint(point, format); +} + +void Lib25519Group::SerializePoint(const EcPoint& point, + PointOctetFormat format, uint8_t* buf, + uint64_t buf_size) const { + YACL_ENFORCE(format == PointOctetFormat::Autonomous, + "{} only support Autonomous format, given={}", GetLibraryName(), + (int)format); + YACL_ENFORCE(buf_size >= 32, "buf size is small than needed 32"); + ge25519_pack(buf, CastP3(point)); +} + +EcPoint Lib25519Group::DeserializePoint(ByteContainerView buf, + PointOctetFormat format) const { + YACL_ENFORCE(format == PointOctetFormat::Autonomous, + "{} only support Autonomous format, given={}", GetLibraryName(), + (int)format); + + EcPoint p(std::in_place_type); + YACL_ENFORCE(ge25519_unpack_vartime(CastP3(p), buf.data()) == 1, + "deserialize point failed"); + + return p; +} + +EcPoint Lib25519Group::HashToCurve(HashToCurveStrategy, + std::string_view) const { + YACL_THROW("not implemented"); +} + +size_t Lib25519Group::HashPoint(const EcPoint& point) const { + const auto* p3 = CastP3(point); + fe25519 recip; + fe25519 x; + + fe25519_invert(&recip, &p3->z); + fe25519_mul(&x, &p3->x, &recip); + + uint64_t buf[4]; // x is always 255 bits + fe25519_pack(reinterpret_cast(buf), &x); + + std::hash h; + return h(buf[0]) ^ h(buf[1]) ^ h(buf[2]) ^ h(buf[3]); +} + +bool Lib25519Group::PointEqual(const EcPoint& p1, const EcPoint& p2) const { + if (IsInfinity(p1) && IsInfinity(p2)) { + return true; + } + + const auto* p1p = CastP3(p1); + const auto* p2p = CastP3(p2); + + // p1 = (X1/Z1, Y1/Z1) = ((X1*Z2)/(Z1*Z2), (Y1*Z2)/(Z1*Z2)); + // P2 = (X2/Z2, Y2/Z2) = ((Z1*X2)/(Z1*Z2), (Z1*Y2)/(Z1*Z2)); + fe25519 a; + fe25519 b; + fe25519_mul(&a, &p1p->x, &p2p->z); + fe25519_mul(&b, &p1p->z, &p2p->x); + for (size_t i = 0; i < sizeof(fe25519) / sizeof(a.v[0]); ++i) { + if (a.v[i] != b.v[i]) { + return false; + } + } + + fe25519_mul(&a, &p1p->y, &p2p->z); + fe25519_mul(&b, &p1p->z, &p2p->y); + uint128_t buf_a[2]; + uint128_t buf_b[2]; + fe25519_pack(reinterpret_cast(buf_a), &a); + fe25519_pack(reinterpret_cast(buf_b), &b); + return buf_a[0] == buf_b[0] && buf_a[1] == buf_b[1]; +} + +const ge25519_p3* Lib25519Group::CastP3(const yacl::crypto::EcPoint& p) { + YACL_ENFORCE(std::holds_alternative(p), + "Illegal EcPoint, expected Array128, real={}", p.index()); + return reinterpret_cast(std::get(p).data()); +} + +ge25519_p3* Lib25519Group::CastP3(EcPoint& p) { + YACL_ENFORCE(std::holds_alternative(p), + "Illegal EcPoint, expected Array128, real={}", p.index()); + return reinterpret_cast(std::get(p).data()); +} + +} // namespace yacl::crypto::lib25519 diff --git a/yacl/crypto/ecc/lib25519/lib25519_group.h b/yacl/crypto/ecc/lib25519/lib25519_group.h new file mode 100644 index 00000000..c28f3f24 --- /dev/null +++ b/yacl/crypto/ecc/lib25519/lib25519_group.h @@ -0,0 +1,70 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "yacl/crypto/ecc/ec_point.h" +#include "yacl/crypto/ecc/group_sketch.h" +#include "yacl/crypto/ecc/lib25519/lib25519_private.h" + +namespace yacl::crypto::lib25519 { + +struct CurveParam { + MPInt p; + MPInt n; + MPInt h; + +#if __cplusplus >= 202002L +#else + CurveParam() = default; +#endif +}; + +class Lib25519Group : public EcGroupSketch { + public: + explicit Lib25519Group(CurveMeta curve_meta, CurveParam param); + std::string GetLibraryName() const override; + + MPInt GetCofactor() const override; + MPInt GetField() const override; + MPInt GetOrder() const override; + std::string ToString() const override; + + EcPoint CopyPoint(const EcPoint& point) const override; + + uint64_t GetSerializeLength(PointOctetFormat format) const override; + + Buffer SerializePoint(const EcPoint& point, + PointOctetFormat format) const override; + void SerializePoint(const EcPoint& point, PointOctetFormat format, + Buffer* buf) const override; + void SerializePoint(const EcPoint& point, PointOctetFormat format, + uint8_t* buf, uint64_t buf_size) const override; + EcPoint DeserializePoint(ByteContainerView buf, + PointOctetFormat format) const override; + + EcPoint HashToCurve(HashToCurveStrategy strategy, + std::string_view str) const override; + + size_t HashPoint(const EcPoint& point) const override; + bool PointEqual(const EcPoint& p1, const EcPoint& p2) const override; + + protected: + static const ge25519_p3* CastP3(const EcPoint& p); + static ge25519_p3* CastP3(EcPoint& p); + + CurveParam param_; +}; + +} // namespace yacl::crypto::lib25519 diff --git a/yacl/crypto/ecc/lib25519/lib25519_private.h b/yacl/crypto/ecc/lib25519/lib25519_private.h new file mode 100644 index 00000000..b016b61a --- /dev/null +++ b/yacl/crypto/ecc/lib25519/lib25519_private.h @@ -0,0 +1,23 @@ +// Copyright 2024 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +extern "C" { +#include "crypto_multiscalar/ed25519/amd64-maax-p3/ge25519_unpack.h" +#include "crypto_nG/merged25519/amd64-maax/ge25519.h" +#include "include-build/ge25519_is_on_curve.h" +#include "include-build/ge25519_scalarmult.h" +#include "include-build/ge25519_sub.h" +}; diff --git a/yacl/crypto/ecc/mcl/BUILD.bazel b/yacl/crypto/ecc/mcl/BUILD.bazel index 5d5de5fa..132f872e 100644 --- a/yacl/crypto/ecc/mcl/BUILD.bazel +++ b/yacl/crypto/ecc/mcl/BUILD.bazel @@ -28,7 +28,7 @@ yacl_cc_library( "//yacl/crypto/ecc:spi", "//yacl/crypto/hash:blake3", "//yacl/crypto/hash:ssl_hash", - "//yacl/crypto/pairing/mcl:pairing_header", + "//yacl/crypto/pairing/factory:mcl_pairing_header", ], alwayslink = 1, ) diff --git a/yacl/crypto/ecc/mcl/mcl_ec_factory.cc b/yacl/crypto/ecc/mcl/mcl_ec_factory.cc index b9cf14e9..1d94158e 100644 --- a/yacl/crypto/ecc/mcl/mcl_ec_factory.cc +++ b/yacl/crypto/ecc/mcl/mcl_ec_factory.cc @@ -14,7 +14,7 @@ #include "yacl/crypto/ecc/mcl/mcl_ec_group.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { std::map Name2MclCurveEnum = { {"secp192k1", MCL_SECP192K1}, @@ -66,4 +66,4 @@ bool MclEGFactory::IsSupported(const CurveMeta& meta) { REGISTER_EC_LIBRARY(kLibName, 400, MclEGFactory::IsSupported, MclEGFactory::Create); -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/ecc/mcl/mcl_ec_group.cc b/yacl/crypto/ecc/mcl/mcl_ec_group.cc index 50564e5b..49a31ca0 100644 --- a/yacl/crypto/ecc/mcl/mcl_ec_group.cc +++ b/yacl/crypto/ecc/mcl/mcl_ec_group.cc @@ -16,14 +16,16 @@ #include "yacl/crypto/ecc/mcl/mcl_util.h" #include "yacl/crypto/hash/blake3.h" -#include "yacl/crypto/pairing/mcl/pairing_header.h" +#include "yacl/crypto/pairing/factory/mcl_pairing_header.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { template MclGroupT::MclGroupT(const CurveMeta& meta, int mcl_curve_type, - const EcPoint& generator) - : EcGroupSketch(meta), mcl_curve_type_(mcl_curve_type) { + const EcPoint& generator, bool const_time_mul) + : EcGroupSketch(meta), + mcl_curve_type_(mcl_curve_type), + const_time_(const_time_mul) { order_ = Mpz2Mp(Zn_::BaseFp::getOp().mp); // Note that order of extension field != field's Modulus, so it's // meaningless for high-level computation. @@ -90,9 +92,11 @@ template EcPoint MclGroupT::MulBase(const MPInt& scalar) const { auto ret = MakeShared(); if (!const_time_) { - Ec::mul(*CastAny(ret), *CastAny(GetGenerator()), Mp2Mpz(scalar)); + Ec::mul(*CastAny(ret), *CastAny(GetGenerator()), + Mp2Mpz(scalar % order_)); } else { - Ec::mulCT(*CastAny(ret), *CastAny(GetGenerator()), Mp2Mpz(scalar)); + Ec::mulCT(*CastAny(ret), *CastAny(GetGenerator()), + Mp2Mpz(scalar % order_)); } return ret; } @@ -102,9 +106,9 @@ EcPoint MclGroupT::Mul(const EcPoint& point, const MPInt& scalar) const { auto ret = MakeShared(); if (!const_time_) { - Ec::mul(*CastAny(ret), *CastAny(point), Mp2Mpz(scalar)); + Ec::mul(*CastAny(ret), *CastAny(point), Mp2Mpz(scalar % order_)); } else { - Ec::mulCT(*CastAny(ret), *CastAny(point), Mp2Mpz(scalar)); + Ec::mulCT(*CastAny(ret), *CastAny(point), Mp2Mpz(scalar % order_)); } return ret; } @@ -113,9 +117,10 @@ template void MclGroupT::MulInplace(EcPoint* point, const MPInt& scalar) const { if (!const_time_) { - Ec::mul(*CastAny(point), *CastAny(point), Mp2Mpz(scalar)); + Ec::mul(*CastAny(point), *CastAny(point), Mp2Mpz(scalar % order_)); } else { - Ec::mulCT(*CastAny(point), *CastAny(point), Mp2Mpz(scalar)); + Ec::mulCT(*CastAny(point), *CastAny(point), + Mp2Mpz(scalar % order_)); } } @@ -123,22 +128,12 @@ template EcPoint MclGroupT::MulDoubleBase(const MPInt& s1, const MPInt& s2, const EcPoint& p2) const { auto ret = MakeShared(); - auto mp = Zn_::BaseFp::getOp().mp; - - auto scalar1 = Mp2Mpz(s1); + auto scalar1 = Mp2Mpz(s1 % order_); Fr ps1; - scalar1 %= mp; - if (scalar1.isNegative()) { - scalar1 += mp; - } ps1.setMpz(scalar1); - auto scalar2 = Mp2Mpz(s2); + auto scalar2 = Mp2Mpz(s2 % order_); Fr ps2; - scalar2 %= mp; - if (scalar2.isNegative()) { - scalar2 += mp; - } ps2.setMpz(scalar2); Ec ecs[] = {*CastAny(GetGenerator()), *CastAny(p2)}; @@ -161,9 +156,18 @@ void MclGroupT::NegateInplace(EcPoint* point) const { template EcPoint MclGroupT::CopyPoint(const EcPoint& point) const { - auto ret = MakeShared(); - *CastAny(ret) = *CastAny(point); - return ret; + if (std::holds_alternative(point)) { + auto ret = MakeShared(); + *CastAny(ret) = *CastAny(point); + return ret; + } + + if (std::holds_alternative(point)) { + auto p = std::get(point); + return GetMclPoint(p); + } + + YACL_THROW("Unsupported EcPoint type {}", point.index()); } template @@ -184,15 +188,21 @@ AnyPtr MclGroupT::GetMclPoint(const AffinePoint& p) const { template uint64_t MclGroupT::GetSerializeLength( PointOctetFormat format) const { + if (mcl_curve_type_ == MCL_BLS12_381 && + (format == PointOctetFormat::ZCash_BLS12_381 || + format == PointOctetFormat::Autonomous)) { + return Ec::getSerializedByteSize(); + } + switch (format) { case PointOctetFormat::X962Uncompressed: case PointOctetFormat::X962Hybrid: { + // 1 more byte for being compatible with x962 format return Fp_::getByteSize() * 2 + 1; } case PointOctetFormat::Autonomous: - case PointOctetFormat::X962Compressed: - case PointOctetFormat::ZCash_BLS12_381: { - return Ec::getSerializedByteSize(); + case PointOctetFormat::X962Compressed: { + return Fp_::getByteSize() + 1; } default: YACL_THROW("Not supported serialize format for standard curve in {}", @@ -217,6 +227,23 @@ void MclGroupT::SerializePoint(const EcPoint& point, SerializePoint(point, format, buf->data(), buf->size()); } +// Compressed Serialization Process: +// IoEcCompY Mode +// 1-bit y prepresentation of elliptic curve +// "2 " ; compressed for even y +// "3 " ; compressed for odd y +// IoSerialize Mode +// if isMSBserialize(): // p is not full bit +// size = Fp::getByteSize() +// use MSB of array of x for 1-bit y for prime p where (p % 8 != 0) +// [0] ; infinity +// ; for even y +// |1 ; for odd y ; |1 means set MSB of x +// else:// x962 compressed format +// size = Fp::getByteSize() + 1 +// [0] ; infinity +// 2 ; for even y +// 3 ; for odd y template void MclGroupT::SerializePoint(const EcPoint& point, PointOctetFormat format, uint8_t* buf, @@ -227,8 +254,9 @@ void MclGroupT::SerializePoint(const EcPoint& point, const Ec& p = *CastAny(point); int write_bits = 0; - // For pairing curve - if (mcl_curve_type_ < MCL_BN_P256) { + if (mcl_curve_type_ == MCL_BLS12_381) { + // pairing curve MCL_BLS12_381, use ZCash_BLS12_381 serialization mode, + // which is Big Endian. switch (format) { case PointOctetFormat::Autonomous: case PointOctetFormat::ZCash_BLS12_381: { @@ -241,86 +269,114 @@ void MclGroupT::SerializePoint(const EcPoint& point, YACL_THROW("Not supported serialize format for pairing curve in {}", kLibName); } - } else { - // For Std curves - switch (format) { - case PointOctetFormat::X962Uncompressed: { - // for ANSI X9.62 uncompressed format - buf[0] = 0x04; - // but only x||y, not z=0x04||x||y - write_bits = - p.serialize(buf + 1, len - 1, mcl::IoMode::IoEcAffineSerialize); - YACL_ENFORCE(len == static_cast(write_bits + 1), - "Serialize error!"); - break; + return; + } + + switch (format) { + case PointOctetFormat::X962Uncompressed: { + // for ANSI X9.62 uncompressed format + buf[0] = 0x04; + // mcl uncompressed serialization is only x||y, not z=0x04||x||y + write_bits = + p.serialize(buf + 1, len - 1, mcl::IoMode::IoEcAffineSerialize); + YACL_ENFORCE(len == static_cast(write_bits + 1), + "Serialize error!"); + break; + } + case PointOctetFormat::X962Hybrid: { + // for ANSI X9.62 hybrid format + Ec ecp = Ec(p); + // Check is normalized for affine coordinates + if (!ecp.isNormalized()) { + ecp.normalize(); } - case PointOctetFormat::X962Hybrid: { - // for ANSI X9.62 hybrid format - buf[0] = (p.y.isOdd() ? 0x06 : 0x07); - // but only x||y, not z=0x04||x||y + buf[0] = (ecp.y.isOdd() ? 7 : 6); + write_bits = + ecp.serialize(buf + 1, len - 1, mcl::IoMode::IoEcAffineSerialize); + YACL_ENFORCE(len == static_cast(write_bits + 1), + "Serialize error!"); + break; + } + case PointOctetFormat::Autonomous: + case PointOctetFormat::X962Compressed: { + if (p.isZero()) { + std::memset(buf + write_bits, 0, len); + write_bits = len; + } else { + Ec ecp = Ec(p); + // Check is normalized for affine coordinates + if (!ecp.isNormalized()) { + ecp.normalize(); + } + buf[0] = ecp.y.isOdd() ? 3 : 2; write_bits = - p.serialize(buf + 1, len - 1, mcl::IoMode::IoEcAffineSerialize); + ecp.x.serialize(buf + 1, buf_size - 1, mcl::IoMode::IoSerialize); YACL_ENFORCE(len == static_cast(write_bits + 1), "Serialize error!"); - break; - } - case PointOctetFormat::Autonomous: - case PointOctetFormat::X962Compressed: { - write_bits = p.serialize(buf, len, mcl::IoMode::IoSerialize); - YACL_ENFORCE(len == static_cast(write_bits), - "Serialize error!"); - break; } - default: - YACL_THROW("Not supported serialize format for standard curve in {}", - kLibName); + break; } + default: + YACL_THROW("Not supported serialize format for curve in {}", kLibName); } if (buf_size > len) { - std::memset(buf + write_bits, 0, buf_size - len); + std::memset(buf + write_bits, 0, buf_size - write_bits); } } template EcPoint MclGroupT::DeserializePoint(ByteContainerView buf, PointOctetFormat format) const { + const auto len = GetSerializeLength(format); + YACL_ENFORCE(buf.size() >= len); auto ret = MakeShared(); - // For pairing curve - if (mcl_curve_type_ < MCL_BN_P256) { + + if (mcl_curve_type_ == MCL_BLS12_381) { + // pairing curve MCL_BLS12_381, use ZCash_BLS12_381 serialization mode, + // which is Big Endian. switch (format) { case PointOctetFormat::Autonomous: case PointOctetFormat::ZCash_BLS12_381: { - // BaseFp::setETHserialization(true); // big endian - CastAny(ret)->deserialize(buf.begin(), buf.size(), + CastAny(ret)->deserialize(buf.cbegin(), len, mcl::IoMode::IoSerialize); - // BaseFp::setETHserialization(false); break; } default: - YACL_THROW("Not supported serialize format for pairing curve in {}", + YACL_THROW("Not supported deserialize format for pairing curve in {}", kLibName); } - } else { - // For Std curves - switch (format) { - case PointOctetFormat::X962Uncompressed: - CastAny(ret)->deserialize(buf.begin() + 1, buf.size() - 1, - mcl::IoMode::IoEcAffineSerialize); - break; - case PointOctetFormat::X962Hybrid: - CastAny(ret)->deserialize(buf.begin() + 1, buf.size() - 1, - mcl::IoMode::IoEcAffineSerialize); - break; - case PointOctetFormat::Autonomous: - case PointOctetFormat::X962Compressed: - CastAny(ret)->deserialize(buf.begin(), buf.size(), - mcl::IoMode::IoSerialize); - break; - default: - YACL_THROW("Not supported serialize format for standard curve in {}", - kLibName); + return ret; + } + + switch (format) { + case PointOctetFormat::X962Uncompressed: + YACL_ENFORCE(buf[0] == 0x04); + CastAny(ret)->deserialize(buf.cbegin() + 1, len - 1, + mcl::IoMode::IoEcAffineSerialize); + break; + case PointOctetFormat::X962Hybrid: + YACL_ENFORCE(buf[0] == 0x06 || buf[0] == 0x07); + CastAny(ret)->deserialize(buf.cbegin() + 1, len - 1, + mcl::IoMode::IoEcAffineSerialize); + break; + case PointOctetFormat::Autonomous: + case PointOctetFormat::X962Compressed: { + auto* p = CastAny(ret); + p->z = 1; + if (mcl::bint::isZeroN(buf.cbegin(), len)) { + p->clear(); + } else { + bool isYodd = buf[0] == 3; + p->x.deserialize(buf.cbegin() + 1, len - 1, mcl::IoMode::IoSerialize); + YACL_ENFORCE(Ec::getYfromX(p->y, p->x, isYodd)); + } + break; } + default: + YACL_THROW("Not supported deserialize format for standard curve in {}", + kLibName); } + return ret; } @@ -390,10 +446,17 @@ EcPoint MclGroupT::HashToCurve(HashToCurveStrategy strategy, } } +// PointEqual 1013ns +// this 3027 ns +// TODO: slow! template -size_t MclGroupT::HashPoint( - [[maybe_unused]] const EcPoint& point) const { - YACL_THROW("Not impl!"); +size_t MclGroupT::HashPoint(const EcPoint& point) const { + Ec ecp = Ec(*CastAny(point)); + // Check is normalized for affine coordinates + if (!ecp.isNormalized()) { + ecp.normalize(); + } + return size_t(*(ecp.x.getUnit())) + ecp.y.isOdd(); } template @@ -423,7 +486,7 @@ AffinePoint MclGroupT::GetAffinePoint(const EcPoint& point) const { if (IsInfinity(point)) { return {}; } - Ec ecp = *CastAny(point); + Ec ecp = Ec(*CastAny(point)); // Check is normalized for affine coordinates if (!ecp.isNormalized()) { ecp.normalize(); @@ -470,17 +533,17 @@ TEMPLATE_NIST_INSTANCE(256) // Pairing Classes TEMPLATE_CURVE_INSTANCE(bls12); +TEMPLATE_CURVE_INSTANCE(bnsnark); #ifdef MCL_ALL_PAIRING_FOR_YACL TEMPLATE_CURVE_INSTANCE(bn254); TEMPLATE_CURVE_INSTANCE(bn382m); TEMPLATE_CURVE_INSTANCE(bn382r); TEMPLATE_CURVE_INSTANCE(bn462); -TEMPLATE_CURVE_INSTANCE(bnsnark); TEMPLATE_CURVE_INSTANCE(bn160); TEMPLATE_CURVE_INSTANCE(bls123); TEMPLATE_CURVE_INSTANCE(bls124); TEMPLATE_CURVE_INSTANCE(bn256); #endif -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/ecc/mcl/mcl_ec_group.h b/yacl/crypto/ecc/mcl/mcl_ec_group.h index d8314089..c5dd57bd 100644 --- a/yacl/crypto/ecc/mcl/mcl_ec_group.h +++ b/yacl/crypto/ecc/mcl/mcl_ec_group.h @@ -20,7 +20,7 @@ #include "yacl/crypto/hash/ssl_hash.h" // hmcl = herumi_mcl -namespace yacl::crypto::hmcl { +namespace yacl::crypto { const std::string kLibName = "libmcl"; @@ -92,7 +92,7 @@ class MclGroupT : public EcGroupSketch { private: explicit MclGroupT(const CurveMeta& meta, int mcl_curve_type, - const EcPoint& generator); + const EcPoint& generator, bool const_time_mul = false); // For standard hash to curve EcPoint HashToStdCurve(HashToCurveStrategy strategy, @@ -146,4 +146,4 @@ MCL_CURVE_NIST_ALIAS(192) MCL_CURVE_NIST_ALIAS(224) MCL_CURVE_NIST_ALIAS(256) -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/ecc/mcl/mcl_ec_test.cc b/yacl/crypto/ecc/mcl/mcl_ec_test.cc index 7f246c4b..e4706063 100644 --- a/yacl/crypto/ecc/mcl/mcl_ec_test.cc +++ b/yacl/crypto/ecc/mcl/mcl_ec_test.cc @@ -16,12 +16,12 @@ #include "yacl/crypto/ecc/mcl/mcl_ec_group.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { // for test extern std::map Name2MclCurveEnum; -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto -namespace yacl::crypto::hmcl::test { +namespace yacl::crypto::test { TEST(MclTest, MclWorks) { // Curve Instances ok @@ -108,4 +108,4 @@ TEST(MclTest, HashToCurveWorks) { } } -} // namespace yacl::crypto::hmcl::test +} // namespace yacl::crypto::test diff --git a/yacl/crypto/ecc/mcl/mcl_util.cc b/yacl/crypto/ecc/mcl/mcl_util.cc index f0ecd83a..219883a8 100644 --- a/yacl/crypto/ecc/mcl/mcl_util.cc +++ b/yacl/crypto/ecc/mcl/mcl_util.cc @@ -16,7 +16,7 @@ #include "mcl/gmp_util.hpp" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { MPInt Mpz2Mp(const mpz_class& m) { const auto* ptr = @@ -43,4 +43,4 @@ mpz_class Mp2Mpz(const MPInt& mpi) { return ret; } -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/ecc/mcl/mcl_util.h b/yacl/crypto/ecc/mcl/mcl_util.h index 5a234f2e..e10396d4 100644 --- a/yacl/crypto/ecc/mcl/mcl_util.h +++ b/yacl/crypto/ecc/mcl/mcl_util.h @@ -18,11 +18,11 @@ #include "yacl/math/mpint/mp_int.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { using yacl::math::MPInt; MPInt Mpz2Mp(const mpz_class& m); mpz_class Mp2Mpz(const MPInt& mpi); -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/ecc/mcl/mcl_util_test.cc b/yacl/crypto/ecc/mcl/mcl_util_test.cc index e3499386..fd2c85ca 100644 --- a/yacl/crypto/ecc/mcl/mcl_util_test.cc +++ b/yacl/crypto/ecc/mcl/mcl_util_test.cc @@ -16,7 +16,7 @@ #include "gtest/gtest.h" -namespace yacl::crypto::hmcl::test { +namespace yacl::crypto::test { TEST(MclFieldTest, MclUtilWorks) { // small case @@ -48,4 +48,4 @@ TEST(MclFieldTest, MclUtilWorks) { ASSERT_EQ(out, in); } } -} // namespace yacl::crypto::hmcl::test +} // namespace yacl::crypto::test diff --git a/yacl/crypto/pairing/BUILD.bazel b/yacl/crypto/pairing/BUILD.bazel index 8f806d63..16e7ad8a 100644 --- a/yacl/crypto/pairing/BUILD.bazel +++ b/yacl/crypto/pairing/BUILD.bazel @@ -14,26 +14,38 @@ load("//bazel:yacl.bzl", "yacl_cc_library", "yacl_cc_test") -package(default_visibility = ["//visibility:public"]) - yacl_cc_library( name = "pairing", + visibility = ["//visibility:public"], deps = [ - "//yacl/crypto/pairing/mcl:pairing", + ":pairing_interface", + "//yacl/crypto/pairing/factory:mcl_factory", ], ) yacl_cc_library( - name = "pairing_spi", - srcs = ["pairing_spi.cc"], - hdrs = ["pairing_spi.h"], + name = "pairing_interface", + hdrs = ["pairing.h"], + visibility = ["//yacl/crypto/pairing/factory:__pkg__"], # grant visibility to factory deps = [ "//yacl/crypto/ecc:spi", - "//yacl/math/galois_field:spi", + "//yacl/math/galois_field:gf", + "//yacl/utils/spi", "@com_google_absl//absl/strings", ], ) +# yacl_cc_library( +# name = "pairing_spi", +# srcs = ["pairing_spi.cc"], +# hdrs = ["pairing_spi.h"], +# deps = [ +# "//yacl/crypto/ecc:spi", +# "//yacl/math/galois_field:gf", +# "@com_google_absl//absl/strings", +# ], +# ) + yacl_cc_test( name = "pairing_test", srcs = ["pairing_test.cc"], diff --git a/yacl/crypto/pairing/mcl/BUILD.bazel b/yacl/crypto/pairing/factory/BUILD.bazel similarity index 73% rename from yacl/crypto/pairing/mcl/BUILD.bazel rename to yacl/crypto/pairing/factory/BUILD.bazel index 2a1fdee2..8bc77f87 100644 --- a/yacl/crypto/pairing/mcl/BUILD.bazel +++ b/yacl/crypto/pairing/factory/BUILD.bazel @@ -18,8 +18,17 @@ load("@bazel_skylib//lib:selects.bzl", "selects") package(default_visibility = ["//visibility:public"]) yacl_cc_library( - name = "pairing_header", - hdrs = ["pairing_header.h"], + name = "spi", + srcs = ["pairing_spi.cc"], + hdrs = ["pairing_spi.h"], + deps = [ + "//yacl/crypto/pairing:pairing_interface", + ], +) + +yacl_cc_library( + name = "mcl_pairing_header", + hdrs = ["mcl_pairing_header.h"], copts = [ ], defines = selects.with_or({ @@ -35,30 +44,30 @@ yacl_cc_library( ) yacl_cc_library( - name = "pairing", + name = "mcl_factory", srcs = [ - "mcl_pairing_bls12_381.cc", - "mcl_pairing_bls12_381.h", - "mcl_pairing_factory.cc", + "mcl_bls12_381.cc", + "mcl_bls12_381.h", + "mcl_factory.cc", "mcl_pairing_group.cc", ], hdrs = [ "mcl_pairing_group.h", ], deps = [ - ":pairing_header", + ":mcl_pairing_header", + ":spi", "//yacl/crypto/ecc", - "//yacl/crypto/pairing:pairing_spi", - "//yacl/math/galois_field/mcl_field:field", + "//yacl/math/galois_field/factory:mcl_factory", ], alwayslink = 1, ) yacl_cc_test( - name = "pairing_test", - srcs = ["mcl_pairing_test.cc"], + name = "mcl_factory_test", + srcs = ["mcl_factory_test.cc"], deps = [ - ":pairing", + ":mcl_factory", "//yacl/crypto/rand", ], ) diff --git a/yacl/crypto/pairing/mcl/mcl_pairing_bls12_381.cc b/yacl/crypto/pairing/factory/mcl_bls12_381.cc similarity index 95% rename from yacl/crypto/pairing/mcl/mcl_pairing_bls12_381.cc rename to yacl/crypto/pairing/factory/mcl_bls12_381.cc index 69adf1bd..96e4293d 100644 --- a/yacl/crypto/pairing/mcl/mcl_pairing_bls12_381.cc +++ b/yacl/crypto/pairing/factory/mcl_bls12_381.cc @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/crypto/pairing/mcl/mcl_pairing_bls12_381.h" +#include "yacl/crypto/pairing/factory/mcl_bls12_381.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { MclPairingBls12381::MclPairingBls12381(const PairingMeta& meta, std::unique_ptr& g1, @@ -71,4 +71,4 @@ GtElement MclPairingBls12381::Pairing(const EcPoint& group1_point, return ret; } -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/pairing/mcl/mcl_pairing_bls12_381.h b/yacl/crypto/pairing/factory/mcl_bls12_381.h similarity index 89% rename from yacl/crypto/pairing/mcl/mcl_pairing_bls12_381.h rename to yacl/crypto/pairing/factory/mcl_bls12_381.h index a1e29600..ff1a5b60 100644 --- a/yacl/crypto/pairing/mcl/mcl_pairing_bls12_381.h +++ b/yacl/crypto/pairing/factory/mcl_bls12_381.h @@ -17,14 +17,14 @@ #include "mcl/bls12_381.hpp" #include "yacl/crypto/ecc/mcl/mcl_ec_group.h" -#include "yacl/crypto/pairing/pairing_spi.h" -#include "yacl/math/galois_field/mcl_field/mcl_field.h" +#include "yacl/crypto/pairing/factory/pairing_spi.h" +#include "yacl/math/galois_field/factory/mcl_factory.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { using MclPairingBls12381G1 = MclGroupT; using MclPairingBls12381G2 = MclGroupT; -using MclPairingBls12381GT = math::hmcl::MclField; +using MclPairingBls12381GT = math::MclField; class MclPairingBls12381 : public PairingGroup { public: @@ -58,4 +58,4 @@ class MclPairingBls12381 : public PairingGroup { std::unique_ptr& gt); }; -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/pairing/mcl/mcl_pairing_factory.cc b/yacl/crypto/pairing/factory/mcl_factory.cc similarity index 57% rename from yacl/crypto/pairing/mcl/mcl_pairing_factory.cc rename to yacl/crypto/pairing/factory/mcl_factory.cc index 02e030f0..35948b46 100644 --- a/yacl/crypto/pairing/mcl/mcl_pairing_factory.cc +++ b/yacl/crypto/pairing/factory/mcl_factory.cc @@ -14,23 +14,23 @@ #include "absl/strings/ascii.h" -#include "yacl/crypto/pairing/mcl/mcl_pairing_group.h" +#include "yacl/crypto/pairing/factory/mcl_pairing_group.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { std::map Name2MclPairingEnum = { - {"bls12-381", MCL_BLS12_381}, + {"bls12-381", MCL_BLS12_381}, {"bn_snark1", MCL_BN_SNARK1}, #ifdef MCL_ALL_PAIRING_FOR_YACL {"bn254", MCL_BN254}, {"bn382m", MCL_BN381_1}, {"bn382r", MCL_BN381_2}, {"bn462", MCL_BN462}, - {"bn_snark1", MCL_BN_SNARK1}, {"bn160", MCL_BN160}, - {"bls12-377", MCL_BLS12_377}, {"bls12-461", MCL_BLS12_461}, + {"bn160", MCL_BN160}, {"bls12-461", MCL_BLS12_461}, {"bn256", MCL_BN_P256}, #endif + // not supported yet, under construction by libmcl + // {"bls12-377", MCL_BLS12_377}, }; -std::unique_ptr MclPGFactory::CreateByName( - const PairingName& name) { +PairingMeta MclPGFactory::GetMeta(const PairingName& name) { PairingMeta meta = GetCurveMetaByName("bls12-381"); meta.name = absl::AsciiStrToLower(name); @@ -38,9 +38,11 @@ std::unique_ptr MclPGFactory::CreateByName( switch (pairing_type) { case MCL_BLS12_381: break; -#ifdef MCL_ALL_PAIRING_FOR_YACL - case MCL_BLS12_377: + case MCL_BN_SNARK1: { + meta.secure_bits = 100; break; + } +#ifdef MCL_ALL_PAIRING_FOR_YACL case MCL_BLS12_461: case MCL_BN381_1: case MCL_BN462: @@ -49,8 +51,7 @@ std::unique_ptr MclPGFactory::CreateByName( break; } case MCL_BN254: - case MCL_BN_P256: - case MCL_BN_SNARK1: { + case MCL_BN_P256: { meta.secure_bits = 100; break; } @@ -60,41 +61,89 @@ std::unique_ptr MclPGFactory::CreateByName( break; } #endif + // case MCL_BLS12_377: { + // meta = GetCurveMetaByName("bls12-377"); + // break; + // } default: - YACL_THROW("Not supported pairing!"); + YACL_THROW("Not supported pairing {} in {}!", meta.LowerName(), kLibName); } - return Create(meta); + return meta; +} + +std::unique_ptr MclPGFactory::CreateByName( + const PairingName& name) { + return Create(GetMeta(name)); } #define CASE_DEFINE(mcl_pairing_macro, class_name, namespace_name) \ + case MCL_##mcl_pairing_macro: { \ + auto p1 = std::make_shared(); \ + auto p2 = std::make_shared(); \ + static bool once = [&] { \ + mcl::namespace_name::initPairing(mcl::mcl_pairing_macro); \ + return true; \ + }(); \ + mcl::namespace_name::hashAndMapToG1(*p1, #class_name); \ + mcl::namespace_name::hashAndMapToG2(*p2, #class_name); \ + YACL_ENFORCE(once && !p1->isZero() && !p2->isZero()); \ + \ + auto g1 = std::unique_ptr(new MclPairing##class_name##G1( \ + meta, pairing_type, AnyPtr(p1), false)); \ + reinterpret_cast(g1.get()) \ + ->hash_to_pairing_curve_func_ = \ + static_cast( \ + mcl::namespace_name::hashAndMapToG1); \ + \ + auto g2 = std::unique_ptr(new MclPairing##class_name##G2( \ + meta, pairing_type, AnyPtr(p2), false)); \ + reinterpret_cast(g2.get()) \ + ->hash_to_pairing_curve_func_ = \ + static_cast( \ + mcl::namespace_name::hashAndMapToG2); \ + \ + auto gt = std::unique_ptr( \ + new MclPairing##class_name##GT(g1->GetOrder(), math::Type::Mul)); \ + \ + auto child_ptr = \ + std::make_unique(meta, g1, g2, gt); \ + child_ptr->pairing_func_ = mcl::namespace_name::pairing; \ + child_ptr->miller_func_ = mcl::namespace_name::millerLoop; \ + child_ptr->final_exp_func_ = mcl::namespace_name::finalExp; \ + return std::unique_ptr(std::move(child_ptr)); \ + } + +#define CASE_DEFINE_BLS(mcl_pairing_macro, class_name, namespace_name) \ case MCL_##mcl_pairing_macro: { \ auto p1 = std::make_shared(); \ auto p2 = std::make_shared(); \ static bool once = [&] { \ mcl::namespace_name::initPairing(mcl::mcl_pairing_macro); \ MclPairing##class_name##G1::BaseFp::setETHserialization(true); \ - mcl::namespace_name::hashAndMapToG1(*p1, #class_name); \ - mcl::namespace_name::hashAndMapToG2(*p2, #class_name); \ + MclPairing##class_name##G1::Fr::setETHserialization(true); \ + mcl::namespace_name::setMapToMode(MCL_MAP_TO_MODE_HASH_TO_CURVE); \ return true; \ }(); \ + mcl::namespace_name::hashAndMapToG1(*p1, #class_name); \ + mcl::namespace_name::hashAndMapToG2(*p2, #class_name); \ YACL_ENFORCE(once && !p1->isZero() && !p2->isZero()); \ \ - auto g1 = std::unique_ptr( \ - new MclPairing##class_name##G1(meta, pairing_type, AnyPtr(p1))); \ + auto g1 = std::unique_ptr(new MclPairing##class_name##G1( \ + meta, pairing_type, AnyPtr(p1), false)); \ reinterpret_cast(g1.get()) \ ->hash_to_pairing_curve_func_ = \ static_cast( \ mcl::namespace_name::hashAndMapToG1); \ \ - auto g2 = std::unique_ptr( \ - new MclPairing##class_name##G2(meta, pairing_type, AnyPtr(p2))); \ + auto g2 = std::unique_ptr(new MclPairing##class_name##G2( \ + meta, pairing_type, AnyPtr(p2), false)); \ reinterpret_cast(g2.get()) \ ->hash_to_pairing_curve_func_ = \ static_cast( \ mcl::namespace_name::hashAndMapToG2); \ \ - auto gt = std::unique_ptr(new MclPairing##class_name##GT( \ - g1->GetOrder(), math::hmcl::Type::Mul)); \ + auto gt = std::unique_ptr( \ + new MclPairing##class_name##GT(g1->GetOrder(), math::Type::Mul)); \ \ auto child_ptr = \ std::make_unique(meta, g1, g2, gt); \ @@ -116,16 +165,18 @@ std::unique_ptr MclPGFactory::Create(const PairingMeta& meta) { static bool once = [&] { mcl::bls12::initPairing(mcl::BLS12_381); mcl::bls12::G1::BaseFp::setETHserialization(true); - mcl::bls12::hashAndMapToG1(*p1, "Bls12381"); - mcl::bls12::hashAndMapToG2(*p2, "Bls12381"); + MclPairingBls12381G1::Fr::setETHserialization(true); + mcl::bls12::setMapToMode(MCL_MAP_TO_MODE_HASH_TO_CURVE); return true; }(); + mcl::bls12::hashAndMapToG1(*p1, "Bls12381"); + mcl::bls12::hashAndMapToG2(*p2, "Bls12381"); YACL_ENFORCE(once && !p1->isZero() && !p2->isZero()); // Init G1 auto g1 = std::unique_ptr( - new MclPairingBls12381G1(meta, pairing_type, AnyPtr(p1))); + new MclPairingBls12381G1(meta, pairing_type, AnyPtr(p1), false)); reinterpret_cast(g1.get()) ->hash_to_pairing_curve_func_ = static_cast( @@ -133,7 +184,7 @@ std::unique_ptr MclPGFactory::Create(const PairingMeta& meta) { // Init G2 auto g2 = std::unique_ptr( - new MclPairingBls12381G2(meta, pairing_type, AnyPtr(p2))); + new MclPairingBls12381G2(meta, pairing_type, AnyPtr(p2), false)); reinterpret_cast(g2.get()) ->hash_to_pairing_curve_func_ = static_cast( @@ -141,24 +192,24 @@ std::unique_ptr MclPGFactory::Create(const PairingMeta& meta) { // Init GT auto gt = std::unique_ptr( - new MclPairingBls12381GT(g1->GetOrder(), math::hmcl::Type::Mul)); + new MclPairingBls12381GT(g1->GetOrder(), math::Type::Mul)); return std::unique_ptr( new MclPairingBls12381(meta, g1, g2, gt)); } + CASE_DEFINE(BN_SNARK1, BNSnark, bnsnark); #ifdef MCL_ALL_PAIRING_FOR_YACL CASE_DEFINE(BN254, BN254, bn254); CASE_DEFINE(BN381_1, BN384M, bn382m); CASE_DEFINE(BN381_2, BN384R, bn382r); CASE_DEFINE(BN462, BN462, bn462); - CASE_DEFINE(BN_SNARK1, BNSnark, bnsnark); CASE_DEFINE(BN160, BN160, bn160); CASE_DEFINE(BLS12_377, Bls12377, bls123); CASE_DEFINE(BLS12_461, Bls12461, bls124); CASE_DEFINE(BN_P256, BN256, bn256); #endif default: - YACL_THROW("Not supported pairing in {}!", kLibName); + YACL_THROW("Not supported pairing {} in {}!", meta.LowerName(), kLibName); } } @@ -169,4 +220,4 @@ bool MclPGFactory::IsSupported(const PairingMeta& meta) { REGISTER_PAIRING_LIBRARY(kLibName, 400, MclPGFactory::IsSupported, MclPGFactory::Create); -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/pairing/mcl/mcl_pairing_test.cc b/yacl/crypto/pairing/factory/mcl_factory_test.cc similarity index 83% rename from yacl/crypto/pairing/mcl/mcl_pairing_test.cc rename to yacl/crypto/pairing/factory/mcl_factory_test.cc index a1c96ab9..a5b3e620 100644 --- a/yacl/crypto/pairing/mcl/mcl_pairing_test.cc +++ b/yacl/crypto/pairing/factory/mcl_factory_test.cc @@ -14,14 +14,14 @@ #include "gtest/gtest.h" -#include "yacl/crypto/pairing/mcl/mcl_pairing_group.h" +#include "yacl/crypto/pairing/factory/mcl_pairing_group.h" #include "yacl/crypto/rand/rand.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { extern std::map Name2MclPairingEnum; -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto -namespace yacl::crypto::hmcl::test { +namespace yacl::crypto::test { class MclPairingTest : public ::testing::Test { protected: @@ -78,6 +78,7 @@ class MclPairingTest : public ::testing::Test { } void TestHashToCurve(std::shared_ptr ec) { + std::vector v; for (int i = 0; i < 1000; ++i) { auto p = ec->HashToCurve(HashToCurveStrategy::TryAndIncrement_SHA2, fmt::format("id{}", i)); @@ -85,7 +86,6 @@ class MclPairingTest : public ::testing::Test { auto p2 = ec->HashToCurve(fmt::format("id{}", i)); ASSERT_TRUE(ec->IsInCurveGroup(p)); ASSERT_TRUE(ec->PointEqual(p, p2)); - static std::vector v; for (const auto& item : v) { ASSERT_FALSE(ec->PointEqual(item, p)); } @@ -94,8 +94,6 @@ class MclPairingTest : public ::testing::Test { } }; -// TODO: temporarily disable mcl pairing-related test, since its weird error on -// Intel Mac #define MCL_PAIRING_TEST(class_name, pairing_name) \ class MclPairing##class_name##Test : public MclPairingTest { \ protected: \ @@ -106,7 +104,7 @@ class MclPairingTest : public ::testing::Test { gt_ = pairing_group_->GetGroupT(); \ } \ }; \ - TEST_F(MclPairing##class_name##Test, DISABLED_Works) { \ + TEST_F(MclPairing##class_name##Test, Works) { \ fmt::print("Begin test pairing {}\n", pairing_group_->GetPairingName()); \ TestPairingAlgo(); \ TestHashToCurve(pairing_group_->GetGroup1()); \ @@ -114,17 +112,26 @@ class MclPairingTest : public ::testing::Test { fmt::print("End test pairing {}\n", pairing_group_->GetPairingName()); \ } -MCL_PAIRING_TEST(Bls12381, "bls12-381") +MCL_PAIRING_TEST(Bls12381, "bls12-381"); +MCL_PAIRING_TEST(BNSnark, "bn_snark1"); #ifdef MCL_ALL_PAIRING_FOR_YACL -MCL_PAIRING_TEST(BN254, "bn254"); -MCL_PAIRING_TEST(BN384M, "bn382m"); -MCL_PAIRING_TEST(BN384R, "bn382r"); -MCL_PAIRING_TEST(BN462, "bn462"); -MCL_PAIRING_TEST(BNSnark, "bn_snark1"); -MCL_PAIRING_TEST(BN160, "bn160"); -MCL_PAIRING_TEST(Bls12461, "bls12-461"); -MCL_PAIRING_TEST(BN256, "bn256"); +// MCL_PAIRING_TEST(BN254, "bn254"); +// MCL_PAIRING_TEST(BN384M, "bn382m"); +// MCL_PAIRING_TEST(BN384R, "bn382r"); +// MCL_PAIRING_TEST(BN462, "bn462"); +// MCL_PAIRING_TEST(BN160, "bn160"); +// MCL_PAIRING_TEST(Bls12461, "bls12-461"); +// MCL_PAIRING_TEST(BN256, "bn256"); #endif -} // namespace yacl::crypto::hmcl::test +TEST(MultInstance, OK) { + for (uint32_t i = 0; i < 5; i++) { + for (auto it = Name2MclPairingEnum.begin(); it != Name2MclPairingEnum.end(); + it++) { + MclPGFactory::CreateByName(it->first); + } + } +} + +} // namespace yacl::crypto::test diff --git a/yacl/crypto/pairing/mcl/mcl_pairing_group.cc b/yacl/crypto/pairing/factory/mcl_pairing_group.cc similarity index 96% rename from yacl/crypto/pairing/mcl/mcl_pairing_group.cc rename to yacl/crypto/pairing/factory/mcl_pairing_group.cc index c19273e6..6e1f71b1 100644 --- a/yacl/crypto/pairing/mcl/mcl_pairing_group.cc +++ b/yacl/crypto/pairing/factory/mcl_pairing_group.cc @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/crypto/pairing/mcl/mcl_pairing_group.h" +#include "yacl/crypto/pairing/factory/mcl_pairing_group.h" -#ifdef MCL_ALL_PAIRING_FOR_YACL -namespace yacl::crypto::hmcl { +namespace yacl::crypto { template std::string MclPairingGroup::GetLibraryName() const { @@ -103,16 +102,17 @@ MclPairingGroup::MclPairingGroup( // Pairing Group Classes // TEMPLATE_PARING_INSTANCE(Bls12381, bls12); +TEMPLATE_PARING_INSTANCE(BNSnark, bnsnark); +#ifdef MCL_ALL_PAIRING_FOR_YACL TEMPLATE_PARING_INSTANCE(BN254, bn254); TEMPLATE_PARING_INSTANCE(BN384M, bn382m); TEMPLATE_PARING_INSTANCE(BN384R, bn382r); TEMPLATE_PARING_INSTANCE(BN462, bn462); -TEMPLATE_PARING_INSTANCE(BNSnark, bnsnark); TEMPLATE_PARING_INSTANCE(BN160, bn160); TEMPLATE_PARING_INSTANCE(Bls12377, bls123); TEMPLATE_PARING_INSTANCE(Bls12461, bls124); TEMPLATE_PARING_INSTANCE(BN256, bn256); - -} // namespace yacl::crypto::hmcl #endif + +} // namespace yacl::crypto diff --git a/yacl/crypto/pairing/mcl/mcl_pairing_group.h b/yacl/crypto/pairing/factory/mcl_pairing_group.h similarity index 89% rename from yacl/crypto/pairing/mcl/mcl_pairing_group.h rename to yacl/crypto/pairing/factory/mcl_pairing_group.h index 40163f48..820af78c 100644 --- a/yacl/crypto/pairing/mcl/mcl_pairing_group.h +++ b/yacl/crypto/pairing/factory/mcl_pairing_group.h @@ -15,41 +15,41 @@ #pragma once #include "yacl/crypto/ecc/mcl/mcl_ec_group.h" -#include "yacl/crypto/pairing/mcl/mcl_pairing_bls12_381.h" -#include "yacl/crypto/pairing/mcl/pairing_header.h" -#include "yacl/crypto/pairing/pairing_spi.h" -#include "yacl/math/galois_field/mcl_field/mcl_field.h" +#include "yacl/crypto/pairing/factory/mcl_bls12_381.h" +#include "yacl/crypto/pairing/factory/mcl_pairing_header.h" +#include "yacl/crypto/pairing/factory/pairing_spi.h" +#include "yacl/math/galois_field/factory/mcl_factory.h" -namespace yacl::crypto::hmcl { +namespace yacl::crypto { class MclPGFactory { public: static std::unique_ptr Create(const PairingMeta& meta); // For non-standard pairing curve supported by libmcl static std::unique_ptr CreateByName(const PairingName& name); + static PairingMeta GetMeta(const PairingName& name); static bool IsSupported(const PairingMeta& meta); }; -#ifdef MCL_ALL_PAIRING_FOR_YACL - // Pairing Classes Alias #define PAIRING_CURVE_ALIAS(classname, curve_name) \ using MclPairing##classname##G1 = \ MclGroupT; \ using MclPairing##classname##G2 = \ MclGroupT; \ - using MclPairing##classname##GT = \ - math::hmcl::MclField; + using MclPairing##classname##GT = math::MclField; +PAIRING_CURVE_ALIAS(BNSnark, bnsnark); +#ifdef MCL_ALL_PAIRING_FOR_YACL PAIRING_CURVE_ALIAS(BN254, bn254); PAIRING_CURVE_ALIAS(BN384M, bn382m); PAIRING_CURVE_ALIAS(BN384R, bn382r); PAIRING_CURVE_ALIAS(BN462, bn462); -PAIRING_CURVE_ALIAS(BNSnark, bnsnark); PAIRING_CURVE_ALIAS(BN160, bn160); PAIRING_CURVE_ALIAS(Bls12377, bls123); PAIRING_CURVE_ALIAS(Bls12461, bls124); PAIRING_CURVE_ALIAS(BN256, bn256); +#endif // Warning! Pairing group in libmcl only support one instance at the same // moment. @@ -103,17 +103,16 @@ class MclPairingGroup : public PairingGroup { mcl::namespace_name::GT>; // Pairing Group Classes -// PAIRING_GROUP_ALIAS(Bls12381, bls12); - +PAIRING_GROUP_ALIAS(BNSnark, bnsnark); +#ifdef MCL_ALL_PAIRING_FOR_YACL PAIRING_GROUP_ALIAS(BN254, bn254); PAIRING_GROUP_ALIAS(BN384M, bn382m); PAIRING_GROUP_ALIAS(BN384R, bn382r); PAIRING_GROUP_ALIAS(BN462, bn462); -PAIRING_GROUP_ALIAS(BNSnark, bnsnark); PAIRING_GROUP_ALIAS(BN160, bn160); PAIRING_GROUP_ALIAS(Bls12377, bls123); PAIRING_GROUP_ALIAS(Bls12461, bls124); PAIRING_GROUP_ALIAS(BN256, bn256); #endif -} // namespace yacl::crypto::hmcl +} // namespace yacl::crypto diff --git a/yacl/crypto/pairing/mcl/pairing_header.h b/yacl/crypto/pairing/factory/mcl_pairing_header.h similarity index 98% rename from yacl/crypto/pairing/mcl/pairing_header.h rename to yacl/crypto/pairing/factory/mcl_pairing_header.h index 0236774c..50423935 100644 --- a/yacl/crypto/pairing/mcl/pairing_header.h +++ b/yacl/crypto/pairing/factory/mcl_pairing_header.h @@ -24,6 +24,15 @@ // libmcl's author herumi doesn't recommend this. // https://github.com/herumi/mcl/issues/181#issuecomment-1513916051 +// For MCL_BN_SNARK1 +#undef MCL_INCLUDE_MCL_BN_HPP +#undef MCL_MAX_FP_BIT_SIZE +#undef MCL_MAX_FR_BIT_SIZE +#define MCL_MAX_FP_BIT_SIZE 256 +#undef MCL_NAMESPACE_BN +#define MCL_NAMESPACE_BN bnsnark +#include "mcl/bn.hpp" + #ifdef MCL_ALL_PAIRING_FOR_YACL // For MCL_BN254 #undef MCL_INCLUDE_MCL_BN_HPP @@ -52,7 +61,6 @@ #define MCL_NAMESPACE_BN bn382r #include "mcl/bn.hpp" -#if MCL_MAX_BIT_SIZE >= 462 #undef MCL_INCLUDE_MCL_BN_HPP #undef MCL_MAX_FP_BIT_SIZE #undef MCL_MAX_FR_BIT_SIZE @@ -60,16 +68,6 @@ #undef MCL_NAMESPACE_BN #define MCL_NAMESPACE_BN bn462 #include "mcl/bn.hpp" -#endif - -// For MCL_BN_SNARK1 -#undef MCL_INCLUDE_MCL_BN_HPP -#undef MCL_MAX_FP_BIT_SIZE -#undef MCL_MAX_FR_BIT_SIZE -#define MCL_MAX_FP_BIT_SIZE 256 -#undef MCL_NAMESPACE_BN -#define MCL_NAMESPACE_BN bnsnark -#include "mcl/bn.hpp" // For MCL_BN160 #undef MCL_INCLUDE_MCL_BN_HPP diff --git a/yacl/crypto/pairing/pairing_spi.cc b/yacl/crypto/pairing/factory/pairing_spi.cc similarity index 89% rename from yacl/crypto/pairing/pairing_spi.cc rename to yacl/crypto/pairing/factory/pairing_spi.cc index 975211d7..f77f3acb 100644 --- a/yacl/crypto/pairing/pairing_spi.cc +++ b/yacl/crypto/pairing/factory/pairing_spi.cc @@ -12,15 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/crypto/pairing/pairing_spi.h" +#include "yacl/crypto/pairing/factory/pairing_spi.h" namespace yacl::crypto { -PairingGroupFactory &PairingGroupFactory::Instance() { - static PairingGroupFactory factory; - return factory; -} - void PairingGroupFactory::Register(const std::string &lib_name, uint64_t performance, const PairingCheckerT &checker, diff --git a/yacl/crypto/pairing/factory/pairing_spi.h b/yacl/crypto/pairing/factory/pairing_spi.h new file mode 100644 index 00000000..6add169e --- /dev/null +++ b/yacl/crypto/pairing/factory/pairing_spi.h @@ -0,0 +1,28 @@ +// Copyright 2023 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "yacl/crypto/ecc/ecc_spi.h" +#include "yacl/crypto/pairing/pairing.h" +#include "yacl/math/galois_field/gf.h" +#include "yacl/utils/spi/spi_factory.h" + +namespace yacl::crypto { + +#define REGISTER_PAIRING_LIBRARY(lib_name, performance, checker, creator) \ + REGISTER_SPI_LIBRARY_HELPER(PairingGroupFactory, lib_name, performance, \ + checker, creator) + +} // namespace yacl::crypto diff --git a/yacl/crypto/pairing/pairing_spi.h b/yacl/crypto/pairing/pairing.h similarity index 92% rename from yacl/crypto/pairing/pairing_spi.h rename to yacl/crypto/pairing/pairing.h index d2afd5da..5825317b 100644 --- a/yacl/crypto/pairing/pairing_spi.h +++ b/yacl/crypto/pairing/pairing.h @@ -15,7 +15,7 @@ #pragma once #include "yacl/crypto/ecc/ecc_spi.h" -#include "yacl/math/galois_field/gf_spi.h" +#include "yacl/math/galois_field/gf.h" #include "yacl/utils/spi/spi_factory.h" namespace yacl::crypto { @@ -61,7 +61,6 @@ class PairingGroup { virtual std::shared_ptr GetGroupT() const = 0; virtual MPInt GetOrder() const = 0; - virtual GtElement MillerLoop(const EcPoint &group1_point, const EcPoint &group2_point) const = 0; virtual GtElement FinalExp(const GtElement &x) const = 0; @@ -82,9 +81,13 @@ using PairingCreatorT = // True is supported and false is unsupported. using PairingCheckerT = std::function; +// registray utils class PairingGroupFactory final : public SpiFactoryBase { public: - static PairingGroupFactory &Instance(); + static PairingGroupFactory &Instance() { + static PairingGroupFactory factory; + return factory; + } /// Register an elliptic curve library /// \param lib_name library name, e.g. openssl @@ -94,8 +97,4 @@ class PairingGroupFactory final : public SpiFactoryBase { const PairingCheckerT &checker, const PairingCreatorT &creator); }; -#define REGISTER_PAIRING_LIBRARY(lib_name, performance, checker, creator) \ - REGISTER_SPI_LIBRARY_HELPER(PairingGroupFactory, lib_name, performance, \ - checker, creator) - } // namespace yacl::crypto diff --git a/yacl/crypto/pairing/pairing_test.cc b/yacl/crypto/pairing/pairing_test.cc index 3a173ad4..9ca743df 100644 --- a/yacl/crypto/pairing/pairing_test.cc +++ b/yacl/crypto/pairing/pairing_test.cc @@ -17,7 +17,7 @@ #include "fmt/ranges.h" #include "gtest/gtest.h" -#include "yacl/crypto/pairing/pairing_spi.h" +#include "yacl/crypto/pairing/factory/pairing_spi.h" #include "yacl/utils/parallel.h" namespace yacl::crypto { @@ -37,10 +37,8 @@ class PairingCurveTest : public ::testing::TestWithParam { TestArithmeticWorks(ec); TestMulIsAdd(ec); TestSerializeWorks(ec); - if (pairing_group_->GetLibraryName() != "libmcl") { - TestHashPointWorks(ec); - TestStorePointsInMapWorks(ec); - } + TestHashPointWorks(ec); + TestStorePointsInMapWorks(ec); MultiThreadWorks(ec); } } @@ -147,6 +145,30 @@ class PairingCurveTest : public ::testing::TestWithParam { void TestSerializeWorks(const std::shared_ptr &ec) { auto s = 12345_mp; auto p1 = ec->MulBase(s); // p1 = sG + // test ZCash_BLS12_381 format + if (absl::AsciiStrToLower(ec->GetCurveName()) == "bls12-381") { + std::cout << "start\n"; + auto p3 = ec->Mul(p1, 67890_mp); + auto buf = ec->SerializePoint(p3, PointOctetFormat::ZCash_BLS12_381); + // 160 = 1010 0000, 128 = 10000 000 + ASSERT_TRUE((buf.data()[0] & 160) == 160 || + (buf.data()[0] & 128) == 128) + << fmt::format("real={:x}", buf.data()[0]); + auto p4 = ec->DeserializePoint(buf, PointOctetFormat::ZCash_BLS12_381); + ASSERT_TRUE(ec->PointEqual(p3, p4)); + + // test zero + auto p5 = ec->Mul(p3, 0_mp); + ASSERT_TRUE(ec->IsInfinity(p5)); + buf = ec->SerializePoint(p5, PointOctetFormat::ZCash_BLS12_381); + // 192 = 1100 0000 + ASSERT_TRUE((buf.data()[0] & 192) == 192); + + auto p6 = ec->DeserializePoint(buf, PointOctetFormat::ZCash_BLS12_381); + ASSERT_TRUE(ec->IsInfinity(p6)); + return; + } + auto buf = ec->SerializePoint(p1); auto p2 = ec->DeserializePoint(buf); ASSERT_TRUE(ec->PointEqual(p1, p2)); @@ -155,36 +177,60 @@ class PairingCurveTest : public ::testing::TestWithParam { ec->SerializePoint(p2, &buf); ASSERT_TRUE(ec->PointEqual(ec->DeserializePoint(buf), ec->GetGenerator())); - // test ZCash_BLS12_381 format + // Autonomous Serialization auto p3 = ec->Mul(p1, 67890_mp); - buf = ec->SerializePoint(p3, PointOctetFormat::ZCash_BLS12_381); - // 160 = 1010 0000, 128 = 10000 000 - ASSERT_TRUE((buf.data()[0] & 160) == 160 || - (buf.data()[0] & 128) == 128) - << fmt::format("real={:x}", buf.data()[0]); - auto p4 = ec->DeserializePoint(buf, PointOctetFormat::ZCash_BLS12_381); + buf = ec->SerializePoint(p3); + + auto p4 = ec->DeserializePoint(buf); ASSERT_TRUE(ec->PointEqual(p3, p4)); // test zero auto p5 = ec->Mul(p3, 0_mp); ASSERT_TRUE(ec->IsInfinity(p5)); - buf = ec->SerializePoint(p5, PointOctetFormat::ZCash_BLS12_381); + buf = ec->SerializePoint(p5); // 192 = 1100 0000 - ASSERT_TRUE((buf.data()[0] & 192) == 192); + // ASSERT_TRUE((buf.data()[0] & 192) == 192); - auto p6 = ec->DeserializePoint(buf, PointOctetFormat::ZCash_BLS12_381); + auto p6 = ec->DeserializePoint(buf); ASSERT_TRUE(ec->IsInfinity(p6)); + + // X962Uncompressed + auto buf2 = ec->SerializePoint(p3, PointOctetFormat::X962Uncompressed); + ASSERT_TRUE((buf2.data()[0]) == 0x4); + + auto p7 = ec->DeserializePoint(buf2, PointOctetFormat::X962Uncompressed); + ASSERT_TRUE(ec->PointEqual(p3, p7)); + auto p7a = ec->GetAffinePoint(p7); + MPInt x, y; + // buf2 = 0x04||x||y |x|=|y|=buf2.size() - 1) / 2 with little endian + // x: 1 to buf2.size() - 1) / 2 + 1 + // y: buf2.size() - 1) / 2 + 1 to end + ASSERT_TRUE((buf2.size() - 1) % 2 == 0); + auto len = (buf2.size() - 1) / 2; + x.FromMagBytes({buf2.data() + 1, static_cast(len)}, + Endian::little); + ASSERT_TRUE(x == p7a.x); + y.FromMagBytes({buf2.data() + len + 1, static_cast(len)}, + Endian::little); + ASSERT_TRUE(y == p7a.y); + + buf2 = ec->SerializePoint(p5, PointOctetFormat::X962Uncompressed); + ASSERT_TRUE((buf2.data()[0]) == 0x4); + auto p8 = ec->DeserializePoint(buf2, PointOctetFormat::X962Uncompressed); + ASSERT_TRUE(ec->IsInfinity(p8)); } void TestHashPointWorks(const std::shared_ptr &ec) { std::map hit_table; auto p = ec->MulBase(0_mp); - int ts = 1 << 15; + int ts = 1 << 10; + for (int i = 0; i < ts; ++i) { auto h = ec->HashPoint(p); ++hit_table[h]; ASSERT_EQ(hit_table[h], 1); ec->AddInplace(&p, ec->GetGenerator()); + auto p = ec->MulBase(MPInt(i)); } ASSERT_EQ(hit_table.size(), ts); @@ -230,7 +276,7 @@ class PairingCurveTest : public ::testing::TestWithParam { } void MultiThreadWorks(const std::shared_ptr &ec) { - constexpr int64_t ts = 1 << 15; + constexpr int64_t ts = 1 << 10; std::array buf; auto g = ec->GetGenerator(); yacl::parallel_for(0, ts, [&](int64_t beg, int64_t end) { @@ -299,12 +345,8 @@ class PairingCurveTest : public ::testing::TestWithParam { class Bls12381Test : public PairingCurveTest { protected: void SetUp() override { - // TODO: temporarily disable mcl pairing-related test, since its weird error - // on Intel Mac - if (GetParam() != "libmcl") { - pairing_group_ = PairingGroupFactory::Instance().Create( - "bls12-381", ArgLib = GetParam()); - } + pairing_group_ = PairingGroupFactory::Instance().Create( + "bls12-381", ArgLib = GetParam()); } }; @@ -324,21 +366,41 @@ TEST_P(Bls12381Test, SpiTest) { } } +class BNSnarkTest : public PairingCurveTest { + protected: + void SetUp() override { + pairing_group_ = PairingGroupFactory::Instance().Create( + "bn_snark1", ArgLib = GetParam()); + } +}; + +INSTANTIATE_TEST_SUITE_P(BNSnark, BNSnarkTest, + ::testing::ValuesIn(PairingGroupFactory::Instance() + .ListLibraries("bn_snark1"))); + +TEST_P(BNSnarkTest, SpiTest) { + if (pairing_group_ != nullptr) { + EXPECT_STRCASEEQ(pairing_group_->GetPairingName().c_str(), "bn_snark1"); + EXPECT_EQ(pairing_group_->GetPairingAlgorithm(), PairingAlgorithm::Ate); + EXPECT_EQ(pairing_group_->GetSecurityStrength(), 100); + EXPECT_FALSE(pairing_group_->ToString().empty()); + + // Run Other tests + RunAllTests(); + } +} + TEST(Pairing_Multi_Instance_Test, Works) { PairingName pairing_name = "bls12-381"; for (auto lib_name : PairingGroupFactory::Instance().ListLibraries(pairing_name)) { - // TODO: temporarily disable mcl pairing-related test, since its weird error - // on Intel Mac - if (lib_name != "libmcl") { - yacl::parallel_for(0, 10, [&](int64_t, int64_t) { - std::shared_ptr pairing = - PairingGroupFactory::Instance().Create(pairing_name, - ArgLib = lib_name); - pairing->Pairing(pairing->GetGroup1()->GetGenerator(), - pairing->GetGroup2()->GetGenerator()); - }); - } + yacl::parallel_for(0, 10, [&](int64_t, int64_t) { + std::shared_ptr pairing = + PairingGroupFactory::Instance().Create(pairing_name, + ArgLib = lib_name); + pairing->Pairing(pairing->GetGroup1()->GetGenerator(), + pairing->GetGroup2()->GetGenerator()); + }); } } diff --git a/yacl/crypto/rand/rand.cc b/yacl/crypto/rand/rand.cc index eab1edbd..228d7e17 100644 --- a/yacl/crypto/rand/rand.cc +++ b/yacl/crypto/rand/rand.cc @@ -21,6 +21,7 @@ #include "yacl/base/dynamic_bitset.h" #include "yacl/crypto/ossl-provider/helper.h" #include "yacl/crypto/rand/entropy_source/entropy_source.h" +#include "yacl/math/gadget.h" namespace yacl::crypto { @@ -79,24 +80,26 @@ std::vector RandBits>(uint64_t len, return out; } -#define IMPL_RANDBIT_DYNAMIC_BIT_TYPE(T) \ - template <> \ - dynamic_bitset RandBits>(uint64_t len, \ - bool use_fast_mode) { \ - dynamic_bitset out(len); \ - const unsigned stride = sizeof(unsigned) * 8; \ - \ - /* generate randomness */ \ - auto rand_buf = RandBytes(len, use_fast_mode); \ - \ - /* for each byte */ \ - for (uint64_t i = 0; i < len; i += stride) { \ - unsigned size = std::min(stride, static_cast(len - i)); \ - for (unsigned j = 0; j < size; ++j) { \ - out[i + j] = (rand_buf[i] & (1 << j)) != 0; \ - } \ - } \ - return out; \ +#define IMPL_RANDBIT_DYNAMIC_BIT_TYPE(T) \ + template <> \ + dynamic_bitset RandBits>(uint64_t len, \ + bool use_fast_mode) { \ + dynamic_bitset out(len); \ + size_t byte_len = math::DivCeil(len, 8); \ + \ + /* generate randomness */ \ + auto rand_buf = RandBytes(byte_len, use_fast_mode); \ + \ + /* for each byte */ \ + for (uint64_t i = 0; i < len; i += 8) { \ + uint64_t size = \ + std::min(static_cast(8), static_cast(len - i)); \ + uint64_t offset = i >> 3; \ + for (unsigned j = 0; j < size; ++j) { \ + out[i + j] = (rand_buf[offset] & (1 << j)) != 0; \ + } \ + } \ + return out; \ } IMPL_RANDBIT_DYNAMIC_BIT_TYPE(uint128_t); diff --git a/yacl/crypto/rand/rand_test.cc b/yacl/crypto/rand/rand_test.cc index 496f51bf..178d2b45 100644 --- a/yacl/crypto/rand/rand_test.cc +++ b/yacl/crypto/rand/rand_test.cc @@ -41,4 +41,46 @@ TEST_GENERIC_TYPE_RAND_FUNC(RandSeed); TEST_GENERIC_TYPE_RAND_FUNC(RandBytes, 10); TEST_GENERIC_TYPE_RAND_FUNC(RandBits, 10); +template +std::pair Count(T val) { + uint64_t zero_num = 0; + uint64_t one_num = 0; + size_t num = sizeof(T) * 8; + for (size_t i = 0; i < num; ++i) { + val & 0x1 ? ++one_num : ++zero_num; + val >>= 1; + } + return std::make_pair(zero_num, one_num); +} + +// \sum_{i=350}^{750}( (1/2)^i (1/2)^{1000-i} (1000 choose i) ) = 0.9999999999 +TEST(GenericRandTest, RandBits01Test) { + auto rand = SecureRandBits(1000); + int64_t one_num = 0; + int64_t zero_num = 0; + for (size_t i = 0; i < 1000; ++i) { + rand[i] ? ++one_num : ++zero_num; + } + auto diff = std::abs(one_num - zero_num); + + EXPECT_TRUE(diff < 300); +} + +TEST(GenericRandTest, RandVec01Test) { + auto vec = RandVec(125); // 125 * 8 = 1000 + yacl::dynamic_bitset rand; + for (const auto& val : vec) { + rand.append(val); + } + + int64_t one_num = 0; + int64_t zero_num = 0; + for (size_t i = 0; i < rand.size(); ++i) { + rand[i] ? ++one_num : ++zero_num; + } + auto diff = std::abs(one_num - zero_num); + + EXPECT_TRUE(diff < 300); +} + } // namespace yacl::crypto diff --git a/yacl/crypto/zkp/BUILD.bazel b/yacl/crypto/zkp/BUILD.bazel index fc851718..c7bea76d 100644 --- a/yacl/crypto/zkp/BUILD.bazel +++ b/yacl/crypto/zkp/BUILD.bazel @@ -39,45 +39,3 @@ yacl_cc_library( "//yacl/crypto/rand", ], ) - -yacl_cc_library( - name = "sigma", - srcs = ["sigma.cc"], - hdrs = [ - "sigma.h", - ], - deps = [ - ":sigma_owh", - "//yacl/crypto/tools:ro", - ], -) - -yacl_cc_test( - name = "sigma_test", - srcs = ["sigma_test.cc"], - deps = [ - ":sigma", - ":sigma_owh", - "//yacl/crypto/rand", - ], -) - -yacl_cc_library( - name = "pedersen_commit", - hdrs = [ - "pedersen_commit.h", - ], - deps = [ - ":sigma_owh", - "//yacl/crypto/hash:hash_utils", - ], -) - -yacl_cc_test( - name = "pedersen_commit_test", - srcs = ["pedersen_commit_test.cc"], - deps = [ - ":pedersen_commit", - "//yacl/crypto/rand", - ], -) diff --git a/yacl/crypto/zkp/sigma_config.cc b/yacl/crypto/zkp/sigma_config.cc index 60155426..9cbf6af0 100644 --- a/yacl/crypto/zkp/sigma_config.cc +++ b/yacl/crypto/zkp/sigma_config.cc @@ -95,9 +95,10 @@ SigmaConfig SigmaConfig::SetDynNum(uint32_t n) { bool SigmaConfig::Equals(SigmaConfig rhs) const { return std::tie(type, num_witness, num_rnd_witness, num_generator, - num_statement, dyn_size_flag) == + num_statement, dyn_size_flag, ro_type, point_format) == std::tie(rhs.type, rhs.num_witness, rhs.num_rnd_witness, - rhs.num_generator, rhs.num_statement, rhs.dyn_size_flag); + rhs.num_generator, rhs.num_statement, rhs.dyn_size_flag, + rhs.ro_type, rhs.point_format); } std::map BuildSigmaMap() { diff --git a/yacl/crypto/zkp/sigma_config.h b/yacl/crypto/zkp/sigma_config.h index f9e7f367..aa1221ed 100644 --- a/yacl/crypto/zkp/sigma_config.h +++ b/yacl/crypto/zkp/sigma_config.h @@ -99,6 +99,8 @@ struct SigmaConfig { false; // true for any meta has dynamic attrs, default set to false HashAlgorithm ro_type = HashAlgorithm::BLAKE3; // hash type for non-interactive proof + PointOctetFormat point_format = + PointOctetFormat::Autonomous; // Ec point serialization mod SigmaConfig SetDynNum(uint32_t n); diff --git a/yacl/kernels/BUILD.bazel b/yacl/kernel/BUILD.bazel similarity index 96% rename from yacl/kernels/BUILD.bazel rename to yacl/kernel/BUILD.bazel index 014c85f2..596245d4 100644 --- a/yacl/kernels/BUILD.bazel +++ b/yacl/kernel/BUILD.bazel @@ -32,7 +32,7 @@ yacl_cc_library( hdrs = ["svole_kernel.h"], deps = [ ":kernel", - "//yacl/kernels/algorithms:silent_vole", + "//yacl/kernel/algorithms:silent_vole", ], ) diff --git a/yacl/kernels/algorithms/BUILD.bazel b/yacl/kernel/algorithms/BUILD.bazel similarity index 92% rename from yacl/kernels/algorithms/BUILD.bazel rename to yacl/kernel/algorithms/BUILD.bazel index aba0e0cb..b8dd5f49 100644 --- a/yacl/kernels/algorithms/BUILD.bazel +++ b/yacl/kernel/algorithms/BUILD.bazel @@ -74,6 +74,7 @@ yacl_cc_library( "//yacl/crypto/tools:ro", "//yacl/link", "//yacl/math:gadget", + "//yacl/math/f2k", "@simplest_ot//:simplest_ot_x86_asm", ], ) @@ -85,7 +86,7 @@ yacl_cc_library( deps = [ "//yacl:secparam", "//yacl/base:exception", - "//yacl/kernels/algorithms:ot_store", + "//yacl/kernel/algorithms:ot_store", "//yacl/link", "@com_google_absl//absl/types:span", ] + select({ @@ -244,11 +245,12 @@ yacl_cc_library( "//yacl/crypto/tools:common", "//yacl/crypto/tools:prg", "//yacl/crypto/tools:rp", - "//yacl/kernels/algorithms:gywz_ote", - "//yacl/kernels/algorithms:sgrr_ote", - "//yacl/kernels/code:linear_code", + "//yacl/kernel/algorithms:gywz_ote", + "//yacl/kernel/algorithms:sgrr_ote", + "//yacl/kernel/code:linear_code", "//yacl/link", "//yacl/math:gadget", + "//yacl/math/f2k", "//yacl/utils:cuckoo_index", ], ) @@ -343,9 +345,9 @@ yacl_cc_library( "//yacl/base:int128", "//yacl/crypto/rand", "//yacl/crypto/tools:crhash", - "//yacl/kernels/algorithms:gywz_ote", - "//yacl/kernels/algorithms:ot_store", - "//yacl/kernels/algorithms:sgrr_ote", + "//yacl/kernel/algorithms:gywz_ote", + "//yacl/kernel/algorithms:ot_store", + "//yacl/kernel/algorithms:sgrr_ote", "//yacl/math:gadget", "//yacl/math/f2k", ], @@ -374,9 +376,10 @@ yacl_cc_library( "//yacl/base:dynamic_bitset", "//yacl/base:int128", "//yacl/crypto/rand", - "//yacl/kernels/algorithms:ot_store", - "//yacl/kernels/algorithms:softspoken_ote", + "//yacl/kernel/algorithms:ot_store", + "//yacl/kernel/algorithms:softspoken_ote", "//yacl/math:gadget", + "//yacl/math/f2k", "//yacl/utils:serialize", ], ) @@ -406,8 +409,8 @@ yacl_cc_library( "//yacl/crypto/hash:hash_utils", "//yacl/crypto/rand", "//yacl/crypto/tools:common", - "//yacl/kernels/algorithms:mpfss", - "//yacl/kernels/algorithms:ot_store", + "//yacl/kernel/algorithms:mpfss", + "//yacl/kernel/algorithms:ot_store", "//yacl/math:gadget", "//yacl/math/f2k", "//yacl/utils:serialize", @@ -439,11 +442,11 @@ yacl_cc_library( "//yacl/base:aligned_vector", "//yacl/base:dynamic_bitset", "//yacl/base:int128", - "//yacl/kernels/algorithms:ot_store", - "//yacl/kernels/algorithms:softspoken_ote", - "//yacl/kernels/code:code_interface", - "//yacl/kernels/code:ea_code", - "//yacl/kernels/code:silver_code", + "//yacl/kernel/algorithms:ot_store", + "//yacl/kernel/algorithms:softspoken_ote", + "//yacl/kernel/code:code_interface", + "//yacl/kernel/code:ea_code", + "//yacl/kernel/code:silver_code", "//yacl/link:context", ], ) diff --git a/yacl/kernels/algorithms/base_ot.cc b/yacl/kernel/algorithms/base_ot.cc similarity index 97% rename from yacl/kernels/algorithms/base_ot.cc rename to yacl/kernel/algorithms/base_ot.cc index 5ae2e07b..90b4d880 100644 --- a/yacl/kernels/algorithms/base_ot.cc +++ b/yacl/kernel/algorithms/base_ot.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/base_ot.h" +#include "yacl/kernel/algorithms/base_ot.h" #include "yacl/base/exception.h" diff --git a/yacl/kernels/algorithms/base_ot.h b/yacl/kernel/algorithms/base_ot.h similarity index 92% rename from yacl/kernels/algorithms/base_ot.h rename to yacl/kernel/algorithms/base_ot.h index 55c69a5c..001ba918 100644 --- a/yacl/kernels/algorithms/base_ot.h +++ b/yacl/kernel/algorithms/base_ot.h @@ -21,15 +21,15 @@ #include "yacl/base/dynamic_bitset.h" #include "yacl/base/int128.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/link.h" #include "yacl/secparam.h" /* submodules */ #if defined(__linux__) && defined(__x86_64) -#include "yacl/kernels/algorithms/x86_asm_ot_interface.h" +#include "yacl/kernel/algorithms/x86_asm_ot_interface.h" #else -#include "yacl/kernels/algorithms/portable_ot_interface.h" +#include "yacl/kernel/algorithms/portable_ot_interface.h" #endif /* security parameter declaration */ diff --git a/yacl/kernels/algorithms/base_ot_interface.h b/yacl/kernel/algorithms/base_ot_interface.h similarity index 100% rename from yacl/kernels/algorithms/base_ot_interface.h rename to yacl/kernel/algorithms/base_ot_interface.h diff --git a/yacl/kernels/algorithms/base_ot_test.cc b/yacl/kernel/algorithms/base_ot_test.cc similarity index 98% rename from yacl/kernels/algorithms/base_ot_test.cc rename to yacl/kernel/algorithms/base_ot_test.cc index e15e87bb..d7f79fe6 100644 --- a/yacl/kernels/algorithms/base_ot_test.cc +++ b/yacl/kernel/algorithms/base_ot_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/base_ot.h" +#include "yacl/kernel/algorithms/base_ot.h" #include #include diff --git a/yacl/kernels/algorithms/base_vole.h b/yacl/kernel/algorithms/base_vole.h similarity index 97% rename from yacl/kernels/algorithms/base_vole.h rename to yacl/kernel/algorithms/base_vole.h index 84377aec..b0a9f43a 100644 --- a/yacl/kernels/algorithms/base_vole.h +++ b/yacl/kernel/algorithms/base_vole.h @@ -16,12 +16,12 @@ #include "yacl/base/exception.h" #include "yacl/base/int128.h" -#include "yacl/math/f2k/f2k.h" +#include "yacl/math/f2k/f2k_utils.h" #include "yacl/math/gadget.h" /* submodules */ -#include "yacl/kernels/algorithms/ot_store.h" -#include "yacl/kernels/algorithms/softspoken_ote.h" +#include "yacl/kernel/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/softspoken_ote.h" #include "yacl/secparam.h" YACL_MODULE_DECLARE("base_vole", SecParam::C::INF, SecParam::S::INF); diff --git a/yacl/kernels/algorithms/base_vole_test.cc b/yacl/kernel/algorithms/base_vole_test.cc similarity index 99% rename from yacl/kernels/algorithms/base_vole_test.cc rename to yacl/kernel/algorithms/base_vole_test.cc index 0f5cefcc..80cdaf03 100644 --- a/yacl/kernels/algorithms/base_vole_test.cc +++ b/yacl/kernel/algorithms/base_vole_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/base_vole.h" +#include "yacl/kernel/algorithms/base_vole.h" #include diff --git a/yacl/kernels/algorithms/ferret_ote.cc b/yacl/kernel/algorithms/ferret_ote.cc similarity index 99% rename from yacl/kernels/algorithms/ferret_ote.cc rename to yacl/kernel/algorithms/ferret_ote.cc index 52768ebf..edf0be17 100644 --- a/yacl/kernels/algorithms/ferret_ote.cc +++ b/yacl/kernel/algorithms/ferret_ote.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/ferret_ote.h" +#include "yacl/kernel/algorithms/ferret_ote.h" #include #include diff --git a/yacl/kernels/algorithms/ferret_ote.h b/yacl/kernel/algorithms/ferret_ote.h similarity index 93% rename from yacl/kernels/algorithms/ferret_ote.h rename to yacl/kernel/algorithms/ferret_ote.h index 1109f2fe..4d9f6564 100644 --- a/yacl/kernels/algorithms/ferret_ote.h +++ b/yacl/kernel/algorithms/ferret_ote.h @@ -19,16 +19,16 @@ #include #include -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/math/gadget.h" #include "yacl/secparam.h" #include "yacl/utils/cuckoo_index.h" /* submodules */ -#include "yacl/kernels/algorithms/ferret_ote_rn.h" -#include "yacl/kernels/algorithms/ferret_ote_un.h" -#include "yacl/kernels/algorithms/gywz_ote.h" -#include "yacl/kernels/code/linear_code.h" +#include "yacl/kernel/algorithms/ferret_ote_rn.h" +#include "yacl/kernel/algorithms/ferret_ote_un.h" +#include "yacl/kernel/algorithms/gywz_ote.h" +#include "yacl/kernel/code/linear_code.h" /* security parameter declaration */ // this module is only a wrapper, no need for security parameter definition diff --git a/yacl/kernels/algorithms/ferret_ote_rn.h b/yacl/kernel/algorithms/ferret_ote_rn.h similarity index 98% rename from yacl/kernels/algorithms/ferret_ote_rn.h rename to yacl/kernel/algorithms/ferret_ote_rn.h index 3866ed48..58c455fc 100644 --- a/yacl/kernels/algorithms/ferret_ote_rn.h +++ b/yacl/kernel/algorithms/ferret_ote_rn.h @@ -20,11 +20,11 @@ #include "yacl/crypto/hash/hash_utils.h" #include "yacl/crypto/tools/common.h" -#include "yacl/math/gadget.h" +#include "yacl/math/f2k/f2k_utils.h" #include "yacl/secparam.h" /* submodules */ -#include "yacl/kernels/algorithms/gywz_ote.h" +#include "yacl/kernel/algorithms/gywz_ote.h" /* security parameter declaration */ YACL_MODULE_DECLARE("ferret_ote_rn", SecParam::C::k128, SecParam::S::INF); diff --git a/yacl/kernels/algorithms/ferret_ote_test.cc b/yacl/kernel/algorithms/ferret_ote_test.cc similarity index 98% rename from yacl/kernels/algorithms/ferret_ote_test.cc rename to yacl/kernel/algorithms/ferret_ote_test.cc index 2660ccdf..80a1dfce 100644 --- a/yacl/kernels/algorithms/ferret_ote_test.cc +++ b/yacl/kernel/algorithms/ferret_ote_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/ferret_ote.h" +#include "yacl/kernel/algorithms/ferret_ote.h" #include #include @@ -27,7 +27,7 @@ #include "yacl/base/int128.h" #include "yacl/crypto/rand/rand.h" #include "yacl/crypto/tools/prg.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/test_util.h" namespace yacl::crypto { diff --git a/yacl/kernels/algorithms/ferret_ote_un.h b/yacl/kernel/algorithms/ferret_ote_un.h similarity index 99% rename from yacl/kernels/algorithms/ferret_ote_un.h rename to yacl/kernel/algorithms/ferret_ote_un.h index 25121938..69eab65c 100644 --- a/yacl/kernels/algorithms/ferret_ote_un.h +++ b/yacl/kernel/algorithms/ferret_ote_un.h @@ -25,7 +25,7 @@ /* submodules */ #include "yacl/crypto/tools/rp.h" -#include "yacl/kernels/algorithms/gywz_ote.h" +#include "yacl/kernel/algorithms/gywz_ote.h" /* security parameter declaration */ YACL_MODULE_DECLARE("ferret_ote_un", SecParam::C::k128, SecParam::S::INF); diff --git a/yacl/kernels/algorithms/gywz_ote.cc b/yacl/kernel/algorithms/gywz_ote.cc similarity index 99% rename from yacl/kernels/algorithms/gywz_ote.cc rename to yacl/kernel/algorithms/gywz_ote.cc index 6d1f4260..972d6d9c 100644 --- a/yacl/kernels/algorithms/gywz_ote.cc +++ b/yacl/kernel/algorithms/gywz_ote.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/gywz_ote.h" +#include "yacl/kernel/algorithms/gywz_ote.h" #include diff --git a/yacl/kernels/algorithms/gywz_ote.h b/yacl/kernel/algorithms/gywz_ote.h similarity index 98% rename from yacl/kernels/algorithms/gywz_ote.h rename to yacl/kernel/algorithms/gywz_ote.h index d9c05dd1..49dad696 100644 --- a/yacl/kernels/algorithms/gywz_ote.h +++ b/yacl/kernel/algorithms/gywz_ote.h @@ -27,7 +27,7 @@ #include "yacl/crypto/rand/rand.h" #include "yacl/crypto/tools/crhash.h" #include "yacl/crypto/tools/prg.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" /* security parameter declaration */ YACL_MODULE_DECLARE("gywz_ote", SecParam::C::INF, SecParam::S::INF); diff --git a/yacl/kernels/algorithms/gywz_ote_test.cc b/yacl/kernel/algorithms/gywz_ote_test.cc similarity index 98% rename from yacl/kernels/algorithms/gywz_ote_test.cc rename to yacl/kernel/algorithms/gywz_ote_test.cc index acea74b6..2e092fd1 100644 --- a/yacl/kernels/algorithms/gywz_ote_test.cc +++ b/yacl/kernel/algorithms/gywz_ote_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/gywz_ote.h" +#include "yacl/kernel/algorithms/gywz_ote.h" #include #include @@ -22,7 +22,7 @@ #include "yacl/base/exception.h" #include "yacl/crypto/rand/rand.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/test_util.h" #include "yacl/math/gadget.h" diff --git a/yacl/kernels/algorithms/iknp_ote.cc b/yacl/kernel/algorithms/iknp_ote.cc similarity index 99% rename from yacl/kernels/algorithms/iknp_ote.cc rename to yacl/kernel/algorithms/iknp_ote.cc index f217674c..8f6d53cb 100644 --- a/yacl/kernels/algorithms/iknp_ote.cc +++ b/yacl/kernel/algorithms/iknp_ote.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/iknp_ote.h" +#include "yacl/kernel/algorithms/iknp_ote.h" #include #include diff --git a/yacl/kernels/algorithms/iknp_ote.h b/yacl/kernel/algorithms/iknp_ote.h similarity index 98% rename from yacl/kernels/algorithms/iknp_ote.h rename to yacl/kernel/algorithms/iknp_ote.h index ee017153..8dd01918 100644 --- a/yacl/kernels/algorithms/iknp_ote.h +++ b/yacl/kernel/algorithms/iknp_ote.h @@ -20,7 +20,7 @@ #include "absl/types/span.h" #include "yacl/base/dynamic_bitset.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/link.h" #include "yacl/secparam.h" #include "yacl/utils/matrix_utils.h" diff --git a/yacl/kernels/algorithms/iknp_ote_test.cc b/yacl/kernel/algorithms/iknp_ote_test.cc similarity index 99% rename from yacl/kernels/algorithms/iknp_ote_test.cc rename to yacl/kernel/algorithms/iknp_ote_test.cc index 67e51a00..0807ec35 100644 --- a/yacl/kernels/algorithms/iknp_ote_test.cc +++ b/yacl/kernel/algorithms/iknp_ote_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/iknp_ote.h" +#include "yacl/kernel/algorithms/iknp_ote.h" #include diff --git a/yacl/kernels/algorithms/kkrt_ote.cc b/yacl/kernel/algorithms/kkrt_ote.cc similarity index 99% rename from yacl/kernels/algorithms/kkrt_ote.cc rename to yacl/kernel/algorithms/kkrt_ote.cc index 11cdf980..a38b683d 100644 --- a/yacl/kernels/algorithms/kkrt_ote.cc +++ b/yacl/kernel/algorithms/kkrt_ote.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/kkrt_ote.h" +#include "yacl/kernel/algorithms/kkrt_ote.h" #include #include diff --git a/yacl/kernels/algorithms/kkrt_ote.h b/yacl/kernel/algorithms/kkrt_ote.h similarity index 99% rename from yacl/kernels/algorithms/kkrt_ote.h rename to yacl/kernel/algorithms/kkrt_ote.h index d3e6a1ca..a03421b0 100644 --- a/yacl/kernels/algorithms/kkrt_ote.h +++ b/yacl/kernel/algorithms/kkrt_ote.h @@ -19,7 +19,7 @@ #include "absl/types/span.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/link.h" #include "yacl/secparam.h" diff --git a/yacl/kernels/algorithms/kkrt_ote_test.cc b/yacl/kernel/algorithms/kkrt_ote_test.cc similarity index 98% rename from yacl/kernels/algorithms/kkrt_ote_test.cc rename to yacl/kernel/algorithms/kkrt_ote_test.cc index 57c7193d..d302aa67 100644 --- a/yacl/kernels/algorithms/kkrt_ote_test.cc +++ b/yacl/kernel/algorithms/kkrt_ote_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/kkrt_ote.h" +#include "yacl/kernel/algorithms/kkrt_ote.h" #include #include @@ -24,7 +24,7 @@ #include "yacl/base/exception.h" #include "yacl/crypto/rand/rand.h" #include "yacl/crypto/tools/prg.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/test_util.h" namespace yacl::crypto { diff --git a/yacl/kernels/algorithms/kos_ote.cc b/yacl/kernel/algorithms/kos_ote.cc similarity index 99% rename from yacl/kernels/algorithms/kos_ote.cc rename to yacl/kernel/algorithms/kos_ote.cc index 136ceeeb..052415cf 100644 --- a/yacl/kernels/algorithms/kos_ote.cc +++ b/yacl/kernel/algorithms/kos_ote.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/kos_ote.h" +#include "yacl/kernel/algorithms/kos_ote.h" #include #include diff --git a/yacl/kernels/algorithms/kos_ote.h b/yacl/kernel/algorithms/kos_ote.h similarity index 98% rename from yacl/kernels/algorithms/kos_ote.h rename to yacl/kernel/algorithms/kos_ote.h index 0d53fef0..8281e3f5 100644 --- a/yacl/kernels/algorithms/kos_ote.h +++ b/yacl/kernel/algorithms/kos_ote.h @@ -19,7 +19,7 @@ #include "absl/types/span.h" #include "yacl/base/dynamic_bitset.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/link.h" #include "yacl/secparam.h" diff --git a/yacl/kernels/algorithms/kos_ote_test.cc b/yacl/kernel/algorithms/kos_ote_test.cc similarity index 99% rename from yacl/kernels/algorithms/kos_ote_test.cc rename to yacl/kernel/algorithms/kos_ote_test.cc index c2c0cebe..080eba0c 100644 --- a/yacl/kernels/algorithms/kos_ote_test.cc +++ b/yacl/kernel/algorithms/kos_ote_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/kos_ote.h" +#include "yacl/kernel/algorithms/kos_ote.h" #include diff --git a/yacl/kernels/algorithms/mp_vole.h b/yacl/kernel/algorithms/mp_vole.h similarity index 98% rename from yacl/kernels/algorithms/mp_vole.h rename to yacl/kernel/algorithms/mp_vole.h index 0a31ac78..4de79ba3 100644 --- a/yacl/kernels/algorithms/mp_vole.h +++ b/yacl/kernel/algorithms/mp_vole.h @@ -20,8 +20,9 @@ #include "yacl/crypto/hash/hash_utils.h" #include "yacl/crypto/rand/rand.h" #include "yacl/crypto/tools/common.h" -#include "yacl/kernels/algorithms/mpfss.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/mpfss.h" +#include "yacl/kernel/algorithms/ot_store.h" +#include "yacl/math/f2k/f2k_utils.h" #include "yacl/math/gadget.h" #include "yacl/secparam.h" diff --git a/yacl/kernels/algorithms/mp_vole_test.cc b/yacl/kernel/algorithms/mp_vole_test.cc similarity index 100% rename from yacl/kernels/algorithms/mp_vole_test.cc rename to yacl/kernel/algorithms/mp_vole_test.cc diff --git a/yacl/kernels/algorithms/mpfss.cc b/yacl/kernel/algorithms/mpfss.cc similarity index 99% rename from yacl/kernels/algorithms/mpfss.cc rename to yacl/kernel/algorithms/mpfss.cc index b195581a..00b01707 100644 --- a/yacl/kernels/algorithms/mpfss.cc +++ b/yacl/kernel/algorithms/mpfss.cc @@ -21,8 +21,8 @@ #include "yacl/base/byte_container_view.h" #include "yacl/base/int128.h" #include "yacl/crypto/tools/crhash.h" -#include "yacl/kernels/algorithms/gywz_ote.h" -#include "yacl/kernels/algorithms/sgrr_ote.h" +#include "yacl/kernel/algorithms/gywz_ote.h" +#include "yacl/kernel/algorithms/sgrr_ote.h" #include "yacl/math/f2k/f2k.h" #include "yacl/math/gadget.h" diff --git a/yacl/kernels/algorithms/mpfss.h b/yacl/kernel/algorithms/mpfss.h similarity index 99% rename from yacl/kernels/algorithms/mpfss.h rename to yacl/kernel/algorithms/mpfss.h index 47321496..228b89d9 100644 --- a/yacl/kernels/algorithms/mpfss.h +++ b/yacl/kernel/algorithms/mpfss.h @@ -19,7 +19,7 @@ /* submodules */ #include "yacl/crypto/rand/rand.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/secparam.h" /* security parameter declaration */ diff --git a/yacl/kernels/algorithms/mpfss_test.cc b/yacl/kernel/algorithms/mpfss_test.cc similarity index 100% rename from yacl/kernels/algorithms/mpfss_test.cc rename to yacl/kernel/algorithms/mpfss_test.cc diff --git a/yacl/kernels/algorithms/ot_store.cc b/yacl/kernel/algorithms/ot_store.cc similarity index 99% rename from yacl/kernels/algorithms/ot_store.cc rename to yacl/kernel/algorithms/ot_store.cc index 1086243f..19cb9335 100644 --- a/yacl/kernels/algorithms/ot_store.cc +++ b/yacl/kernel/algorithms/ot_store.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include #include diff --git a/yacl/kernels/algorithms/ot_store.h b/yacl/kernel/algorithms/ot_store.h similarity index 100% rename from yacl/kernels/algorithms/ot_store.h rename to yacl/kernel/algorithms/ot_store.h diff --git a/yacl/kernels/algorithms/ot_store_test.cc b/yacl/kernel/algorithms/ot_store_test.cc similarity index 99% rename from yacl/kernels/algorithms/ot_store_test.cc rename to yacl/kernel/algorithms/ot_store_test.cc index 5add55c7..bd95e364 100644 --- a/yacl/kernels/algorithms/ot_store_test.cc +++ b/yacl/kernel/algorithms/ot_store_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include #include diff --git a/yacl/kernels/algorithms/portable_ot_interface.cc b/yacl/kernel/algorithms/portable_ot_interface.cc similarity index 98% rename from yacl/kernels/algorithms/portable_ot_interface.cc rename to yacl/kernel/algorithms/portable_ot_interface.cc index 9db11fff..e37de380 100644 --- a/yacl/kernels/algorithms/portable_ot_interface.cc +++ b/yacl/kernel/algorithms/portable_ot_interface.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/portable_ot_interface.h" +#include "yacl/kernel/algorithms/portable_ot_interface.h" #include "simplest_ot_portable/ot_receiver.h" #include "simplest_ot_portable/ot_sender.h" diff --git a/yacl/kernels/algorithms/portable_ot_interface.h b/yacl/kernel/algorithms/portable_ot_interface.h similarity index 96% rename from yacl/kernels/algorithms/portable_ot_interface.h rename to yacl/kernel/algorithms/portable_ot_interface.h index 53ad309c..16538255 100644 --- a/yacl/kernels/algorithms/portable_ot_interface.h +++ b/yacl/kernel/algorithms/portable_ot_interface.h @@ -22,7 +22,7 @@ #error "OT interface already defined" #endif -#include "yacl/kernels/algorithms/base_ot_interface.h" +#include "yacl/kernel/algorithms/base_ot_interface.h" #include "yacl/secparam.h" /* security parameter declaration */ diff --git a/yacl/kernels/algorithms/sgrr_ote.cc b/yacl/kernel/algorithms/sgrr_ote.cc similarity index 99% rename from yacl/kernels/algorithms/sgrr_ote.cc rename to yacl/kernel/algorithms/sgrr_ote.cc index 92e3c9af..c8e360f5 100644 --- a/yacl/kernels/algorithms/sgrr_ote.cc +++ b/yacl/kernel/algorithms/sgrr_ote.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/sgrr_ote.h" +#include "yacl/kernel/algorithms/sgrr_ote.h" #include #include diff --git a/yacl/kernels/algorithms/sgrr_ote.h b/yacl/kernel/algorithms/sgrr_ote.h similarity index 99% rename from yacl/kernels/algorithms/sgrr_ote.h rename to yacl/kernel/algorithms/sgrr_ote.h index e8e900e5..729f003b 100644 --- a/yacl/kernels/algorithms/sgrr_ote.h +++ b/yacl/kernel/algorithms/sgrr_ote.h @@ -18,7 +18,7 @@ #include "absl/types/span.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/link.h" #include "yacl/secparam.h" diff --git a/yacl/kernels/algorithms/sgrr_ote_test.cc b/yacl/kernel/algorithms/sgrr_ote_test.cc similarity index 98% rename from yacl/kernels/algorithms/sgrr_ote_test.cc rename to yacl/kernel/algorithms/sgrr_ote_test.cc index f02edaa0..95c58f8d 100644 --- a/yacl/kernels/algorithms/sgrr_ote_test.cc +++ b/yacl/kernel/algorithms/sgrr_ote_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/sgrr_ote.h" +#include "yacl/kernel/algorithms/sgrr_ote.h" #include #include @@ -23,7 +23,7 @@ #include "gtest/gtest.h" #include "yacl/base/exception.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/test_util.h" #include "yacl/math/gadget.h" diff --git a/yacl/kernels/algorithms/silent_vole.cc b/yacl/kernel/algorithms/silent_vole.cc similarity index 99% rename from yacl/kernels/algorithms/silent_vole.cc rename to yacl/kernel/algorithms/silent_vole.cc index 7e10ed60..08c56e21 100644 --- a/yacl/kernels/algorithms/silent_vole.cc +++ b/yacl/kernel/algorithms/silent_vole.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/silent_vole.h" +#include "yacl/kernel/algorithms/silent_vole.h" #include #include diff --git a/yacl/kernels/algorithms/silent_vole.h b/yacl/kernel/algorithms/silent_vole.h similarity index 94% rename from yacl/kernels/algorithms/silent_vole.h rename to yacl/kernel/algorithms/silent_vole.h index 66c59fff..3f9fcc06 100644 --- a/yacl/kernels/algorithms/silent_vole.h +++ b/yacl/kernel/algorithms/silent_vole.h @@ -21,11 +21,11 @@ /* submodules */ #include "yacl/crypto/rand/rand.h" -#include "yacl/kernels/algorithms/base_vole.h" -#include "yacl/kernels/algorithms/mp_vole.h" -#include "yacl/kernels/code/code_interface.h" -#include "yacl/kernels/code/ea_code.h" -#include "yacl/kernels/code/silver_code.h" +#include "yacl/kernel/algorithms/base_vole.h" +#include "yacl/kernel/algorithms/mp_vole.h" +#include "yacl/kernel/code/code_interface.h" +#include "yacl/kernel/code/ea_code.h" +#include "yacl/kernel/code/silver_code.h" /* security parameter declaration */ YACL_MODULE_DECLARE("silent_vole", SecParam::C::k128, SecParam::S::INF); @@ -49,9 +49,9 @@ namespace yacl::crypto { // // Security assumptions: // > OT extension functionality, for more details about its implementation, see -// `yacl/kernels/algorithms/softspoken_ote.h` +// `yacl/kernel/algorithms/softspoken_ote.h` // > base VOLE and multi-point VOLE functionalities, for more details about its -// implementation, see `yacl/kernels/algorithms/mp_vole.h` +// implementation, see `yacl/kernel/algorithms/mp_vole.h` // > Dual LPN problem, for more details, please see the original papers // 1) Silver (https://eprint.iacr.org/2021/1150.pdf) Most // efficiency, but not recommended to use due to its security flaw. diff --git a/yacl/kernels/algorithms/silent_vole_test.cc b/yacl/kernel/algorithms/silent_vole_test.cc similarity index 99% rename from yacl/kernels/algorithms/silent_vole_test.cc rename to yacl/kernel/algorithms/silent_vole_test.cc index 5f057bbb..ca2d114b 100644 --- a/yacl/kernels/algorithms/silent_vole_test.cc +++ b/yacl/kernel/algorithms/silent_vole_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/silent_vole.h" +#include "yacl/kernel/algorithms/silent_vole.h" #include diff --git a/yacl/kernels/algorithms/softspoken_ote.cc b/yacl/kernel/algorithms/softspoken_ote.cc similarity index 99% rename from yacl/kernels/algorithms/softspoken_ote.cc rename to yacl/kernel/algorithms/softspoken_ote.cc index eaea1db6..de907ae6 100644 --- a/yacl/kernels/algorithms/softspoken_ote.cc +++ b/yacl/kernel/algorithms/softspoken_ote.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/softspoken_ote.h" +#include "yacl/kernel/algorithms/softspoken_ote.h" #include diff --git a/yacl/kernels/algorithms/softspoken_ote.h b/yacl/kernel/algorithms/softspoken_ote.h similarity index 98% rename from yacl/kernels/algorithms/softspoken_ote.h rename to yacl/kernel/algorithms/softspoken_ote.h index 16784b58..8503c0c1 100644 --- a/yacl/kernels/algorithms/softspoken_ote.h +++ b/yacl/kernel/algorithms/softspoken_ote.h @@ -31,9 +31,9 @@ #include "yacl/crypto/tools/crhash.h" #include "yacl/crypto/tools/prg.h" #include "yacl/crypto/tools/rp.h" -#include "yacl/kernels/algorithms/base_ot.h" -#include "yacl/kernels/algorithms/ot_store.h" -#include "yacl/kernels/algorithms/sgrr_ote.h" +#include "yacl/kernel/algorithms/base_ot.h" +#include "yacl/kernel/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/sgrr_ote.h" /* security parameter declaration */ YACL_MODULE_DECLARE("softspoken_ote", SecParam::C::k128, SecParam::S::INF); diff --git a/yacl/kernels/algorithms/softspoken_ote_test.cc b/yacl/kernel/algorithms/softspoken_ote_test.cc similarity index 99% rename from yacl/kernels/algorithms/softspoken_ote_test.cc rename to yacl/kernel/algorithms/softspoken_ote_test.cc index 4bfb6690..3ff0344e 100644 --- a/yacl/kernels/algorithms/softspoken_ote_test.cc +++ b/yacl/kernel/algorithms/softspoken_ote_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/softspoken_ote.h" +#include "yacl/kernel/algorithms/softspoken_ote.h" #include @@ -23,7 +23,7 @@ #include "yacl/base/exception.h" #include "yacl/crypto/rand/rand.h" -#include "yacl/kernels/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/ot_store.h" #include "yacl/link/test_util.h" namespace yacl::crypto { diff --git a/yacl/kernels/algorithms/x86_asm_ot_interface.cc b/yacl/kernel/algorithms/x86_asm_ot_interface.cc similarity index 98% rename from yacl/kernels/algorithms/x86_asm_ot_interface.cc rename to yacl/kernel/algorithms/x86_asm_ot_interface.cc index e7a3def6..62659a90 100644 --- a/yacl/kernels/algorithms/x86_asm_ot_interface.cc +++ b/yacl/kernel/algorithms/x86_asm_ot_interface.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/algorithms/x86_asm_ot_interface.h" +#include "yacl/kernel/algorithms/x86_asm_ot_interface.h" #include #include diff --git a/yacl/kernels/algorithms/x86_asm_ot_interface.h b/yacl/kernel/algorithms/x86_asm_ot_interface.h similarity index 95% rename from yacl/kernels/algorithms/x86_asm_ot_interface.h rename to yacl/kernel/algorithms/x86_asm_ot_interface.h index 81806c63..b1456d13 100644 --- a/yacl/kernels/algorithms/x86_asm_ot_interface.h +++ b/yacl/kernel/algorithms/x86_asm_ot_interface.h @@ -22,7 +22,7 @@ #include -#include "yacl/kernels/algorithms/base_ot_interface.h" +#include "yacl/kernel/algorithms/base_ot_interface.h" #include "yacl/secparam.h" /* security parameter declaration */ diff --git a/yacl/kernels/benchmark/BUILD.bazel b/yacl/kernel/benchmark/BUILD.bazel similarity index 73% rename from yacl/kernels/benchmark/BUILD.bazel rename to yacl/kernel/benchmark/BUILD.bazel index faf33860..23ae5c74 100644 --- a/yacl/kernels/benchmark/BUILD.bazel +++ b/yacl/kernel/benchmark/BUILD.bazel @@ -24,14 +24,14 @@ yacl_cc_binary( ], deps = [ "//yacl/crypto/rand", - "//yacl/kernels/algorithms:base_ot", - "//yacl/kernels/algorithms:ferret_ote", - "//yacl/kernels/algorithms:gywz_ote", - "//yacl/kernels/algorithms:iknp_ote", - "//yacl/kernels/algorithms:kkrt_ote", - "//yacl/kernels/algorithms:kos_ote", - "//yacl/kernels/algorithms:sgrr_ote", - "//yacl/kernels/algorithms:softspoken_ote", + "//yacl/kernel/algorithms:base_ot", + "//yacl/kernel/algorithms:ferret_ote", + "//yacl/kernel/algorithms:gywz_ote", + "//yacl/kernel/algorithms:iknp_ote", + "//yacl/kernel/algorithms:kkrt_ote", + "//yacl/kernel/algorithms:kos_ote", + "//yacl/kernel/algorithms:sgrr_ote", + "//yacl/kernel/algorithms:softspoken_ote", "//yacl/link:test_util", "@com_github_google_benchmark//:benchmark_main", "@com_google_absl//absl/numeric:bits", @@ -46,8 +46,8 @@ yacl_cc_binary( copts = AES_COPT_FLAGS, deps = [ "//yacl/crypto/rand", - "//yacl/kernels/algorithms:base_vole", - "//yacl/kernels/algorithms:silent_vole", + "//yacl/kernel/algorithms:base_vole", + "//yacl/kernel/algorithms:silent_vole", "//yacl/link:test_util", "@com_github_google_benchmark//:benchmark_main", "@com_google_absl//absl/numeric:bits", diff --git a/yacl/kernels/benchmark/ot_bench.cc b/yacl/kernel/benchmark/ot_bench.cc similarity index 97% rename from yacl/kernels/benchmark/ot_bench.cc rename to yacl/kernel/benchmark/ot_bench.cc index d2a2be01..e8a0dc99 100644 --- a/yacl/kernels/benchmark/ot_bench.cc +++ b/yacl/kernel/benchmark/ot_bench.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/benchmark/ot_bench.h" +#include "yacl/kernel/benchmark/ot_bench.h" #include #include diff --git a/yacl/kernels/benchmark/ot_bench.h b/yacl/kernel/benchmark/ot_bench.h similarity index 97% rename from yacl/kernels/benchmark/ot_bench.h rename to yacl/kernel/benchmark/ot_bench.h index 1d20a5d9..26b88cef 100644 --- a/yacl/kernels/benchmark/ot_bench.h +++ b/yacl/kernel/benchmark/ot_bench.h @@ -25,15 +25,15 @@ #include "yacl/base/exception.h" #include "yacl/base/int128.h" #include "yacl/crypto/rand/rand.h" -#include "yacl/kernels/algorithms/base_ot.h" -#include "yacl/kernels/algorithms/ferret_ote.h" -#include "yacl/kernels/algorithms/gywz_ote.h" -#include "yacl/kernels/algorithms/iknp_ote.h" -#include "yacl/kernels/algorithms/kkrt_ote.h" -#include "yacl/kernels/algorithms/kos_ote.h" -#include "yacl/kernels/algorithms/ot_store.h" -#include "yacl/kernels/algorithms/sgrr_ote.h" -#include "yacl/kernels/algorithms/softspoken_ote.h" +#include "yacl/kernel/algorithms/base_ot.h" +#include "yacl/kernel/algorithms/ferret_ote.h" +#include "yacl/kernel/algorithms/gywz_ote.h" +#include "yacl/kernel/algorithms/iknp_ote.h" +#include "yacl/kernel/algorithms/kkrt_ote.h" +#include "yacl/kernel/algorithms/kos_ote.h" +#include "yacl/kernel/algorithms/ot_store.h" +#include "yacl/kernel/algorithms/sgrr_ote.h" +#include "yacl/kernel/algorithms/softspoken_ote.h" #include "yacl/link/test_util.h" #include "yacl/utils/matrix_utils.h" diff --git a/yacl/kernels/benchmark/vole_bench.cc b/yacl/kernel/benchmark/vole_bench.cc similarity index 98% rename from yacl/kernels/benchmark/vole_bench.cc rename to yacl/kernel/benchmark/vole_bench.cc index 70f0b62e..8c228c19 100644 --- a/yacl/kernels/benchmark/vole_bench.cc +++ b/yacl/kernel/benchmark/vole_bench.cc @@ -19,12 +19,12 @@ #include "benchmark/benchmark.h" #include "yacl/base/exception.h" -#include "yacl/kernels/algorithms/base_vole.h" -#include "yacl/kernels/algorithms/silent_vole.h" +#include "yacl/kernel/algorithms/base_vole.h" +#include "yacl/kernel/algorithms/silent_vole.h" #include "yacl/link/test_util.h" // -// bazel run //yacl/kernelsle/f2k:benchmark -c opt -- +// bazel run //yacl/kernelle/f2k:benchmark -c opt -- // --benchmark_counters_tabular=true // // User Counters: diff --git a/yacl/kernels/code/BUILD.bazel b/yacl/kernel/code/BUILD.bazel similarity index 100% rename from yacl/kernels/code/BUILD.bazel rename to yacl/kernel/code/BUILD.bazel diff --git a/yacl/kernels/code/benchmark.cc b/yacl/kernel/code/benchmark.cc similarity index 97% rename from yacl/kernels/code/benchmark.cc rename to yacl/kernel/code/benchmark.cc index 19590198..f9fb383b 100644 --- a/yacl/kernels/code/benchmark.cc +++ b/yacl/kernel/code/benchmark.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/code/benchmark.h" +#include "yacl/kernel/code/benchmark.h" namespace yacl::crypto { diff --git a/yacl/kernels/code/benchmark.h b/yacl/kernel/code/benchmark.h similarity index 97% rename from yacl/kernels/code/benchmark.h rename to yacl/kernel/code/benchmark.h index c6b6ad87..ac9cf039 100644 --- a/yacl/kernels/code/benchmark.h +++ b/yacl/kernel/code/benchmark.h @@ -21,9 +21,9 @@ #include "yacl/base/aligned_vector.h" #include "yacl/crypto/rand/rand.h" -#include "yacl/kernels/code/ea_code.h" -#include "yacl/kernels/code/linear_code.h" -#include "yacl/kernels/code/silver_code.h" +#include "yacl/kernel/code/ea_code.h" +#include "yacl/kernel/code/linear_code.h" +#include "yacl/kernel/code/silver_code.h" namespace yacl::crypto { diff --git a/yacl/kernels/code/code_interface.h b/yacl/kernel/code/code_interface.h similarity index 100% rename from yacl/kernels/code/code_interface.h rename to yacl/kernel/code/code_interface.h diff --git a/yacl/kernels/code/ea_code.h b/yacl/kernel/code/ea_code.h similarity index 98% rename from yacl/kernels/code/ea_code.h rename to yacl/kernel/code/ea_code.h index 48490515..3949f358 100644 --- a/yacl/kernels/code/ea_code.h +++ b/yacl/kernel/code/ea_code.h @@ -29,8 +29,8 @@ #include "yacl/base/block.h" #include "yacl/base/exception.h" #include "yacl/base/int128.h" -#include "yacl/kernels/code/code_interface.h" -#include "yacl/kernels/code/linear_code.h" +#include "yacl/kernel/code/code_interface.h" +#include "yacl/kernel/code/linear_code.h" namespace yacl::crypto { diff --git a/yacl/kernels/code/ea_code_test.cc b/yacl/kernel/code/ea_code_test.cc similarity index 99% rename from yacl/kernels/code/ea_code_test.cc rename to yacl/kernel/code/ea_code_test.cc index 08393aef..fcf29bcb 100644 --- a/yacl/kernels/code/ea_code_test.cc +++ b/yacl/kernel/code/ea_code_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/code/ea_code.h" +#include "yacl/kernel/code/ea_code.h" #include diff --git a/yacl/kernels/code/linear_code.h b/yacl/kernel/code/linear_code.h similarity index 99% rename from yacl/kernels/code/linear_code.h rename to yacl/kernel/code/linear_code.h index 7fddf370..5a2eb4af 100644 --- a/yacl/kernels/code/linear_code.h +++ b/yacl/kernel/code/linear_code.h @@ -22,7 +22,7 @@ #include "yacl/base/exception.h" #include "yacl/base/int128.h" #include "yacl/crypto/tools/rp.h" -#include "yacl/kernels/code/code_interface.h" +#include "yacl/kernel/code/code_interface.h" #include "yacl/math/gadget.h" #ifndef __aarch64__ diff --git a/yacl/kernels/code/linear_code_test.cc b/yacl/kernel/code/linear_code_test.cc similarity index 97% rename from yacl/kernels/code/linear_code_test.cc rename to yacl/kernel/code/linear_code_test.cc index 64fcae49..0ffdc595 100644 --- a/yacl/kernels/code/linear_code_test.cc +++ b/yacl/kernel/code/linear_code_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/code/linear_code.h" +#include "yacl/kernel/code/linear_code.h" #include diff --git a/yacl/kernels/code/silver_code.cc b/yacl/kernel/code/silver_code.cc similarity index 99% rename from yacl/kernels/code/silver_code.cc rename to yacl/kernel/code/silver_code.cc index 93f858f0..1f73a12a 100644 --- a/yacl/kernels/code/silver_code.cc +++ b/yacl/kernel/code/silver_code.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/code/silver_code.h" +#include "yacl/kernel/code/silver_code.h" #include #include diff --git a/yacl/kernels/code/silver_code.h b/yacl/kernel/code/silver_code.h similarity index 99% rename from yacl/kernels/code/silver_code.h rename to yacl/kernel/code/silver_code.h index ee87f451..afaf9f55 100644 --- a/yacl/kernels/code/silver_code.h +++ b/yacl/kernel/code/silver_code.h @@ -27,7 +27,7 @@ #include "yacl/base/block.h" #include "yacl/base/exception.h" #include "yacl/base/int128.h" -#include "yacl/kernels/code/code_interface.h" +#include "yacl/kernel/code/code_interface.h" namespace yacl::crypto { diff --git a/yacl/kernels/code/silver_code_test.cc b/yacl/kernel/code/silver_code_test.cc similarity index 99% rename from yacl/kernels/code/silver_code_test.cc rename to yacl/kernel/code/silver_code_test.cc index b9e578eb..fb362827 100644 --- a/yacl/kernels/code/silver_code_test.cc +++ b/yacl/kernel/code/silver_code_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/code/silver_code.h" +#include "yacl/kernel/code/silver_code.h" #include diff --git a/yacl/kernels/kernel.h b/yacl/kernel/kernel.h similarity index 98% rename from yacl/kernels/kernel.h rename to yacl/kernel/kernel.h index 6867390c..f2ca4d38 100644 --- a/yacl/kernels/kernel.h +++ b/yacl/kernel/kernel.h @@ -35,7 +35,7 @@ class Kernel { // virtual void eval(); }; -// Stream kernels +// Stream kernel class StreamKernel : public Kernel { public: Kind kind() const override { return Kind::SingleThread; } diff --git a/yacl/kernels/svole_kernel.cc b/yacl/kernel/svole_kernel.cc similarity index 98% rename from yacl/kernels/svole_kernel.cc rename to yacl/kernel/svole_kernel.cc index 48bcd84f..0c3918c5 100644 --- a/yacl/kernels/svole_kernel.cc +++ b/yacl/kernel/svole_kernel.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/svole_kernel.h" +#include "yacl/kernel/svole_kernel.h" #include #include @@ -22,7 +22,7 @@ #include "yacl/base/exception.h" #include "yacl/crypto/tools/common.h" #include "yacl/crypto/tools/ro.h" -#include "yacl/kernels/algorithms/silent_vole.h" +#include "yacl/kernel/algorithms/silent_vole.h" #include "yacl/link/context.h" #include "yacl/utils/thread_pool.h" diff --git a/yacl/kernels/svole_kernel.h b/yacl/kernel/svole_kernel.h similarity index 95% rename from yacl/kernels/svole_kernel.h rename to yacl/kernel/svole_kernel.h index cb9b7eb7..b6581073 100644 --- a/yacl/kernels/svole_kernel.h +++ b/yacl/kernel/svole_kernel.h @@ -17,11 +17,11 @@ #include #include -#include "yacl/kernels/kernel.h" +#include "yacl/kernel/kernel.h" /* submodules */ -#include "yacl/kernels/algorithms/silent_vole.h" -#include "yacl/kernels/code/silver_code.h" +#include "yacl/kernel/algorithms/silent_vole.h" +#include "yacl/kernel/code/silver_code.h" namespace yacl::crypto { diff --git a/yacl/kernels/svole_kernel_bench.cc b/yacl/kernel/svole_kernel_bench.cc similarity index 99% rename from yacl/kernels/svole_kernel_bench.cc rename to yacl/kernel/svole_kernel_bench.cc index bea0d9ad..cc0d5e47 100644 --- a/yacl/kernels/svole_kernel_bench.cc +++ b/yacl/kernel/svole_kernel_bench.cc @@ -16,7 +16,7 @@ #include "benchmark/benchmark.h" -#include "yacl/kernels/svole_kernel.h" +#include "yacl/kernel/svole_kernel.h" #include "yacl/link/test_util.h" namespace yacl::crypto { diff --git a/yacl/kernels/svole_kernel_test.cc b/yacl/kernel/svole_kernel_test.cc similarity index 98% rename from yacl/kernels/svole_kernel_test.cc rename to yacl/kernel/svole_kernel_test.cc index 83d642e3..e0b2bc58 100644 --- a/yacl/kernels/svole_kernel_test.cc +++ b/yacl/kernel/svole_kernel_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/kernels/svole_kernel.h" +#include "yacl/kernel/svole_kernel.h" #include diff --git a/yacl/math/BUILD.bazel b/yacl/math/BUILD.bazel index 6fbd8575..19522c7b 100644 --- a/yacl/math/BUILD.bazel +++ b/yacl/math/BUILD.bazel @@ -20,8 +20,6 @@ yacl_cc_library( name = "gadget", hdrs = ["gadget.h"], deps = [ - "//yacl/base:aligned_vector", - "//yacl/math/f2k", "@com_google_absl//absl/strings", ], ) diff --git a/yacl/math/f2k/BUILD.bazel b/yacl/math/f2k/BUILD.bazel index e3e88702..5f309b2a 100644 --- a/yacl/math/f2k/BUILD.bazel +++ b/yacl/math/f2k/BUILD.bazel @@ -18,11 +18,16 @@ package(default_visibility = ["//visibility:public"]) yacl_cc_library( name = "f2k", - hdrs = ["f2k.h"], + hdrs = [ + "f2k.h", + "f2k_utils.h", + ], deps = [ + "//yacl/base:aligned_vector", "//yacl/base:block", "//yacl/base:exception", "//yacl/base:int128", + "//yacl/math:gadget", "@com_google_absl//absl/types:span", ], ) diff --git a/yacl/math/f2k/f2k.h b/yacl/math/f2k/f2k.h index bbfd3e5f..48c81e8f 100644 --- a/yacl/math/f2k/f2k.h +++ b/yacl/math/f2k/f2k.h @@ -289,4 +289,4 @@ inline uint64_t PackGf64(absl::Span data) { // inner product return GfMul64(data, absl::MakeSpan(gf64_basis.data(), size)); } -}; // namespace yacl \ No newline at end of file +}; // namespace yacl diff --git a/yacl/math/f2k/f2k_bench.cc b/yacl/math/f2k/f2k_bench.cc index 6e39480b..e4603eed 100644 --- a/yacl/math/f2k/f2k_bench.cc +++ b/yacl/math/f2k/f2k_bench.cc @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include -#include - #include "benchmark/benchmark.h" #include "yacl/crypto/rand/rand.h" @@ -221,4 +218,4 @@ BENCHMARK(BM_GfMul64_inner_product) ->Arg(1 << 22) ->Arg(1 << 23) ->Arg(1 << 24) - ->Arg(1 << 25); \ No newline at end of file + ->Arg(1 << 25); diff --git a/yacl/math/f2k/f2k_utils.h b/yacl/math/f2k/f2k_utils.h new file mode 100644 index 00000000..90f42e27 --- /dev/null +++ b/yacl/math/f2k/f2k_utils.h @@ -0,0 +1,107 @@ +// Copyright 2023 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "yacl/base/aligned_vector.h" +#include "yacl/math/f2k/f2k.h" +#include "yacl/math/gadget.h" + +namespace yacl::math { + +// ------------------------ +// f2k-field operation +// ------------------------ + +// inner-product +uint128_t inline GfMul(absl::Span a, + absl::Span b) { + return GfMul128(a, b); +} + +uint64_t inline GfMul(absl::Span a, + absl::Span b) { + return GfMul64(a, b); +} + +uint128_t inline GfMul(absl::Span a, + absl::Span b) { + UninitAlignedVector tmp(b.size()); + std::transform(b.cbegin(), b.cend(), tmp.begin(), [](const uint64_t& val) { + return static_cast(val); + }); + return GfMul128(a, absl::MakeSpan(tmp)); +} + +uint128_t inline GfMul(absl::Span a, + absl::Span b) { + return GfMul(b, a); +} + +// element-wise +uint128_t inline GfMul(uint128_t a, uint128_t b) { return GfMul128(a, b); } + +uint64_t inline GfMul(uint64_t a, uint64_t b) { return GfMul64(a, b); } + +uint128_t inline GfMul(uint128_t a, uint64_t b) { + return GfMul128(a, static_cast(b)); +} + +uint128_t inline GfMul(uint64_t a, uint128_t b) { + return GfMul128(static_cast(a), b); +} + +// ------------------------ +// f2k-Universal Hash +// ------------------------ + +// see difference between universal hash and collision-resistent hash functions: +// https://crypto.stackexchange.com/a/88247/61581 +template +T UniversalHash(T seed, absl::Span data) { + T ret = 0; + for_each(data.rbegin(), data.rend(), [&ret, &seed](const T& val) { + ret ^= val; + ret = GfMul(seed, ret); + }); + return ret; +} + +template +std::vector ExtractHashCoef(T seed, + absl::Span indexes /*sorted*/) { + std::array buff = {}; + auto max_bits = math::Log2Ceil(indexes.back()); + buff[0] = seed; + for (size_t i = 1; i <= max_bits; ++i) { + buff[i] = GfMul(buff[i - 1], buff[i - 1]); + } + + std::vector ret; + for (const auto& index : indexes) { + auto index_plus_one = index + 1; + uint64_t mask = 1; + T coef = 1; + for (size_t i = 0; i < 64 && mask <= index_plus_one; ++i) { + if (mask & index_plus_one) { + coef = GfMul(coef, buff[i]); + } + mask <<= 1; + } + ret.push_back(coef); + } + return ret; +} + +} // namespace yacl::math \ No newline at end of file diff --git a/yacl/math/gadget.h b/yacl/math/gadget.h index 5134b745..f978ab15 100644 --- a/yacl/math/gadget.h +++ b/yacl/math/gadget.h @@ -16,9 +16,7 @@ #include "absl/strings/numbers.h" -#include "yacl/base/aligned_vector.h" #include "yacl/base/exception.h" -#include "yacl/math/f2k/f2k.h" namespace yacl::math { @@ -40,88 +38,4 @@ constexpr uint64_t RoundUpTo(uint64_t x, uint64_t y) { return DivCeil(x, y) * y; } -// ------------------------ -// f2k-field operation -// ------------------------ - -// inner-product -uint128_t inline GfMul(absl::Span a, - absl::Span b) { - return GfMul128(a, b); -} - -uint64_t inline GfMul(absl::Span a, - absl::Span b) { - return GfMul64(a, b); -} - -uint128_t inline GfMul(absl::Span a, - absl::Span b) { - UninitAlignedVector tmp(b.size()); - std::transform(b.cbegin(), b.cend(), tmp.begin(), [](const uint64_t& val) { - return static_cast(val); - }); - return GfMul128(a, absl::MakeSpan(tmp)); -} - -uint128_t inline GfMul(absl::Span a, - absl::Span b) { - return GfMul(b, a); -} - -// element-wise -uint128_t inline GfMul(uint128_t a, uint128_t b) { return GfMul128(a, b); } - -uint64_t inline GfMul(uint64_t a, uint64_t b) { return GfMul64(a, b); } - -uint128_t inline GfMul(uint128_t a, uint64_t b) { - return GfMul128(a, static_cast(b)); -} - -uint128_t inline GfMul(uint64_t a, uint128_t b) { - return GfMul128(static_cast(a), b); -} - -// ------------------------ -// f2k-Universal Hash -// ------------------------ - -// see difference between universal hash and collision-resistent hash functions: -// https://crypto.stackexchange.com/a/88247/61581 -template -T UniversalHash(T seed, absl::Span data) { - T ret = 0; - for_each(data.rbegin(), data.rend(), [&ret, &seed](const T& val) { - ret ^= val; - ret = GfMul(seed, ret); - }); - return ret; -} - -template -std::vector ExtractHashCoef(T seed, - absl::Span indexes /*sorted*/) { - std::array buff = {}; - auto max_bits = math::Log2Ceil(indexes.back()); - buff[0] = seed; - for (size_t i = 1; i <= max_bits; ++i) { - buff[i] = GfMul(buff[i - 1], buff[i - 1]); - } - - std::vector ret; - for (const auto& index : indexes) { - auto index_plus_one = index + 1; - uint64_t mask = 1; - T coef = 1; - for (size_t i = 0; i < 64 && mask <= index_plus_one; ++i) { - if (mask & index_plus_one) { - coef = GfMul(coef, buff[i]); - } - mask <<= 1; - } - ret.push_back(coef); - } - return ret; -} - } // namespace yacl::math diff --git a/yacl/math/galois_field/BUILD.bazel b/yacl/math/galois_field/BUILD.bazel index 43b560b8..01935daf 100644 --- a/yacl/math/galois_field/BUILD.bazel +++ b/yacl/math/galois_field/BUILD.bazel @@ -14,42 +14,32 @@ load("//bazel:yacl.bzl", "yacl_cc_library", "yacl_cc_test") -package(default_visibility = ["//visibility:public"]) - yacl_cc_library( - name = "galois_field", + name = "gf", + visibility = ["//visibility:public"], deps = [ - "//yacl/math/galois_field/mpint_field", + ":gf_interface", + "//yacl/math/galois_field/factory:intel_factory", + "//yacl/math/galois_field/factory:mcl_factory", + "//yacl/math/galois_field/factory:mpint_factory", ], ) yacl_cc_library( - name = "sketch", - hdrs = [ - "gf_scalar.h", - "gf_vector.h", - ], + name = "gf_interface", + hdrs = ["gf.h"], + visibility = ["//yacl/math/galois_field/factory:__pkg__"], # grant visibility to factory deps = [ - ":spi", - "//yacl/io/msgpack:buffer", - "//yacl/io/msgpack:spec_traits", - "//yacl/utils:parallel", - "//yacl/utils/spi/sketch", - "@com_google_absl//absl/types:span", + "//yacl/utils/spi", ], ) -yacl_cc_library( - name = "spi", +yacl_cc_test( + name = "gf_test", srcs = [ - "gf_spi.cc", - ], - hdrs = [ - "gf_configs.h", - "gf_spi.h", + "gf_test.cc", ], deps = [ - "//yacl/math/mpint", - "//yacl/utils/spi", + ":gf", ], ) diff --git a/yacl/math/galois_field/factory/BUILD.bazel b/yacl/math/galois_field/factory/BUILD.bazel new file mode 100644 index 00000000..ae616086 --- /dev/null +++ b/yacl/math/galois_field/factory/BUILD.bazel @@ -0,0 +1,109 @@ +# Copyright 2023 Ant Group Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:yacl.bzl", "AES_COPT_FLAGS", "yacl_cc_library", "yacl_cc_test") + +package(default_visibility = ["//visibility:private"]) + +yacl_cc_library( + name = "spi", + srcs = ["gf_spi.cc"], + hdrs = [ + "gf_scalar.h", + "gf_spi.h", + "gf_vector.h", + ], + deps = [ + "//yacl/io/msgpack:buffer", + "//yacl/io/msgpack:spec_traits", + "//yacl/math/galois_field:gf_interface", + "//yacl/math/mpint", + "//yacl/utils:parallel", + "//yacl/utils/spi/sketch", + "@com_google_absl//absl/types:span", + ], +) + +yacl_cc_library( + name = "mcl_factory", + srcs = [ + "mcl_factory.cc", + ], + hdrs = ["mcl_factory.h"], + visibility = [ + "//yacl/crypto/pairing/factory:__pkg__", + "//yacl/math/galois_field:__pkg__", + ], # grant visibility + deps = [ + ":spi", + "//yacl/crypto/ecc/mcl:util", + "//yacl/crypto/pairing/factory:mcl_pairing_header", + ], + alwayslink = 1, +) + +yacl_cc_test( + name = "mcl_factory_test", + srcs = ["mcl_factory_test.cc"], + deps = [ + ":mcl_factory", + "//yacl/crypto/rand", + ], +) + +yacl_cc_library( + name = "mpint_factory", + srcs = ["mpint_factory.cc"], + hdrs = ["mpint_factory.h"], + visibility = ["//yacl/math/galois_field:__pkg__"], # grant visibility to main target + deps = [ + ":spi", + ], + alwayslink = 1, +) + +yacl_cc_test( + name = "mpint_factory_test", + srcs = ["mpint_factory_test.cc"], + deps = [ + ":mpint_factory", + ], +) + +yacl_cc_library( + name = "intel_factory", + srcs = [ + "intel_factory.cc", + ], + hdrs = ["intel_factory.h"], + copts = AES_COPT_FLAGS, + visibility = ["//yacl/math/galois_field:__pkg__"], # grant visibility to main target + deps = [ + ":spi", + "//yacl/base:block", + "//yacl/base:exception", + "//yacl/base:int128", + "//yacl/crypto/rand", + "@com_google_absl//absl/types:span", + ], + alwayslink = 1, +) + +yacl_cc_test( + name = "intel_factory_test", + srcs = ["intel_factory_test.cc"], + deps = [ + ":intel_factory", + ], +) diff --git a/yacl/math/galois_field/gf_scalar.h b/yacl/math/galois_field/factory/gf_scalar.h similarity index 99% rename from yacl/math/galois_field/gf_scalar.h rename to yacl/math/galois_field/factory/gf_scalar.h index 844e6814..af159933 100644 --- a/yacl/math/galois_field/gf_scalar.h +++ b/yacl/math/galois_field/factory/gf_scalar.h @@ -16,7 +16,7 @@ #include -#include "yacl/math/galois_field/gf_spi.h" +#include "yacl/math/galois_field/factory/gf_spi.h" #include "yacl/utils/parallel.h" #include "yacl/utils/spi/sketch/scalar_define.h" #include "yacl/utils/spi/sketch/scalar_tools.h" diff --git a/yacl/math/galois_field/gf_spi.cc b/yacl/math/galois_field/factory/gf_spi.cc similarity index 78% rename from yacl/math/galois_field/gf_spi.cc rename to yacl/math/galois_field/factory/gf_spi.cc index f6731173..dff9e6f5 100644 --- a/yacl/math/galois_field/gf_spi.cc +++ b/yacl/math/galois_field/factory/gf_spi.cc @@ -12,9 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/math/galois_field/gf_spi.h" - -#include "yacl/math/galois_field/gf_configs.h" +#include "yacl/math/galois_field/factory/gf_spi.h" namespace yacl::math { @@ -22,9 +20,4 @@ DEFINE_ARG(MPInt, Mod); DEFINE_ARG(uint64_t, Degree); DEFINE_ARG(uint64_t, MaxBitSize); -GaloisFieldFactory& GaloisFieldFactory::Instance() { - static GaloisFieldFactory factory; - return factory; -} - } // namespace yacl::math diff --git a/yacl/math/galois_field/factory/gf_spi.h b/yacl/math/galois_field/factory/gf_spi.h new file mode 100644 index 00000000..6a50bba4 --- /dev/null +++ b/yacl/math/galois_field/factory/gf_spi.h @@ -0,0 +1,25 @@ +// Copyright 2023 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "yacl/math/galois_field/gf.h" + +namespace yacl::math { + +#define REGISTER_GF_LIBRARY(lib_name, performance, checker, creator) \ + REGISTER_SPI_LIBRARY_HELPER(GaloisFieldFactory, lib_name, performance, \ + checker, creator) + +} // namespace yacl::math diff --git a/yacl/math/galois_field/gf_vector.h b/yacl/math/galois_field/factory/gf_vector.h similarity index 99% rename from yacl/math/galois_field/gf_vector.h rename to yacl/math/galois_field/factory/gf_vector.h index 3b348a76..cc44efe6 100644 --- a/yacl/math/galois_field/gf_vector.h +++ b/yacl/math/galois_field/factory/gf_vector.h @@ -16,7 +16,7 @@ #include "absl/types/span.h" -#include "yacl/math/galois_field/gf_spi.h" +#include "yacl/math/galois_field/factory/gf_spi.h" namespace yacl::math { diff --git a/yacl/math/galois_field/factory/intel_factory.cc b/yacl/math/galois_field/factory/intel_factory.cc new file mode 100644 index 00000000..b1d083ac --- /dev/null +++ b/yacl/math/galois_field/factory/intel_factory.cc @@ -0,0 +1,235 @@ +// Copyright 2023 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "yacl/math/galois_field/factory/intel_factory.h" + +#include +#include + +#include "yacl/base/block.h" + +namespace yacl::math { + +// Irreducible Polynomials of degree 128 and 64. +constexpr uint64_t kGf128Mod = (1 << 7) | (1 << 2) | (1 << 1) | 1; +constexpr uint64_t kGf64Mod = (1 << 4) | (1 << 3) | (1 << 1) | 1; + +namespace { + +// carry-less multiplication over Z_{2^128} +// ref: +// https://www.intel.com/content/dam/develop/external/us/en/documents/clmul-wp-rev-2-02-2014-04-20.pdf +// Figure 5 or Algorithm 1 +inline std::pair cl_mul_128(block x, block y) { + block low = _mm_clmulepi64_si128(x, y, 0x00); // low 64 of x, low 64 of y + block high = _mm_clmulepi64_si128(x, y, 0x11); // low 64 of x, low 64 of y + + block mid1 = _mm_clmulepi64_si128(x, y, 0x10); // low 64 of x, high 64 of y + block mid2 = _mm_clmulepi64_si128(x, y, 0x01); // high 64 of x, low 64 of y + block mid = _mm_xor_si128(mid1, mid2); + + mid1 = _mm_srli_si128(mid, 8); // mid1 = mid >> 64 + mid2 = _mm_slli_si128(mid, 8); // mid2 = mid << 64 + + high = _mm_xor_si128(high, mid1); // high ^ (mid >> 64) + low = _mm_xor_si128(low, mid2); // low ^ (mid << 64) + + return std::make_pair(high, low); +} + +inline block reduce_128(block high, block low) { + const block modulo = block(kGf128Mod); + + auto [upper, carry0] = cl_mul_128(high, modulo); + low = _mm_xor_si128(low, carry0); + + auto [zero, carry1] = cl_mul_128(upper, modulo); + low = _mm_xor_si128(low, carry1); + return low; +} + +// multiplication over Galois Field F_{2^128} +inline block gf_mul_128(block x, block y) { + auto [high, low] = cl_mul_128(x, y); + return reduce_128(high, low); +} + +// carry-less multiplication over Z_{2^64} +// ref: +// https://github.com/scipr-lab/libff/blob/9769030a06b7ab933d6c064db120019decd359f1/libff/algebra/fields/binary/gf64.cpp#L62 +inline uint128_t cl_mul_64(uint64_t x, uint64_t y) { + block rb = _mm_clmulepi64_si128(_mm_loadl_epi64((const __m128i*)&(x)), + _mm_loadl_epi64((const __m128i*)&(y)), 0x00); + return toU128(rb); +} + +inline uint64_t reduce_64(uint128_t x) { + const block modulo = block(0, kGf64Mod); + auto xb = block(x); + + // low 64 of modulo, high 64 of x + // output is 96 bits, since modulo < 2^32 + auto temp = _mm_clmulepi64_si128(modulo, xb, 0x10); + xb = _mm_xor_si128(xb, temp); + + // low 64 of modulo, high 64 of temp + // output is 64 bits, since modulo < 2^32 && high 64 of temp < 2^32 + temp = _mm_clmulepi64_si128(modulo, temp, 0x10); + xb = _mm_xor_si128(xb, temp); + return xb.as()[0]; // low 64 bit +} + +} // namespace + +// ----------------------- +// Implementaion of SPI +// ----------------------- +template <> +uint128_t IntrinsicField::Mul(const uint128_t& x, + const uint128_t& y) const { + return toU128(gf_mul_128(block(x), block(y))); +} + +template <> +uint64_t IntrinsicField::Mul(const uint64_t& x, + const uint64_t& y) const { + return reduce_64(cl_mul_64(x, y)); +} + +template <> +uint64_t IntrinsicField::Pow(const uint64_t& x, + const MPInt& y) const { + uint64_t res = 1; + uint64_t x_copy = x; + for (MPInt i = y; i >= 2_mp; i = i / 2_mp) { + if (i == 1_mp) { + res = Mul(res, x_copy); + } + x_copy = Mul(x_copy, x_copy); + } + return res; +} + +template <> +uint128_t IntrinsicField::Pow( + [[maybe_unused]] const uint128_t& x, + [[maybe_unused]] const MPInt& y) const { + YACL_THROW("Not implemented!"); + // uint128_t res = 1; + // uint128_t x_copy = x; + // for (MPInt i = y; i >= 2_mp; i = i / 2_mp) { + // if (i == 1_mp) { + // res = Mul(res, x_copy); + // } + // x_copy = Mul(x_copy, x_copy); + // } + // return res; +} + +// Computes z^{2^64-2} +// (by Fermat's little theorem, this is the correct inverse) +template <> +uint64_t IntrinsicField::Inv(const uint64_t& x) const { + YACL_ENFORCE(x != 0); + uint64_t t0 = x; // x + uint64_t t1 = Mul(t0, t0); // x^2 + uint64_t t2 = Mul(t1, t0); // x^3 + t0 = Mul(t2, t2); // x^6 + t0 = Mul(t0, t0); // x^12 + t1 = Mul(t1, t0); // x^14 + t2 = Mul(t2, t0); // x^15 + t0 = Mul(t2, t2); // x^30 + t0 = Mul(t0, t0); // x^60 + t0 = Mul(t0, t0); // x^120 + t0 = Mul(t0, t0); // x^240 + t1 = Mul(t1, t0); // x^254 + t2 = Mul(t2, t0); + t0 = Mul(t2, t2); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t1 = Mul(t1, t0); + t2 = Mul(t2, t0); + t0 = Mul(t2, t2); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t0 = Mul(t0, t0); + t1 = Mul(t1, t0); + t0 = Mul(t0, t2); + for (int i = 0; i < 32; i++) { + t0 = Mul(t0, t0); + } + t0 = Mul(t0, t1); + return t0; +} + +// Computes z^{2^128-2} +// (by Fermat's little theorem, this is the correct inverse) +template <> +uint128_t IntrinsicField::Inv(const uint128_t& x) const { + YACL_ENFORCE(x != 0); + return Pow(x, GetOrder() - 2_mp); +} + +// ----------------------- +// Register Intrinsic Lib +// ----------------------- +REGISTER_GF_LIBRARY(kIntelLib, 100, IntrinsicFieldFactory::Check, + IntrinsicFieldFactory::Create); + +std::unique_ptr IntrinsicFieldFactory::Create( + const std::string& field_name, const SpiArgs& args) { + YACL_ENFORCE(field_name == kBinaryField); + auto degree = args.GetRequired(ArgDegree); + switch (degree) { + case 64: + return std::make_unique>(); + case 128: + return std::make_unique>(); + default: + YACL_THROW( + "IntrinsicFieldFactory create failure (for F_2k), unsupported " + "degree(k) = {}", + degree); + } +} + +bool IntrinsicFieldFactory::Check(const std::string& field_name, + const SpiArgs& args) { + return field_name == kBinaryField; + auto degree = args.GetRequired(ArgDegree); + if (degree == 64 || degree == 128) { + return true; + } else { + return false; + } +} + +}; // namespace yacl::math diff --git a/yacl/math/galois_field/factory/intel_factory.h b/yacl/math/galois_field/factory/intel_factory.h new file mode 100644 index 00000000..c45d73b9 --- /dev/null +++ b/yacl/math/galois_field/factory/intel_factory.h @@ -0,0 +1,141 @@ +// Copyright 2023 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include + +#include "yacl/base/exception.h" +#include "yacl/base/int128.h" +#include "yacl/crypto/rand/rand.h" +#include "yacl/math/galois_field/factory/gf_scalar.h" + +namespace yacl::math { + +// Galois Field GF(2^n) implmentation +// +// Currently intrinsic field only supports F_{2^64} and F_{2^128}. Therefore +// this class only takes input type as uint64_t or uint128_t. +template , + std::is_same>::value, + bool> = true> +class IntrinsicField : public GFScalarSketch { + public: + std::string GetLibraryName() const override { return kIntelLib; } + std::string GetFieldName() const override { return kBinaryField; } + + MPInt GetOrder() const override { + MPInt ret = 2_mp; + ret.PowInplace(sizeof(T) * 8); + return ret; + } + + MPInt GetMulGroupOrder() const override { return GetOrder(); } + MPInt GetAddGroupOrder() const override { return GetOrder(); } + uint64_t GetExtensionDegree() const override { return sizeof(T) * 8; } + MPInt GetBaseFieldOrder() const override { return MPInt(2); } + + Item GetIdentityZero() const override { return T(0); } + Item GetIdentityOne() const override { return T(1); } + + bool IsIdentityOne(const T& x) const override { return x == 1; } + bool IsIdentityZero(const T& x) const override { return x == 0; } + bool IsInField([[maybe_unused]] const T& x) const override { return true; } + + bool Equal(const T& x, const T& y) const override { return x == y; } + + //==================================// + // operations defined on field // + //==================================// + + // get the additive inverse −a for all elements in set + T Neg(const T& x) const override { return x; } + void NegInplace([[maybe_unused]] T* x) const override {} + + // get the multiplicative inverse 1/b for every nonzero element in set + T Inv(const T& x) const override; + void InvInplace(T* x) const override { *x = Inv(*x); } + + T Add(const T& x, const T& y) const override { return x ^ y; } + void AddInplace(T* x, const T& y) const override { *x = Add(*x, y); } + + T Sub(const T& x, const T& y) const override { return x ^ y; } + void SubInplace(T* x, const T& y) const override { *x = Sub(*x, y); } + + T Mul(const T& x, const T& y) const override; + void MulInplace(T* x, const T& y) const override { *x = Mul(*x, y); } + + T Div(const T& x, const T& y) const override { return Mul(x, Inv(y)); } + void DivInplace(T* x, const T& y) const override { *x = Div(*x, y); } + + T Pow(const T& x, const MPInt& y) const override; + void PowInplace(T* x, const MPInt& y) const override { *x = Pow(*x, y); } + + // scalar version: return a random scalar element + T RandomT() const override { + T ret; + crypto::FillRand((char*)&ret, sizeof(T)); + return ret; + } + + //==================================// + // operations defined on field // + //==================================// + + T DeepCopy(const T& x) const override { return x; } + + // To human-readable string + std::string ToString(const T& x) const override { + return fmt::format("{}", x); + } + + size_t Serialize(const T& x, uint8_t* buf, size_t buf_len) const override { + YACL_ENFORCE(sizeof(T) == buf_len); + memcpy(buf, &x, buf_len); + return buf_len; + } + + T DeserializeT(ByteContainerView buffer) const override { + YACL_ENFORCE(sizeof(T) == buffer.size()); + T ret; + memcpy(&ret, buffer.data(), buffer.size()); + return ret; + } + + // compile-time utilities for generating galois field basis for uint64_t and + // uint128_t + constexpr std::array GenGfBasisArray() { + std::array basis = {0}; + uint128_t one = yacl::MakeUint128(0, 1); + for (size_t i = 0; i < sizeof(T) * 8; ++i) { + basis[i] = one << i; + } + return basis; + } +}; + +// ----------------------- +// Register this lib +// ----------------------- +class IntrinsicFieldFactory { + public: + static std::unique_ptr Create(const std::string& field_name, + const SpiArgs& args); + static bool Check(const std::string& field_name, const SpiArgs&); +}; + +} // namespace yacl::math diff --git a/yacl/math/galois_field/factory/intel_factory_test.cc b/yacl/math/galois_field/factory/intel_factory_test.cc new file mode 100644 index 00000000..59fc7fb2 --- /dev/null +++ b/yacl/math/galois_field/factory/intel_factory_test.cc @@ -0,0 +1,140 @@ +// Copyright 2023 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "yacl/math/galois_field/factory/intel_factory.h" + +#include + +#include "gtest/gtest.h" + +namespace yacl::math::test { + +TEST(IntrinsicFieldTest, Basic64Works) { + auto gf = GaloisFieldFactory::Instance().Create(kBinaryField, ArgDegree = 64); + + EXPECT_EQ(gf->GetLibraryName(), kIntelLib); + EXPECT_EQ(gf->GetFieldName(), kBinaryField); + + EXPECT_TRUE(gf->GetExtensionDegree() == 64); + EXPECT_TRUE((bool)gf->IsIdentityZero(gf->GetIdentityZero())); + EXPECT_TRUE((bool)gf->IsIdentityOne(gf->GetIdentityOne())); +} + +TEST(IntrinsicFieldTest, Basic128Works) { + auto gf = + GaloisFieldFactory::Instance().Create(kBinaryField, ArgDegree = 128); + + EXPECT_EQ(gf->GetLibraryName(), kIntelLib); + EXPECT_EQ(gf->GetFieldName(), kBinaryField); + + EXPECT_TRUE(gf->GetExtensionDegree() == 128); + EXPECT_TRUE((bool)gf->IsIdentityZero(gf->GetIdentityZero())); + EXPECT_TRUE((bool)gf->IsIdentityOne(gf->GetIdentityOne())); +} + +TEST(IntrinsicFieldTest, Scalar64Works) { + auto gf = GaloisFieldFactory::Instance().Create(kBinaryField, ArgDegree = 64); + using T = uint64_t; + + EXPECT_TRUE((bool)gf->IsIdentityZero(T(0))); + EXPECT_FALSE((bool)gf->IsIdentityZero(T(1))); + EXPECT_FALSE((bool)gf->IsIdentityOne(T(0))); + EXPECT_TRUE((bool)gf->IsIdentityOne(T(1))); + + EXPECT_TRUE((bool)gf->IsInField(T(0))); + EXPECT_TRUE((bool)gf->IsInField(T(1))); + EXPECT_TRUE((bool)gf->IsInField(T(12))); + + EXPECT_TRUE((bool)gf->Equal(T(0), T(0))); + EXPECT_FALSE((bool)gf->Equal(T(1), T(0))); + EXPECT_TRUE((bool)gf->Equal(T(12), T(12))); + + // operands // + const auto x = gf->Random(); + const auto y = gf->Random(); + const auto kOne = gf->GetIdentityOne(); + const auto kZero = gf->GetIdentityZero(); + +#define EXPECT_FIELD_EQ(x, y) EXPECT_EQ(x.As(), y.As()) + // neg + EXPECT_FIELD_EQ(x, gf->Neg(gf->Neg(x))); + EXPECT_FIELD_EQ(kZero, gf->Neg(kZero)); + + // inv + EXPECT_FIELD_EQ(x, gf->Inv(gf->Inv(x))); + EXPECT_FIELD_EQ(gf->Inv(kOne), kOne); + EXPECT_ANY_THROW(gf->Inv(kZero)); // error + + // +, - + EXPECT_FIELD_EQ(gf->Add(x, y), gf->Add(y, x)); + EXPECT_FIELD_EQ(gf->Add(x, gf->Neg(y)), gf->Sub(x, y)); + + // mul, div + const auto z = gf->Mul(x, y); + EXPECT_FIELD_EQ(gf->Mul(x, kOne), x); + EXPECT_FIELD_EQ(gf->Mul(gf->Inv(x), x), kOne); + EXPECT_FIELD_EQ(gf->Div(z, y), x); + EXPECT_FIELD_EQ(gf->Div(z, x), y); + EXPECT_FIELD_EQ(gf->Inv(x), gf->Div(kOne, x)); +#undef EXPECT_FIELD_EQ +} + +TEST(IntrinsicFieldTest, Scalar128Works) { + auto gf = + GaloisFieldFactory::Instance().Create(kBinaryField, ArgDegree = 128); + using T = uint128_t; + + EXPECT_TRUE((bool)gf->IsIdentityZero(T(0))); + EXPECT_FALSE((bool)gf->IsIdentityZero(T(1))); + EXPECT_FALSE((bool)gf->IsIdentityOne(T(0))); + EXPECT_TRUE((bool)gf->IsIdentityOne(T(1))); + + EXPECT_TRUE((bool)gf->IsInField(T(0))); + EXPECT_TRUE((bool)gf->IsInField(T(1))); + EXPECT_TRUE((bool)gf->IsInField(T(12))); + + EXPECT_TRUE((bool)gf->Equal(T(0), T(0))); + EXPECT_FALSE((bool)gf->Equal(T(1), T(0))); + EXPECT_TRUE((bool)gf->Equal(T(12), T(12))); + + // operands // + const auto x = gf->Random(); + const auto y = gf->Random(); + const auto kOne = gf->GetIdentityOne(); + const auto kZero = gf->GetIdentityZero(); + +#define EXPECT_FIELD_EQ(x, y) EXPECT_EQ(x.As(), y.As()) + // neg + EXPECT_FIELD_EQ(x, gf->Neg(gf->Neg(x))); + EXPECT_FIELD_EQ(kZero, gf->Neg(kZero)); + + // inv + // EXPECT_FIELD_EQ(x, gf->Inv(gf->Inv(x))); + // EXPECT_FIELD_EQ(gf->Inv(kOne), kOne); + EXPECT_ANY_THROW(gf->Inv(kZero)); // error + + // +, - + EXPECT_FIELD_EQ(gf->Add(x, y), gf->Add(y, x)); + EXPECT_FIELD_EQ(gf->Add(x, gf->Neg(y)), gf->Sub(x, y)); + + // mul, div + const auto z = gf->Mul(x, y); + EXPECT_FIELD_EQ(gf->Mul(x, kOne), x); + // EXPECT_FIELD_EQ(gf->Mul(gf->Inv(x), x), kOne); + // EXPECT_FIELD_EQ(gf->Div(z, y), x); + // EXPECT_FIELD_EQ(gf->Div(z, x), y); + // EXPECT_FIELD_EQ(gf->Inv(x), gf->Div(kOne, x)); +#undef EXPECT_FIELD_EQ +} +} // namespace yacl::math::test diff --git a/yacl/math/galois_field/mcl_field/mcl_field.cc b/yacl/math/galois_field/factory/mcl_factory.cc similarity index 93% rename from yacl/math/galois_field/mcl_field/mcl_field.cc rename to yacl/math/galois_field/factory/mcl_factory.cc index 3fdec702..c90eea93 100644 --- a/yacl/math/galois_field/mcl_field/mcl_field.cc +++ b/yacl/math/galois_field/factory/mcl_factory.cc @@ -12,18 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/math/galois_field/mcl_field/mcl_field.h" - -#include +#include "yacl/math/galois_field/factory/mcl_factory.h" #include "mcl/fp_tower.hpp" #include "mcl/op.hpp" #include "yacl/crypto/ecc/mcl/mcl_util.h" -#include "yacl/crypto/pairing/mcl/pairing_header.h" -#include "yacl/math/galois_field/gf_configs.h" +#include "yacl/crypto/pairing/factory/mcl_pairing_header.h" -namespace yacl::math::hmcl { +namespace yacl::math { REGISTER_GF_LIBRARY(kMclLib, 200, MclFieldFactory::Check, MclFieldFactory::Create); @@ -47,11 +44,9 @@ struct MclFieldMeta { }; const std::vector kMclFieldMetas = { -#ifdef MCL_FIELD_YACL_TEST {kPrimeField, 1, 256}, {kPrimeField, 1, 512}, {kExtensionField, 2, 512}, {kExtensionField, 6, 512}, {kExtensionField, 12, 512}, -#endif }; std::unique_ptr MclFieldFactory::Create( @@ -72,9 +67,11 @@ std::unique_ptr MclFieldFactory::Create( if (maxBitSize == 256) { return std::unique_ptr( new MclField, 1>(mod)); - } else { + } else if (maxBitSize == 512) { return std::unique_ptr( new MclField, 1>(mod)); + } else { + YACL_THROW("Unsupported parameter: maxBitSize = {}", maxBitSize); } case 2: return std::unique_ptr( @@ -92,7 +89,13 @@ std::unique_ptr MclFieldFactory::Create( bool MclFieldFactory::Check(const std::string& field_name, const SpiArgs& args) { - auto degree = args.GetOrDefault(ArgDegree, 1); + uint64_t degree; + if (field_name == kPrimeField) { + degree = args.GetOrDefault(ArgDegree, 1); + } else { + degree = args.GetRequired(ArgDegree); + } + auto maxBitSize = args.GetOrDefault(ArgMaxBitSize, 512); MclFieldMeta meta = {field_name, degree, maxBitSize}; for (auto it : kMclFieldMetas) { @@ -103,7 +106,7 @@ bool MclFieldFactory::Check(const std::string& field_name, return false; } -namespace ch = yacl::crypto::hmcl; +namespace ch = yacl::math; #define BASE_FP_SIZE ((T::BaseFp::getOp().mp.getBitSize() + 7) / 8) @@ -139,7 +142,7 @@ MPInt MclField::GetAddGroupOrder() const { template MPInt MclField::GetBaseFieldOrder() const { - return ch::Mpz2Mp(T::BaseFp::getOp().mp); + return crypto::Mpz2Mp(T::BaseFp::getOp().mp); } template @@ -241,13 +244,13 @@ void MclField::DivInplace(T* x, const T& y) const { template T MclField::Pow(const T& x, const MPInt& y) const { T ret; - T::pow(ret, x, ch::Mp2Mpz(y)); + T::pow(ret, x, crypto::Mp2Mpz(y)); return ret; } template void MclField::PowInplace(T* x, const MPInt& y) const { - T::pow(*x, *x, ch::Mp2Mpz(y)); + T::pow(*x, *x, crypto::Mp2Mpz(y)); } template @@ -320,7 +323,7 @@ MclField::MclField(const MPInt& order, Type field_type) { template MclField::MclField(const MPInt& base_prime_p, mcl::fp::Mode mode, int xi_a) { - auto base_p = ch::Mp2Mpz(base_prime_p); + auto base_p = crypto::Mp2Mpz(base_prime_p); if (degree == 1) { T::BaseFp::init(base_p, mode); order_ = base_prime_p; @@ -341,29 +344,29 @@ MclField::MclField(const MPInt& base_prime_p, mcl::fp::Mode mode, // =============================================================== // Instantiate Field for test // =============================================================== -#ifdef MCL_FIELD_YACL_TEST template class MclField; template class MclField; template class MclField; template class MclField; template class MclField; -#endif // =============================================================== // Instantiate Pairing Curve Field from template // =============================================================== +// Declare class instances for Pairing Curve template class MclField; +template class MclField; +// ONLY for test, not recommended to use in production #ifdef MCL_ALL_PAIRING_FOR_YACL template class MclField; template class MclField; template class MclField; template class MclField; -template class MclField; template class MclField; template class MclField; template class MclField; template class MclField; #endif -} // namespace yacl::math::hmcl +} // namespace yacl::math diff --git a/yacl/math/galois_field/mcl_field/mcl_field.h b/yacl/math/galois_field/factory/mcl_factory.h similarity index 92% rename from yacl/math/galois_field/mcl_field/mcl_field.h rename to yacl/math/galois_field/factory/mcl_factory.h index 4c0a5a88..9dbbc035 100644 --- a/yacl/math/galois_field/mcl_field/mcl_field.h +++ b/yacl/math/galois_field/factory/mcl_factory.h @@ -17,10 +17,9 @@ #include "mcl/fp.hpp" #include "mcl/fp_tower.hpp" -#include "yacl/crypto/pairing/mcl/pairing_header.h" -#include "yacl/math/galois_field/gf_scalar.h" +#include "yacl/math/galois_field/factory/gf_scalar.h" -namespace yacl::math::hmcl { +namespace yacl::math { class MclFieldFactory { public: @@ -106,8 +105,8 @@ class MclField : public GFScalarSketch { private: // xi_a is used for Fp2::mul_xi(), where xi = xi_a + i and i^2 = -1, see // Fp::init(int xi_a, ...) - MclField(const MPInt& base_prime_p, mcl::fp::Mode mode = mcl::fp::FP_AUTO, - int xi_a = 1); + explicit MclField(const MPInt& base_prime_p, + mcl::fp::Mode mode = mcl::fp::FP_AUTO, int xi_a = 1); // Sometimes the order_ maybe used as the subgroup order over field // For additive group, given an element $e$ in field, $e * order_ = 0$, // For multiplicative group, given an element $e$ in field, $e^(order_-1)=1$. @@ -118,12 +117,10 @@ class MclField : public GFScalarSketch { friend class MclFieldFactory; }; -#ifdef MCL_FIELD_YACL_TEST using DefaultFp = mcl::FpT<>; // size 512 using FpWithSize256 = mcl::FpT; // Max element size 256 bits using DefaultFp2 = mcl::Fp2T>; using DefaultFp6 = mcl::Fp6T>; using DefaultFp12 = mcl::Fp12T>; // size 512 -#endif -} // namespace yacl::math::hmcl +} // namespace yacl::math diff --git a/yacl/math/galois_field/mcl_field/mcl_field_test.cc b/yacl/math/galois_field/factory/mcl_factory_test.cc similarity index 81% rename from yacl/math/galois_field/mcl_field/mcl_field_test.cc rename to yacl/math/galois_field/factory/mcl_factory_test.cc index 4b4e79f2..22b51db3 100644 --- a/yacl/math/galois_field/mcl_field/mcl_field_test.cc +++ b/yacl/math/galois_field/factory/mcl_factory_test.cc @@ -12,16 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/math/galois_field/mcl_field/mcl_field.h" +#include "yacl/math/galois_field/factory/mcl_factory.h" #include "gtest/gtest.h" #include "yacl/crypto/ecc/mcl/mcl_util.h" -#include "yacl/crypto/pairing/mcl/mcl_pairing_group.h" #include "yacl/crypto/rand/rand.h" -#include "yacl/math/galois_field/gf_configs.h" +#include "yacl/math/galois_field/factory/gf_spi.h" -namespace yacl::math::hmcl::test { +namespace yacl::math::test { template class MclFieldTest : public ::testing::Test { @@ -33,13 +32,13 @@ class MclFieldTest : public ::testing::Test { bool is_sub_field_ = false; void RunAllTests() { - fmt::print("Begin to test mcl field {} \n", filed_name_); + // fmt::print("Begin to test mcl field {} \n", filed_name_); TestCompare(); TestArithmetic(); TestArithmeticVector(); // TestOrder(); TestSerialize(); - fmt::print("End to test mcl field {} \n", filed_name_); + // fmt::print("End to test mcl field {} \n", filed_name_); } void TestCompare() { @@ -185,7 +184,7 @@ class MclFieldTest : public ::testing::Test { if (!field_->GetAddGroupOrder().IsZero()) { typename T::BaseFp order_fp; // TODO: mpint 2 Fp - // order_fp.setMpz(crypto::hmcl::Mp2Mpz(order)); + // order_fp.setMpz(math::Mp2Mpz(order)); auto t = field_->Mul(f, order_fp); EXPECT_TRUE((bool)field_->Equal(t, field_->GetIdentityZero())); } @@ -214,7 +213,6 @@ class MclFieldTest : public ::testing::Test { } }; -#ifdef MCL_FIELD_YACL_TEST #define DEFAULT_FIELD_TEST(intern_type, fieldType, degree, maxBitSize) \ class Mcl##intern_type##Test \ : public MclFieldTest> { \ @@ -233,33 +231,32 @@ DEFAULT_FIELD_TEST(FpWithSize256, kPrimeField, 1, 256); DEFAULT_FIELD_TEST(DefaultFp2, kExtensionField, 2, 512); DEFAULT_FIELD_TEST(DefaultFp6, kExtensionField, 6, 512); DEFAULT_FIELD_TEST(DefaultFp12, kExtensionField, 12, 512); -#endif -// TODO: temporarily disable mcl pairing test, since its weird error on Intel -// Mac -#define DECLARE_PAIRING_FIELD_TEST_CLASS(classname, pairing_name) \ - class MclPairing##classname##GTTest \ - : public MclFieldTest { \ - void SetUp() override { \ - auto pairing = crypto::hmcl::MclPGFactory::CreateByName(pairing_name); \ - field_ = pairing->GetGroupT(); \ - filed_name_ = "MclPairing" #classname "GTField"; \ - is_sub_field_ = true; \ - } \ - }; \ - TEST_F(MclPairing##classname##GTTest, DISABLED_Works) { RunAllTests(); } +/** + * #define DECLARE_PAIRING_FIELD_TEST_CLASS(classname, pairing_name) \ + * class MclPairing##classname##GTTest \ + * : public MclFieldTest { \ + * void SetUp() override { \ + * auto pairing = math::MclPGFactory::CreateByName(pairing_name); \ + * field_ = pairing->GetGroupT(); \ + * filed_name_ = "MclPairing" #classname "GTField"; \ + * is_sub_field_ = true; \ + * } \ + * }; \ + * TEST_F(MclPairing##classname##GTTest, Works) { RunAllTests(); } + */ -DECLARE_PAIRING_FIELD_TEST_CLASS(Bls12381, "bls12-381"); +// DECLARE_PAIRING_FIELD_TEST_CLASS(Bls12381, "bls12-381"); +// DECLARE_PAIRING_FIELD_TEST_CLASS(BNSnark, "bn_snark1"); -#ifdef MCL_ALL_PAIRING_FOR_YACL -DECLARE_PAIRING_FIELD_TEST_CLASS(BN254, "bn254"); -DECLARE_PAIRING_FIELD_TEST_CLASS(BN384M, "bn382m"); -DECLARE_PAIRING_FIELD_TEST_CLASS(BN384R, "bn382r"); -DECLARE_PAIRING_FIELD_TEST_CLASS(BN462, "bn462"); -DECLARE_PAIRING_FIELD_TEST_CLASS(BNSnark, "bn_snark1"); -DECLARE_PAIRING_FIELD_TEST_CLASS(BN160, "bn160"); -DECLARE_PAIRING_FIELD_TEST_CLASS(Bls12461, "bls12-461"); -DECLARE_PAIRING_FIELD_TEST_CLASS(BN256, "bn256"); -#endif +// #ifdef MCL_ALL_PAIRING_FOR_YACL +// DECLARE_PAIRING_FIELD_TEST_CLASS(BN254, "bn254"); +// DECLARE_PAIRING_FIELD_TEST_CLASS(BN384M, "bn382m"); +// DECLARE_PAIRING_FIELD_TEST_CLASS(BN384R, "bn382r"); +// DECLARE_PAIRING_FIELD_TEST_CLASS(BN462, "bn462"); +// DECLARE_PAIRING_FIELD_TEST_CLASS(BN160, "bn160"); +// DECLARE_PAIRING_FIELD_TEST_CLASS(Bls12461, "bls12-461"); +// DECLARE_PAIRING_FIELD_TEST_CLASS(BN256, "bn256"); +// #endif -} // namespace yacl::math::hmcl::test +} // namespace yacl::math::test diff --git a/yacl/math/galois_field/mpint_field/mpint_field.cc b/yacl/math/galois_field/factory/mpint_factory.cc similarity index 96% rename from yacl/math/galois_field/mpint_field/mpint_field.cc rename to yacl/math/galois_field/factory/mpint_factory.cc index 76145bf5..4c4e8a9f 100644 --- a/yacl/math/galois_field/mpint_field/mpint_field.cc +++ b/yacl/math/galois_field/factory/mpint_factory.cc @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "yacl/math/galois_field/mpint_field/mpint_field.h" +#include "yacl/math/galois_field/factory/mpint_factory.h" -#include "yacl/math/galois_field/gf_configs.h" +#include "yacl/math/galois_field/gf.h" -namespace yacl::math::mpf { +namespace yacl::math { REGISTER_GF_LIBRARY(kMPIntLib, 100, MPIntField::Check, MPIntField::Create); @@ -148,4 +148,4 @@ MPInt MPIntField::DeserializeT(ByteContainerView buffer) const { return res; } -} // namespace yacl::math::mpf +} // namespace yacl::math diff --git a/yacl/math/galois_field/mpint_field/mpint_field.h b/yacl/math/galois_field/factory/mpint_factory.h similarity index 96% rename from yacl/math/galois_field/mpint_field/mpint_field.h rename to yacl/math/galois_field/factory/mpint_factory.h index 026e1ea7..dfafb9b3 100644 --- a/yacl/math/galois_field/mpint_field/mpint_field.h +++ b/yacl/math/galois_field/factory/mpint_factory.h @@ -16,10 +16,10 @@ #include -#include "yacl/math/galois_field/gf_scalar.h" +#include "yacl/math/galois_field/factory/gf_scalar.h" #include "yacl/math/mpint/mp_int.h" -namespace yacl::math::mpf { +namespace yacl::math { class MPIntField : public GFScalarSketch { public: @@ -80,4 +80,4 @@ class MPIntField : public GFScalarSketch { MPInt mod_; }; -} // namespace yacl::math::mpf +} // namespace yacl::math diff --git a/yacl/math/galois_field/mpint_field/mpint_field_test.cc b/yacl/math/galois_field/factory/mpint_factory_test.cc similarity index 95% rename from yacl/math/galois_field/mpint_field/mpint_field_test.cc rename to yacl/math/galois_field/factory/mpint_factory_test.cc index eaa779ad..8a16b1a2 100644 --- a/yacl/math/galois_field/mpint_field/mpint_field_test.cc +++ b/yacl/math/galois_field/factory/mpint_factory_test.cc @@ -14,14 +14,13 @@ #include "gtest/gtest.h" -#include "yacl/math/galois_field/gf_configs.h" -#include "yacl/math/galois_field/gf_spi.h" +#include "yacl/math/galois_field/factory/gf_spi.h" -namespace yacl::math::mpf::test { +namespace yacl::math::test { -class MPIntFieldTest : public testing::Test {}; +class IntrinsicFieldTest : public testing::Test {}; -TEST_F(MPIntFieldTest, AddWorks) { +TEST_F(IntrinsicFieldTest, AddWorks) { auto gf = GaloisFieldFactory::Instance().Create( kPrimeField, ArgLib = kMPIntLib, ArgMod = 13_mp); @@ -36,7 +35,7 @@ TEST_F(MPIntFieldTest, AddWorks) { EXPECT_EQ(gf->GetIdentityOne(), 1_mp); } -TEST_F(MPIntFieldTest, ScalarWorks) { +TEST_F(IntrinsicFieldTest, ScalarWorks) { auto gf = GaloisFieldFactory::Instance().Create( kPrimeField, ArgLib = kMPIntLib, ArgMod = 13_mp); @@ -124,7 +123,7 @@ TEST_F(MPIntFieldTest, ScalarWorks) { EXPECT_EQ(gf->Deserialize(buf), mp1); } -TEST_F(MPIntFieldTest, VectorWorks) { +TEST_F(IntrinsicFieldTest, VectorWorks) { auto gf = GaloisFieldFactory::Instance().Create( kPrimeField, ArgLib = kMPIntLib, ArgMod = 13_mp); @@ -205,7 +204,7 @@ TEST_F(MPIntFieldTest, VectorWorks) { EXPECT_FALSE(gf->Sub(r1, r2).IsAll(0_mp)); } -TEST_F(MPIntFieldTest, VectorIoWorks) { +TEST_F(IntrinsicFieldTest, VectorIoWorks) { MPInt mod; MPInt::RandPrimeOver(1024, &mod, PrimeType::Normal); auto gf = GaloisFieldFactory::Instance().Create( @@ -249,7 +248,7 @@ TEST_F(MPIntFieldTest, VectorIoWorks) { EXPECT_EQ(gf->Deserialize(buf), vt); } -TEST_F(MPIntFieldTest, ScalarInplaceWorks) { +TEST_F(IntrinsicFieldTest, ScalarInplaceWorks) { auto gf = GaloisFieldFactory::Instance().Create( kPrimeField, ArgLib = kMPIntLib, ArgMod = 13_mp); @@ -283,7 +282,7 @@ TEST_F(MPIntFieldTest, ScalarInplaceWorks) { ASSERT_EQ(a, 1_mp); } -TEST_F(MPIntFieldTest, VectorInplaceWorks) { +TEST_F(IntrinsicFieldTest, VectorInplaceWorks) { auto gf = GaloisFieldFactory::Instance().Create( kPrimeField, ArgLib = kMPIntLib, ArgMod = 13_mp); @@ -312,7 +311,7 @@ TEST_F(MPIntFieldTest, VectorInplaceWorks) { ASSERT_EQ(a.AsSpan(), std::vector({10_mp, 10_mp, 4_mp})); } -TEST_F(MPIntFieldTest, OrderWorks) { +TEST_F(IntrinsicFieldTest, OrderWorks) { auto gf = GaloisFieldFactory::Instance().Create( kPrimeField, ArgLib = kMPIntLib, ArgMod = 13_mp); EXPECT_EQ(gf->GetOrder(), 13_mp); @@ -325,4 +324,4 @@ TEST_F(MPIntFieldTest, OrderWorks) { EXPECT_TRUE((bool)gf->IsIdentityOne(gf->Pow(x, gf->GetMulGroupOrder()))); } -} // namespace yacl::math::mpf::test +} // namespace yacl::math::test diff --git a/yacl/math/galois_field/gf_spi.h b/yacl/math/galois_field/gf.h similarity index 72% rename from yacl/math/galois_field/gf_spi.h rename to yacl/math/galois_field/gf.h index 34c5828c..8761f934 100644 --- a/yacl/math/galois_field/gf_spi.h +++ b/yacl/math/galois_field/gf.h @@ -18,6 +18,7 @@ #include #include "yacl/math/mpint/mp_int.h" +#include "yacl/utils/spi/argument/arg_k.h" #include "yacl/utils/spi/item.h" #include "yacl/utils/spi/spi_factory.h" @@ -38,10 +39,10 @@ class GaloisField { // p. And in extension field, field order and field modulus are different and // not directly related, which is unlike in normal prime field that field // order is just field modulus. - // !Note, we will set the default order to be 0 for extension field, since the - // origin order(p^k) of extension field(degree k>1) is actually useless for - // field computation. Actually, we often deal within a subgroup(additive or - // multiplicative) over the extension field, so we provide the other two + // ! Note, we will set the default order to be 0 for extension field, since + // the origin order(p^k) of extension field(degree k>1) is actually useless + // for field computation. Actually, we often deal within a subgroup(additive + // or multiplicative) over the extension field, so we provide the other two // interfaces for `order`(GetMulGroupOrder and GetAddGroupOrder). virtual MPInt GetOrder() const = 0; virtual uint64_t GetExtensionDegree() const = 0; // the k of GF(p^k) @@ -116,13 +117,53 @@ class GaloisField { virtual Item Deserialize(ByteContainerView buffer) const = 0; }; +// ================================ // +// Registray Utils +// ================================ // + +// Field names +inline const std::string kPrimeField = "GF_p"; // require ArgMod +inline const std::string kExtensionField = "GF_p^k"; +inline const std::string kBinaryField = "GF_2^k"; + +// SPI Args + +// configs for kPrimeField, kExtensionField +DECLARE_ARG(MPInt, Mod); // the value of p in GF_p + +// configs for kExtensionField, kBinaryField +DECLARE_ARG(uint64_t, Degree); + +// configs for max bit size for underlying prime number +DECLARE_ARG(uint64_t, MaxBitSize); + +// How to use galois field factory? +// +// Example: +// +// > #include "yacl/math/galois_field/gf.h" +// > +// > void foo() { +// > auto mod = "0xffffffffffffffffffffffffffffffffffffffffffffff13"_mp; +// > auto gf = GaloisFieldFactory::Instance().Create( +// > /* field names */ kPrimeField, +// > /* spi args (optional) */ ArgMod = mod, +// > /* spi args (optional) */ ArgDegree = 1, +// > /* spi args (optional) */ ArgMaxBitSize = 512); +// > } +// class GaloisFieldFactory final : public SpiFactoryBase { public: - static GaloisFieldFactory& Instance(); + static GaloisFieldFactory& Instance() { + static GaloisFieldFactory factory; + return factory; + } }; -#define REGISTER_GF_LIBRARY(lib_name, performance, checker, creator) \ - REGISTER_SPI_LIBRARY_HELPER(GaloisFieldFactory, lib_name, performance, \ - checker, creator) +//== Supported lib list... ==// + +inline const std::string kMPIntLib = "mpint"; +inline const std::string kMclLib = "libmcl"; +inline const std::string kIntelLib = "intel"; } // namespace yacl::math diff --git a/yacl/math/galois_field/gf_configs.h b/yacl/math/galois_field/gf_configs.h deleted file mode 100644 index 18e31d4c..00000000 --- a/yacl/math/galois_field/gf_configs.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2023 Ant Group Co., Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#include "yacl/math/mpint/mp_int.h" -#include "yacl/utils/spi/argument/argument.h" - -namespace yacl::math { - -//== Field names ==// - -inline const std::string kPrimeField = "GF_p"; -inline const std::string kExtensionField = "GF_p^k"; -inline const std::string kBinaryField = "GF_2^k"; - -//== Field options... ==// - -// configs for kPrimeField, kExtensionField -DECLARE_ARG(MPInt, Mod); // the value of p in GF_p - -// configs for kExtensionField, kBinaryField -DECLARE_ARG(uint64_t, Degree); - -// configs for max bit size for underlying prime number -DECLARE_ARG(uint64_t, MaxBitSize); - -//== Supported lib list... ==// - -// Example: -// How to use mpint field? -// -// > #include "yacl/math/galois_field/gf_spi.h" -// > -// > void foo() { -// > auto gf = GaloisFieldFactory::Instance().Create("Zn", ArgMod = 13_mp); -// > auto sum = gf->Add(10_mp, 5_mp); // output 2 -// > } -// -// Note 1: Do not include any field in mpint_field dir. -// Note 2: Get mpint field instance by `GaloisFieldFactory::Instance().Create()` - -inline const std::string kMPIntLib = "mpint"; -inline const std::string kMclLib = "libmcl"; - -} // namespace yacl::math diff --git a/yacl/math/galois_field/gf_test.cc b/yacl/math/galois_field/gf_test.cc new file mode 100644 index 00000000..b4f584dc --- /dev/null +++ b/yacl/math/galois_field/gf_test.cc @@ -0,0 +1,54 @@ +// Copyright 2023 Ant Group Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "yacl/math/galois_field/gf.h" + +#include + +#include "gtest/gtest.h" + +namespace yacl::math { + +TEST(PrimeFieldTest, Works) { + // Note that: kPrimeField implmentation requires ArgMod + auto gf = GaloisFieldFactory::Instance().Create( + kPrimeField, + ArgMod = "0xffffffffffffffffffffffffffffffffffffffffffffff13"_mp); + + EXPECT_EQ(gf->GetLibraryName(), kMclLib); // kMclLib has kPrimeField + EXPECT_EQ(gf->GetFieldName(), kPrimeField); // + EXPECT_TRUE(gf->GetExtensionDegree() == 1); // default = no extension +} + +TEST(ExtensionFieldTest, Works) { + // Note that: kPrimeField implmentation requires ArgDegree and ArgMod + auto gf = GaloisFieldFactory::Instance().Create( + kExtensionField, ArgDegree = 2, + ArgMod = "0xffffffffffffffffffffffffffffffffffffffffffffff13"_mp); + + EXPECT_EQ(gf->GetLibraryName(), kMclLib); // kMclLib has kExtensionField + EXPECT_EQ(gf->GetFieldName(), kExtensionField); + EXPECT_TRUE(gf->GetExtensionDegree() == 2); +} + +TEST(BinaryTest, Works) { + // Note that: kPrimeField implmentation requires ArgDegree + auto gf = GaloisFieldFactory::Instance().Create(kBinaryField, ArgDegree = 64); + + EXPECT_EQ(gf->GetLibraryName(), kIntelLib); // kIntelLib has kBinaryField + EXPECT_EQ(gf->GetFieldName(), kBinaryField); + EXPECT_TRUE(gf->GetExtensionDegree() == 64); +} + +} // namespace yacl::math diff --git a/yacl/math/galois_field/mpint_field/mpint_field_bench.cc b/yacl/math/galois_field/mpint_field/mpint_field_bench.cc deleted file mode 100644 index 55b6b729..00000000 --- a/yacl/math/galois_field/mpint_field/mpint_field_bench.cc +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2023 Ant Group Co., Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "benchmark/benchmark.h" - -#include "yacl/math/galois_field/gf_configs.h" -#include "yacl/math/galois_field/gf_spi.h" -#include "yacl/math/mpint/mp_int.h" - -using yacl::math::MPInt; - -// state.range(0): bits of number -static void BM_MPIntAddMod(benchmark::State& state) { - MPInt m1, m2, mod; - MPInt::RandomExactBits(state.range(0), &m1); - MPInt::RandomExactBits(state.range(0), &m2); - MPInt::RandomExactBits(state.range(0) - 1, &mod); - for (auto _ : state) { - benchmark::DoNotOptimize(m1.AddMod(m2, mod)); - } -} - -// state.range(0): bits of number -static void BM_MpfAdd(benchmark::State& state) { - MPInt m1, m2, mod; - MPInt::RandomExactBits(state.range(0), &m1); - MPInt::RandomExactBits(state.range(0), &m2); - MPInt::RandomExactBits(state.range(0) - 1, &mod); - - auto spi = yacl::math::GaloisFieldFactory::Instance().Create( - yacl::math::kPrimeField, yacl::ArgLib = yacl::math::kMPIntLib, - yacl::math::ArgMod = mod); - - for (auto _ : state) { - benchmark::DoNotOptimize(spi->Add(m1, m2)); - } -} - -BENCHMARK(BM_MPIntAddMod)->Arg(64)->Arg(1024)->Arg(2048)->Arg(4096); -BENCHMARK(BM_MpfAdd)->Arg(64)->Arg(1024)->Arg(2048)->Arg(4096); - -int main() { - benchmark::RunSpecifiedBenchmarks(); - return 0; -}