From c89a041628a6d74799a26da797f59edd82e63942 Mon Sep 17 00:00:00 2001 From: exfinen <47593166+exfinen@users.noreply.github.com> Date: Wed, 5 Feb 2025 16:35:57 +0900 Subject: [PATCH 1/4] export scalar and point functions --- CMakeLists.txt | 6 + Makefile.am | 4 + README-original.md | 141 +++++++++++++++ README.md | 163 ++++------------- configure.ac | 10 + include/secp256k1_export.h | 214 ++++++++++++++++++++++ src/modules/export/Makefile.am.include | 4 + src/modules/export/generator.h | 144 +++++++++++++++ src/modules/export/main_impl.h | 241 +++++++++++++++++++++++++ src/modules/export/tests_impl.h | 87 +++++++++ src/secp256k1.c | 4 + src/tests.c | 8 + 12 files changed, 894 insertions(+), 132 deletions(-) create mode 100644 README-original.md create mode 100644 include/secp256k1_export.h create mode 100644 src/modules/export/Makefile.am.include create mode 100644 src/modules/export/generator.h create mode 100644 src/modules/export/main_impl.h create mode 100644 src/modules/export/tests_impl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 041bfa3dca..0230f57b33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,11 @@ option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON) option(SECP256K1_ENABLE_MODULE_MUSIG "Enable musig module." ON) option(SECP256K1_ENABLE_MODULE_ELLSWIFT "Enable ElligatorSwift module." ON) +option(SECP256K1_ENABLE_MODULE_EXPORT "Enable Export module." ON) +if(SECP256K1_ENABLE_MODULE_EXPORT) + add_definitions(-DENABLE_MODULE_EXPORT=1) +endif() + # Processing must be done in a topological sorting of the dependency graph # (dependent module first). if(SECP256K1_ENABLE_MODULE_ELLSWIFT) @@ -326,6 +331,7 @@ message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOV message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRAKEYS}") message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}") message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}") +message(" export .............................. ${SECP256K1_ENABLE_MODULE_EXPORT}") message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}") message("Parameters:") message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}") diff --git a/Makefile.am b/Makefile.am index a95b4809d4..0290d00807 100644 --- a/Makefile.am +++ b/Makefile.am @@ -300,3 +300,7 @@ endif if ENABLE_MODULE_ELLSWIFT include src/modules/ellswift/Makefile.am.include endif + +if ENABLE_MODULE_EXPORT +include src/modules/export/Makefile.am.include +endif diff --git a/README-original.md b/README-original.md new file mode 100644 index 0000000000..6a311aa66a --- /dev/null +++ b/README-original.md @@ -0,0 +1,141 @@ +libsecp256k1 +============ + +![Dependencies: None](https://img.shields.io/badge/dependencies-none-success) +[![irc.libera.chat #secp256k1](https://img.shields.io/badge/irc.libera.chat-%23secp256k1-success)](https://web.libera.chat/#secp256k1) + +High-performance high-assurance C library for digital signatures and other cryptographic primitives on the secp256k1 elliptic curve. + +This library is intended to be the highest quality publicly available library for cryptography on the secp256k1 curve. However, the primary focus of its development has been for usage in the Bitcoin system and usage unlike Bitcoin's may be less well tested, verified, or suffer from a less well thought out interface. Correct usage requires some care and consideration that the library is fit for your application's purpose. + +Features: +* secp256k1 ECDSA signing/verification and key generation. +* Additive and multiplicative tweaking of secret/public keys. +* Serialization/parsing of secret keys, public keys, signatures. +* Constant time, constant memory access signing and public key generation. +* Derandomized ECDSA (via RFC6979 or with a caller provided function.) +* Very efficient implementation. +* Suitable for embedded systems. +* No runtime dependencies. +* Optional module for public key recovery. +* Optional module for ECDH key exchange. +* Optional module for Schnorr signatures according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). +* Optional module for ElligatorSwift key exchange according to [BIP-324](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki). +* Optional module for MuSig2 Schnorr multi-signatures according to [BIP-327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki). + +Implementation details +---------------------- + +* General + * No runtime heap allocation. + * Extensive testing infrastructure. + * Structured to facilitate review and analysis. + * Intended to be portable to any system with a C89 compiler and uint64_t support. + * No use of floating types. + * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.") +* Field operations + * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). + * Using 5 52-bit limbs + * Using 10 26-bit limbs (including hand-optimized assembly for 32-bit ARM, by Wladimir J. van der Laan). + * This is an experimental feature that has not received enough scrutiny to satisfy the standard of quality of this library but is made available for testing and review by the community. +* Scalar operations + * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. + * Using 4 64-bit limbs (relying on __int128 support in the compiler). + * Using 8 32-bit limbs. +* Modular inverses (both field elements and scalars) based on [safegcd](https://gcd.cr.yp.to/index.html) with some modifications, and a variable-time variant (by Peter Dettman). +* Group operations + * Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7). + * Use addition between points in Jacobian and affine coordinates where possible. + * Use a unified addition/doubling formula where necessary to avoid data-dependent branches. + * Point/x comparison without a field inversion by comparison in the Jacobian coordinate space. +* Point multiplication for verification (a*P + b*G). + * Use wNAF notation for point multiplicands. + * Use a much larger window for multiples of G, using precomputed multiples. + * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. + * Use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. +* Point multiplication for signing + * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. + * Intended to be completely free of timing sidechannels for secret-key operations (on reasonable hardware/toolchains) + * Access the table with branch-free conditional moves so memory access is uniform. + * No data-dependent branches + * Optional runtime blinding which attempts to frustrate differential power analysis. + * The precomputed tables add and eventually subtract points for which no known scalar (secret key) is known, preventing even an attacker with control over the secret key used to control the data internally. + +Building with Autotools +----------------------- + + $ ./autogen.sh # Generate a ./configure script + $ ./configure # Generate a build system + $ make # Run the actual build process + $ make check # Run the test suite + $ sudo make install # Install the library into the system (optional) + +To compile optional modules (such as Schnorr signatures), you need to run `./configure` with additional flags (such as `--enable-module-schnorrsig`). Run `./configure --help` to see the full list of available flags. + +Building with CMake (experimental) +---------------------------------- + +To maintain a pristine source tree, CMake encourages to perform an out-of-source build by using a separate dedicated build tree. + +### Building on POSIX systems + + $ cmake -B build # Generate a build system in subdirectory "build" + $ cmake --build build # Run the actual build process + $ ctest --test-dir build # Run the test suite + $ sudo cmake --install build # Install the library into the system (optional) + +To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake -B build -LH` or `ccmake -B build` to see the full list of available flags. + +### Cross compiling + +To alleviate issues with cross compiling, preconfigured toolchain files are available in the `cmake` directory. +For example, to cross compile for Windows: + + $ cmake -B build -DCMAKE_TOOLCHAIN_FILE=cmake/x86_64-w64-mingw32.toolchain.cmake + +To cross compile for Android with [NDK](https://developer.android.com/ndk/guides/cmake) (using NDK's toolchain file, and assuming the `ANDROID_NDK_ROOT` environment variable has been set): + + $ cmake -B build -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 + +### Building on Windows + +To build on Windows with Visual Studio, a proper [generator](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators) must be specified for a new build tree. + +The following example assumes using of Visual Studio 2022 and CMake v3.21+. + +In "Developer Command Prompt for VS 2022": + + >cmake -G "Visual Studio 17 2022" -A x64 -B build + >cmake --build build --config RelWithDebInfo + +Usage examples +----------- +Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`. + * [ECDSA example](examples/ecdsa.c) + * [Schnorr signatures example](examples/schnorr.c) + * [Deriving a shared secret (ECDH) example](examples/ecdh.c) + * [ElligatorSwift key exchange example](examples/ellswift.c) + +To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`. + +Benchmark +------------ +If configured with `--enable-benchmark` (which is the default), binaries for benchmarking the libsecp256k1 functions will be present in the root directory after the build. + +To print the benchmark result to the command line: + + $ ./bench_name + +To create a CSV file for the benchmark result : + + $ ./bench_name | sed '2d;s/ \{1,\}//g' > bench_name.csv + +Reporting a vulnerability +------------ + +See [SECURITY.md](SECURITY.md) + +Contributing to libsecp256k1 +------------ + +See [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/README.md b/README.md index 222e5fb768..20fc6a600c 100644 --- a/README.md +++ b/README.md @@ -1,142 +1,41 @@ -libsecp256k1 -============ +# secp256k1-export -![Dependencies: None](https://img.shields.io/badge/dependencies-none-success) -[![irc.libera.chat #secp256k1](https://img.shields.io/badge/irc.libera.chat-%23secp256k1-success)](https://web.libera.chat/#secp256k1) +The Bitcoin [secp256k1](https://github.com/bitcoin-core/secp256k1/) library, based on version 0.6.0, modified to export scalar and point manipulation functions. -High-performance high-assurance C library for digital signatures and other cryptographic primitives on the secp256k1 elliptic curve. +## Usage +1. Build the library -This library is intended to be the highest quality publicly available library for cryptography on the secp256k1 curve. However, the primary focus of its development has been for usage in the Bitcoin system and usage unlike Bitcoin's may be less well tested, verified, or suffer from a less well thought out interface. Correct usage requires some care and consideration that the library is fit for your application's purpose. +```bash +./autogen.sh +./configure +make +``` -Features: -* secp256k1 ECDSA signing/verification and key generation. -* Additive and multiplicative tweaking of secret/public keys. -* Serialization/parsing of secret keys, public keys, signatures. -* Constant time, constant memory access signing and public key generation. -* Derandomized ECDSA (via RFC6979 or with a caller provided function.) -* Very efficient implementation. -* Suitable for embedded systems. -* No runtime dependencies. -* Optional module for public key recovery. -* Optional module for ECDH key exchange. -* Optional module for Schnorr signatures according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). -* Optional module for ElligatorSwift key exchange according to [BIP-324](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki). -* Optional module for MuSig2 Schnorr multi-signatures according to [BIP-327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki). +2. Link `.libs/libsecp256k1.a` or `.libs/libsecp256k1.{so,dylib}` to your project +3. Include `include/secp256k1_export.h` and call functions defined in the header -Implementation details ----------------------- +## Sample code +```c +#include +#include "secp256k1_export.h" -* General - * No runtime heap allocation. - * Extensive testing infrastructure. - * Structured to facilitate review and analysis. - * Intended to be portable to any system with a C89 compiler and uint64_t support. - * No use of floating types. - * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.") -* Field operations - * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). - * Using 5 52-bit limbs - * Using 10 26-bit limbs (including hand-optimized assembly for 32-bit ARM, by Wladimir J. van der Laan). - * This is an experimental feature that has not received enough scrutiny to satisfy the standard of quality of this library but is made available for testing and review by the community. -* Scalar operations - * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. - * Using 4 64-bit limbs (relying on __int128 support in the compiler). - * Using 8 32-bit limbs. -* Modular inverses (both field elements and scalars) based on [safegcd](https://gcd.cr.yp.to/index.html) with some modifications, and a variable-time variant (by Peter Dettman). -* Group operations - * Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7). - * Use addition between points in Jacobian and affine coordinates where possible. - * Use a unified addition/doubling formula where necessary to avoid data-dependent branches. - * Point/x comparison without a field inversion by comparison in the Jacobian coordinate space. -* Point multiplication for verification (a*P + b*G). - * Use wNAF notation for point multiplicands. - * Use a much larger window for multiples of G, using precomputed multiples. - * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. - * Use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. -* Point multiplication for signing - * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. - * Intended to be completely free of timing sidechannels for secret-key operations (on reasonable hardware/toolchains) - * Access the table with branch-free conditional moves so memory access is uniform. - * No data-dependent branches - * Optional runtime blinding which attempts to frustrate differential power analysis. - * The precomputed tables add and eventually subtract points for which no known scalar (secret key) is known, preventing even an attacker with control over the secret key used to control the data internally. +int main() { + secp256k1_gej_alias g; + secp256k1_gej_alias sum1; + secp256k1_gej_alias sum2; + secp256k1_gej_alias prod; + secp256k1_scalar four; -Building with Autotools ------------------------ + secp256k1_export_group_get_base_point(&g); + secp256k1_export_group_add(&sum1, &g, &g); + secp256k1_export_group_add(&sum2, &sum1, &sum1); - $ ./autogen.sh - $ ./configure - $ make - $ make check # run the test suite - $ sudo make install # optional + secp256k1_export_scalar_set_int(&four, 4); + secp256k1_export_group_ecmult(&prod, &four); -To compile optional modules (such as Schnorr signatures), you need to run `./configure` with additional flags (such as `--enable-module-schnorrsig`). Run `./configure --help` to see the full list of available flags. + int r = secp256k1_export_group_eq(&sum2, &prod); + printf("%s\n", r == 1 ? "equal" : "not equal"); -Building with CMake (experimental) ----------------------------------- - -To maintain a pristine source tree, CMake encourages to perform an out-of-source build by using a separate dedicated build tree. - -### Building on POSIX systems - - $ mkdir build && cd build - $ cmake .. - $ cmake --build . - $ ctest # run the test suite - $ sudo cmake --install . # optional - -To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake .. -LH` to see the full list of available flags. - -### Cross compiling - -To alleviate issues with cross compiling, preconfigured toolchain files are available in the `cmake` directory. -For example, to cross compile for Windows: - - $ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-w64-mingw32.toolchain.cmake - -To cross compile for Android with [NDK](https://developer.android.com/ndk/guides/cmake) (using NDK's toolchain file, and assuming the `ANDROID_NDK_ROOT` environment variable has been set): - - $ cmake .. -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 - -### Building on Windows - -To build on Windows with Visual Studio, a proper [generator](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators) must be specified for a new build tree. - -The following example assumes using of Visual Studio 2022 and CMake v3.21+. - -In "Developer Command Prompt for VS 2022": - - >cmake -G "Visual Studio 17 2022" -A x64 -S . -B build - >cmake --build build --config RelWithDebInfo - -Usage examples ------------ -Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`. - * [ECDSA example](examples/ecdsa.c) - * [Schnorr signatures example](examples/schnorr.c) - * [Deriving a shared secret (ECDH) example](examples/ecdh.c) - * [ElligatorSwift key exchange example](examples/ellswift.c) - -To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`. - -Benchmark ------------- -If configured with `--enable-benchmark` (which is the default), binaries for benchmarking the libsecp256k1 functions will be present in the root directory after the build. - -To print the benchmark result to the command line: - - $ ./bench_name - -To create a CSV file for the benchmark result : - - $ ./bench_name | sed '2d;s/ \{1,\}//g' > bench_name.csv - -Reporting a vulnerability ------------- - -See [SECURITY.md](SECURITY.md) - -Contributing to libsecp256k1 ------------- - -See [CONTRIBUTING.md](CONTRIBUTING.md) + return 0; +} +``` diff --git a/configure.ac b/configure.ac index f880a3578d..4aadcc338f 100644 --- a/configure.ac +++ b/configure.ac @@ -192,6 +192,10 @@ AC_ARG_ENABLE(module_ellswift, AS_HELP_STRING([--enable-module-ellswift],[enable ElligatorSwift module [default=yes]]), [], [SECP_SET_DEFAULT([enable_module_ellswift], [yes], [yes])]) +AC_ARG_ENABLE(module_export, + AS_HELP_STRING([--enable-module-export],[enable export module [default=yes]]), [], + [SECP_SET_DEFAULT([enable_module_export], [yes], [yes])]) + AC_ARG_ENABLE(external_default_callbacks, AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), [], [SECP_SET_DEFAULT([enable_external_default_callbacks], [no], [no])]) @@ -434,6 +438,10 @@ if test x"$enable_external_default_callbacks" = x"yes"; then SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_EXTERNAL_DEFAULT_CALLBACKS=1" fi +if test x"$enable_module_export" = x"yes"; then + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_EXPORT=1" +fi + ### ### Check for --enable-experimental if necessary ### @@ -463,6 +471,7 @@ AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x" AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_MUSIG], [test x"$enable_module_musig" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"]) +AM_CONDITIONAL([ENABLE_MODULE_EXPORT], [test x"$enable_module_export" = x"yes"]) AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"]) AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"]) AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"]) @@ -486,6 +495,7 @@ echo " module extrakeys = $enable_module_extrakeys" echo " module schnorrsig = $enable_module_schnorrsig" echo " module musig = $enable_module_musig" echo " module ellswift = $enable_module_ellswift" +echo " module export = $enable_module_export" echo echo " asm = $set_asm" echo " ecmult window size = $set_ecmult_window" diff --git a/include/secp256k1_export.h b/include/secp256k1_export.h new file mode 100644 index 0000000000..e2c471915a --- /dev/null +++ b/include/secp256k1_export.h @@ -0,0 +1,214 @@ +#ifndef SECP256K1_EXPORT_H +#define SECP256K1_EXPORT_H + +#include "secp256k1.h" +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* taken from "util.h" and extracted necessary part */ +#if defined(__SIZEOF_INT128__) +/* If a native 128-bit integer type exists, use int128. */ +# define SECP256K1_WIDEMUL_INT128 1 +#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) +/* On 64-bit MSVC targets (x86_64 and arm64), use int128_struct + * (which has special logic to implement using intrinsics on those systems). */ +# define SECP256K1_WIDEMUL_INT128 1 +#elif SIZE_MAX > 0xffffffff +/* Systems with 64-bit pointers (and thus registers) very likely benefit from + * using 64-bit based arithmetic (even if we need to fall back to 32x32->64 based + * multiplication logic). */ +# define SECP256K1_WIDEMUL_INT128 1 +#else +/* Lastly, fall back to int64 based arithmetic. */ +# define SECP256K1_WIDEMUL_INT64 1 +#endif + +/* expose secp256k1_scalar to outside */ + +/* taken from "scalar.h" and extracted necessary part */ +#if defined(SECP256K1_WIDEMUL_INT128) +#include "../src/scalar_4x64.h" +#elif defined(SECP256K1_WIDEMUL_INT64) +#include "../src/scalar_8x32.h" +#else +#error "Please select wide multiplication implementation" +#endif + +/* taken from field.h to expose secp256k1_fe */ + +#ifndef SECP256K1_FE_VERIFY_FIELDS +#define SECP256K1_FE_VERIFY_FIELDS +#endif + +#if defined(SECP256K1_WIDEMUL_INT128) +#include "../src/field_5x52.h" +#elif defined(SECP256K1_WIDEMUL_INT64) +#include "../src/field_10x26.h" +#else +#error "Please select wide multiplication implementation" +#endif + +/* since secp256k1_gej in group.h not accessible from outside, + this defines the identical structure with a different name */ +typedef struct { + secp256k1_fe x; + secp256k1_fe y; + secp256k1_fe z; + int infinity; +} secp256k1_gej_alias; + +/* since secp256k1_ge_storage in group.h not accessible from outside, + this defines the identical structure with a different name */ +typedef struct { + secp256k1_fe_storage x; + secp256k1_fe_storage y; +} secp256k1_ge_storage_alias; + +/* Scalar functions */ + +SECP256K1_API void secp256k1_export_scalar_clear( + secp256k1_scalar* r +); + +SECP256K1_API int secp256k1_export_scalar_eq( + const secp256k1_scalar* a, + const secp256k1_scalar* b +); + +SECP256K1_API int secp256k1_export_scalar_is_zero( + const secp256k1_scalar* a +); + +SECP256K1_API void secp256k1_export_scalar_negate( + secp256k1_scalar* r, + const secp256k1_scalar* a +); + +SECP256K1_API void secp256k1_export_scalar_inverse( + secp256k1_scalar* r, + const secp256k1_scalar* a +); + +SECP256K1_API void secp256k1_export_scalar_square( + secp256k1_scalar* r, + const secp256k1_scalar* a +); + +SECP256K1_API void secp256k1_export_scalar_cube( + secp256k1_scalar* r, + const secp256k1_scalar* a +); + +SECP256K1_API void secp256k1_export_scalar_add( + secp256k1_scalar* r, + const secp256k1_scalar* a, + const secp256k1_scalar* b +); + +SECP256K1_API void secp256k1_export_scalar_sub( + secp256k1_scalar* r, + const secp256k1_scalar* a, + const secp256k1_scalar* b +); + +SECP256K1_API void secp256k1_export_scalar_mul( + secp256k1_scalar* r, + const secp256k1_scalar* a, + const secp256k1_scalar* b +); + +SECP256K1_API void secp256k1_export_scalar_div( + secp256k1_scalar* r, + const secp256k1_scalar* a, + const secp256k1_scalar* b +); + +SECP256K1_API void secp256k1_export_scalar_set_int( + secp256k1_scalar* r, + const uint32_t n +); + +/* buf is expected to have size 32. returns buf modulo the group order */ +SECP256K1_API void secp256k1_export_scalar_set_b32( + secp256k1_scalar* r, + const uint8_t* buf +); + +SECP256K1_API void secp256k1_export_scalar_get_b32( + uint8_t (*buf)[32], + const secp256k1_scalar* a +); + +SECP256K1_API uint32_t secp256k1_export_scalar_get_bits_limb32( + uint8_t offset, + const secp256k1_scalar* a +); + +/* Group functions */ + +SECP256K1_API void secp256k1_export_group_clear( + secp256k1_gej_alias* r +); + +SECP256K1_API void secp256k1_export_group_get_base_point( + secp256k1_gej_alias* r +); + +SECP256K1_API void secp256k1_export_group_serialize( + secp256k1_ge_storage_alias *r, + const secp256k1_gej_alias *p +); + +SECP256K1_API void secp256k1_export_group_deserialize( + secp256k1_gej_alias *r, + const secp256k1_ge_storage_alias *a +); + +SECP256K1_API void secp256k1_export_group_add( + secp256k1_gej_alias* r, + const secp256k1_gej_alias* a, + const secp256k1_gej_alias* b +); + +SECP256K1_API int secp256k1_export_group_eq( + const secp256k1_gej_alias* a, + const secp256k1_gej_alias* b +); + +SECP256K1_API int secp256k1_export_group_is_infinity( + const secp256k1_gej_alias* a +); + +SECP256K1_API void secp256k1_export_group_double( + secp256k1_gej_alias* r, + const secp256k1_gej_alias* a +); + +SECP256K1_API void secp256k1_export_group_subtract( + secp256k1_gej_alias* r, + const secp256k1_gej_alias* a, + const secp256k1_gej_alias* b +); + +SECP256K1_API void secp256k1_export_group_ecmult( + secp256k1_gej_alias *r, + const secp256k1_scalar *q +); + +SECP256K1_API int secp256k1_export_group_is_valid( + const secp256k1_gej_alias* a +); + +SECP256K1_API void secp256k1_export_group_set_infinity( + secp256k1_gej_alias* r +); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_EXPORT_H */ diff --git a/src/modules/export/Makefile.am.include b/src/modules/export/Makefile.am.include new file mode 100644 index 0000000000..799c0eb1ef --- /dev/null +++ b/src/modules/export/Makefile.am.include @@ -0,0 +1,4 @@ +include_HEADERS += include/secp256k1_export.h +noinst_HEADERS += src/modules/export/generator.h +noinst_HEADERS += src/modules/export/main_impl.h +noinst_HEADERS += src/modules/export/tests_impl.h diff --git a/src/modules/export/generator.h b/src/modules/export/generator.h new file mode 100644 index 0000000000..9496962b9d --- /dev/null +++ b/src/modules/export/generator.h @@ -0,0 +1,144 @@ +/* using code in https://github.com/ElementsProject/elements/blob/master/src/secp256k1/src/modules/generator/main_impl.h */ + +/********************************************************************** + * Copyright (c) 2016 Andrew Poelstra & Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +/** Opaque data structure that stores a base point + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use secp256k1_generator_serialize and secp256k1_generator_parse. + */ +typedef struct { + unsigned char data[64]; +} secp256k1_generator; + +static void shallue_van_de_woestijne(secp256k1_ge* ge, const secp256k1_fe* t) { + /* Implements the algorithm from: + * Indifferentiable Hashing to Barreto-Naehrig Curves + * Pierre-Alain Fouque and Mehdi Tibouchi + * Latincrypt 2012 + */ + + /* Basic algorithm: + + c = sqrt(-3) + d = (c - 1)/2 + + w = c * t / (1 + b + t^2) [with b = 7] + x1 = d - t*w + x2 = -(x1 + 1) + x3 = 1 + 1/w^2 + + To avoid the 2 divisions, compute the above in numerator/denominator form: + wn = c * t + wd = 1 + 7 + t^2 + x1n = d*wd - t*wn + x1d = wd + x2n = -(x1n + wd) + x2d = wd + x3n = wd^2 + c^2 + t^2 + x3d = (c * t)^2 + + The joint denominator j = wd * c^2 * t^2, and + 1 / x1d = 1/j * c^2 * t^2 + 1 / x2d = x3d = 1/j * wd + */ + + static const secp256k1_fe c = SECP256K1_FE_CONST(0x0a2d2ba9, 0x3507f1df, 0x233770c2, 0xa797962c, 0xc61f6d15, 0xda14ecd4, 0x7d8d27ae, 0x1cd5f852); + static const secp256k1_fe d = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40); + static const secp256k1_fe b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7); + static const secp256k1_fe b_plus_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 8); + + secp256k1_fe wn, wd, x1n, x2n, x3n, x3d, jinv, tmp, x1, x2, x3, alphain, betain, gammain, y1, y2, y3; + int alphaquad, betaquad; + + secp256k1_fe_mul(&wn, &c, t); /* mag 1 */ + secp256k1_fe_sqr(&wd, t); /* mag 1 */ + secp256k1_fe_add(&wd, &b_plus_one); /* mag 2 */ + secp256k1_fe_mul(&tmp, t, &wn); /* mag 1 */ + secp256k1_fe_negate(&tmp, &tmp, 1); /* mag 2 */ + secp256k1_fe_mul(&x1n, &d, &wd); /* mag 1 */ + secp256k1_fe_add(&x1n, &tmp); /* mag 3 */ + x2n = x1n; /* mag 3 */ + secp256k1_fe_add(&x2n, &wd); /* mag 5 */ + secp256k1_fe_negate(&x2n, &x2n, 5); /* mag 6 */ + secp256k1_fe_mul(&x3d, &c, t); /* mag 1 */ + secp256k1_fe_sqr(&x3d, &x3d); /* mag 1 */ + secp256k1_fe_sqr(&x3n, &wd); /* mag 1 */ + secp256k1_fe_add(&x3n, &x3d); /* mag 2 */ + secp256k1_fe_mul(&jinv, &x3d, &wd); /* mag 1 */ + secp256k1_fe_inv(&jinv, &jinv); /* mag 1 */ + secp256k1_fe_mul(&x1, &x1n, &x3d); /* mag 1 */ + secp256k1_fe_mul(&x1, &x1, &jinv); /* mag 1 */ + secp256k1_fe_mul(&x2, &x2n, &x3d); /* mag 1 */ + secp256k1_fe_mul(&x2, &x2, &jinv); /* mag 1 */ + secp256k1_fe_mul(&x3, &x3n, &wd); /* mag 1 */ + secp256k1_fe_mul(&x3, &x3, &jinv); /* mag 1 */ + + secp256k1_fe_sqr(&alphain, &x1); /* mag 1 */ + secp256k1_fe_mul(&alphain, &alphain, &x1); /* mag 1 */ + secp256k1_fe_add(&alphain, &b); /* mag 2 */ + secp256k1_fe_sqr(&betain, &x2); /* mag 1 */ + secp256k1_fe_mul(&betain, &betain, &x2); /* mag 1 */ + secp256k1_fe_add(&betain, &b); /* mag 2 */ + secp256k1_fe_sqr(&gammain, &x3); /* mag 1 */ + secp256k1_fe_mul(&gammain, &gammain, &x3); /* mag 1 */ + secp256k1_fe_add(&gammain, &b); /* mag 2 */ + + alphaquad = secp256k1_fe_sqrt(&y1, &alphain); + betaquad = secp256k1_fe_sqrt(&y2, &betain); + secp256k1_fe_sqrt(&y3, &gammain); + + secp256k1_fe_cmov(&x1, &x2, (!alphaquad) & betaquad); + secp256k1_fe_cmov(&y1, &y2, (!alphaquad) & betaquad); + secp256k1_fe_cmov(&x1, &x3, (!alphaquad) & !betaquad); + secp256k1_fe_cmov(&y1, &y3, (!alphaquad) & !betaquad); + + secp256k1_ge_set_xy(ge, &x1, &y1); + + /* The linked algorithm from the paper uses the Jacobi symbol of t to + * determine the Jacobi symbol of the produced y coordinate. Since the + * rest of the algorithm only uses t^2, we can safely use another criterion + * as long as negation of t results in negation of the y coordinate. Here + * we choose to use t's oddness, as it is faster to determine. */ + secp256k1_fe_negate(&tmp, &ge->y, 1); + secp256k1_fe_cmov(&ge->y, &tmp, secp256k1_fe_is_odd(t)); +} + +static int secp256k1_generator_generate_internal(secp256k1_gej* gen, const uint8_t* key, const size_t key_len) { + static const unsigned char prefix1[17] = "navcoin-v8-gen1-"; + static const unsigned char prefix2[17] = "navcoin-v8-gen2-"; + secp256k1_fe t; + secp256k1_ge add; + secp256k1_sha256 sha256; + unsigned char b32[32]; + int ret = 1; + secp256k1_gej tmp_gej; + + secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_write(&sha256, prefix1, 16); + secp256k1_sha256_write(&sha256, key, key_len); + secp256k1_sha256_finalize(&sha256, b32); + ret &= secp256k1_fe_set_b32_limit(&t, b32); + shallue_van_de_woestijne(&add, &t); + + secp256k1_gej_set_ge(gen, &add); + + secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_write(&sha256, prefix2, 16); + secp256k1_sha256_write(&sha256, key, key_len); + secp256k1_sha256_finalize(&sha256, b32); + ret &= secp256k1_fe_set_b32_limit(&t, b32); + shallue_van_de_woestijne(&add, &t); + secp256k1_gej_set_ge(&tmp_gej, &add); + + secp256k1_gej_add_var(gen, gen, &tmp_gej, NULL); + + return ret; +} diff --git a/src/modules/export/main_impl.h b/src/modules/export/main_impl.h new file mode 100644 index 0000000000..4f1ea9c9c3 --- /dev/null +++ b/src/modules/export/main_impl.h @@ -0,0 +1,241 @@ +#ifndef SECP256K1_MODULE_EXPORT_MAIN_H +#define SECP256K1_MODULE_EXPORT_MAIN_H + +#include "../../../include/secp256k1_export.h" +#include "../../../include/secp256k1.h" +#include "./generator.h" + +#define ALIAS_GEJ(x) ((secp256k1_gej_alias*) x) +#define UNALIAS_GEJ(x) ((secp256k1_gej*) x) +#define UNALIAS_GE_STORAGE(x) ((secp256k1_ge_storage*) x) + +/* Scalar functions */ + +SECP256K1_API void secp256k1_export_scalar_clear( + secp256k1_scalar* r +) { + secp256k1_scalar_clear(r); +} + +SECP256K1_API int secp256k1_export_scalar_eq( + const secp256k1_scalar* a, + const secp256k1_scalar* b +) { + return secp256k1_scalar_eq(a, b) != 0; +} + +SECP256K1_API int secp256k1_export_scalar_is_zero( + const secp256k1_scalar* a +) { + return secp256k1_scalar_is_zero(a); +} + +SECP256K1_API void secp256k1_export_scalar_negate( + secp256k1_scalar* r, + const secp256k1_scalar* a +) { + secp256k1_scalar_negate(r, a); +} + +SECP256K1_API void secp256k1_export_scalar_inverse( + secp256k1_scalar* r, + const secp256k1_scalar* a +) { + secp256k1_scalar_inverse(r, a); +} + +SECP256K1_API void secp256k1_export_scalar_square( + secp256k1_scalar* r, + const secp256k1_scalar* a +) { + secp256k1_scalar_mul(r, a, a); +} + +SECP256K1_API void secp256k1_export_scalar_cube( + secp256k1_scalar* r, + const secp256k1_scalar* a +) { + secp256k1_scalar tmp; + secp256k1_scalar_mul(&tmp, a, a); + secp256k1_scalar_mul(r, &tmp, a); +} + +SECP256K1_API void secp256k1_export_scalar_add( + secp256k1_scalar* r, + const secp256k1_scalar* a, + const secp256k1_scalar* b +) { + secp256k1_scalar_add(r, a, b); +} + +SECP256K1_API void secp256k1_export_scalar_sub( + secp256k1_scalar* r, + const secp256k1_scalar* a, + const secp256k1_scalar* b +) { + secp256k1_scalar neg_b; + secp256k1_scalar_negate(&neg_b, b); + secp256k1_scalar_add(r, a, &neg_b); +} + +SECP256K1_API void secp256k1_export_scalar_mul( + secp256k1_scalar* r, + const secp256k1_scalar* a, + const secp256k1_scalar* b +) { + secp256k1_scalar_mul(r, a, b); +} + +SECP256K1_API void secp256k1_export_scalar_div( + secp256k1_scalar* r, + const secp256k1_scalar* a, + const secp256k1_scalar* b +) { + secp256k1_scalar inv_b; + secp256k1_scalar_inverse(&inv_b, b); + secp256k1_scalar_mul(r, a, &inv_b); +} + +SECP256K1_API void secp256k1_export_scalar_set_int( + secp256k1_scalar* r, + const uint32_t n +) { + secp256k1_scalar_set_int(r, n); +} + +SECP256K1_API void secp256k1_export_scalar_set_b32( + secp256k1_scalar* r, + const uint8_t *buf +) { + secp256k1_scalar_set_b32(r, buf, NULL); +} + +SECP256K1_API void secp256k1_export_scalar_get_b32( + uint8_t (*buf)[32], + const secp256k1_scalar* a +) { + secp256k1_scalar_get_b32((unsigned char *) buf, a); +} + +SECP256K1_API uint32_t secp256k1_export_scalar_get_bits_limb32( + uint8_t offset, + const secp256k1_scalar* a +) { + return secp256k1_scalar_get_bits_limb32(a, offset, 32); +} + +/* Group functions */ + +static void gej_to_ge(secp256k1_ge* r, const secp256k1_gej* a) { + secp256k1_fe z_inv, z_inv2, z_inv3; + + secp256k1_fe_inv(&z_inv, &a->z); + secp256k1_fe_sqr(&z_inv2, &z_inv); + secp256k1_fe_mul(&z_inv3, &z_inv, &z_inv2); + + secp256k1_fe_mul(&r->x, &a->x, &z_inv2); + secp256k1_fe_mul(&r->y, &a->y, &z_inv3); + + r->infinity = a->infinity; +} + +SECP256K1_API void secp256k1_export_group_clear( + secp256k1_gej_alias* r +) { + secp256k1_gej_clear(UNALIAS_GEJ(r)); +} + +SECP256K1_API void secp256k1_export_group_get_base_point( + secp256k1_gej_alias* r +) { + secp256k1_gej_set_ge(UNALIAS_GEJ(r), &secp256k1_ge_const_g); +} + +SECP256K1_API void secp256k1_export_group_serialize( + secp256k1_ge_storage_alias *r, + const secp256k1_gej_alias *a +) { + secp256k1_ge a_ge; + secp256k1_ge_set_gej(&a_ge, UNALIAS_GEJ(a)); + secp256k1_ge_to_storage(UNALIAS_GE_STORAGE(r), &a_ge); +} + +SECP256K1_API void secp256k1_export_group_deserialize( + secp256k1_gej_alias *r, + const secp256k1_ge_storage_alias *a +) { + secp256k1_ge r_ge; + secp256k1_ge_from_storage(&r_ge, UNALIAS_GE_STORAGE(a)); + secp256k1_gej_set_ge(UNALIAS_GEJ(r), &r_ge); +} + +SECP256K1_API void secp256k1_export_group_add( + secp256k1_gej_alias* r, + const secp256k1_gej_alias* a, + const secp256k1_gej_alias* b +) { + secp256k1_gej_add_var(UNALIAS_GEJ(r), UNALIAS_GEJ(a), UNALIAS_GEJ(b), NULL); +} + +SECP256K1_API int secp256k1_export_group_eq( + const secp256k1_gej_alias* a, + const secp256k1_gej_alias* b +) { + return secp256k1_gej_eq_var(UNALIAS_GEJ(a), UNALIAS_GEJ(b)); +} + +SECP256K1_API int secp256k1_export_group_is_infinity( + const secp256k1_gej_alias* a +) { + /** Check whether a group element is the point at infinity. */ + return secp256k1_gej_is_infinity(UNALIAS_GEJ(a)); +} + +SECP256K1_API void secp256k1_export_group_double( + secp256k1_gej_alias* r, + const secp256k1_gej_alias* a +) { + secp256k1_gej_double(UNALIAS_GEJ(r), UNALIAS_GEJ(a)); +} + +SECP256K1_API void secp256k1_export_group_sub( + secp256k1_gej_alias* r, + const secp256k1_gej_alias* a, + const secp256k1_gej_alias* b +) { + secp256k1_gej b_neg; + secp256k1_gej_neg(&b_neg, UNALIAS_GEJ(b)); + secp256k1_gej_add_var(UNALIAS_GEJ(r), UNALIAS_GEJ(a), &b_neg, NULL); +} + +SECP256K1_API void secp256k1_export_group_ecmult( + secp256k1_gej_alias *r, + const secp256k1_scalar *q +) { + secp256k1_gej a; + secp256k1_scalar zero; + + /* make a the identity element */ + secp256k1_gej_set_infinity(&a); + secp256k1_scalar_set_int(&zero, 0); + + /* calculate qG */ + secp256k1_ecmult(UNALIAS_GEJ(r), &a, &zero, q); +} + +SECP256K1_API int secp256k1_export_group_is_valid( + const secp256k1_gej_alias* a +) { + secp256k1_ge a_ge; + gej_to_ge(&a_ge, UNALIAS_GEJ(a)); + return secp256k1_ge_is_valid_var(&a_ge); +} + +SECP256K1_API void secp256k1_export_group_set_infinity( + secp256k1_gej_alias* r +) { + secp256k1_gej_set_infinity(UNALIAS_GEJ(r)); +} + +#endif /* SECP256K1_MODULE_EXPORT_MAIN_H */ + diff --git a/src/modules/export/tests_impl.h b/src/modules/export/tests_impl.h new file mode 100644 index 0000000000..588c886b1f --- /dev/null +++ b/src/modules/export/tests_impl.h @@ -0,0 +1,87 @@ +/* Copyright (c) 2023 The Navcoin developers + * Distributed under the MIT software license, see the accompanying + * file COPYING or http://www.opensource.org/licenses/mit-license.php. + */ + +#ifndef SECP256K1_MODULE_EXPORT_TESTS_H +#define SECP256K1_MODULE_EXPORT_TESTS_H + +#include + +static void test_group_mult(void) { + secp256k1_gej_alias g; + secp256k1_gej_alias sum1; + secp256k1_gej_alias sum2; + secp256k1_gej_alias prod; + secp256k1_scalar four; + + secp256k1_export_group_get_base_point(&g); + secp256k1_export_group_add( + &sum1, + &g, + &g + ); + secp256k1_export_group_add( + &sum2, + &sum1, + &sum1 + ); + + secp256k1_export_scalar_set_int( + &four, + 4 + ); + secp256k1_export_group_ecmult( + &prod, + &four + ); + + CHECK(secp256k1_export_group_eq( + &sum2, + &prod + )); +} + +static void test_gej_to_ge(void) { + secp256k1_gej gj; + secp256k1_ge g; + + secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); + gej_to_ge(&g, &gj); + + CHECK(secp256k1_fe_equal(&g.x, &secp256k1_ge_const_g.x)); + CHECK(secp256k1_fe_equal(&g.y, &secp256k1_ge_const_g.y)); +} + +static void test_group_serialize(void) { + secp256k1_gej pj; + secp256k1_ge_storage_alias r; + size_t i; + uint64_t exp_x[4] = { + 6481385041966929816, + 188021827762530521, + 6170039885052185351, + 8772561819708210092 + }; + uint64_t exp_y[4] = { + -7185545363635252040, + -209500633525038055, + 6747795201694173352, + 5204712524664259685 + }; + secp256k1_gej_set_ge(&pj, &secp256k1_ge_const_g); + secp256k1_export_group_serialize(&r, ALIAS_GEJ(&pj)); + + for(i=0;i<4;++i) { + CHECK(exp_x[i] == r.x.n[i]); + CHECK(exp_y[i] == r.y.n[i]); + } +} + +static void run_export_tests(void) { + test_gej_to_ge(); + test_group_serialize(); + test_group_mult(); +} + +#endif /* SECP256K1_MODULE_EXPORT_TESTS_H */ diff --git a/src/secp256k1.c b/src/secp256k1.c index a248519dfd..5e4146d50f 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -829,3 +829,7 @@ int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32, #ifdef ENABLE_MODULE_ELLSWIFT # include "modules/ellswift/main_impl.h" #endif + +#ifdef ENABLE_MODULE_EXPORT +# include "modules/export/main_impl.h" +#endif diff --git a/src/tests.c b/src/tests.c index 78533b11c2..b36c29cb84 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7455,6 +7455,10 @@ static void run_ecdsa_wycheproof(void) { # include "modules/ellswift/tests_impl.h" #endif +#ifdef ENABLE_MODULE_EXPORT +# include "modules/export/tests_impl.h" +#endif + static void run_secp256k1_memczero_test(void) { unsigned char buf1[6] = {1, 2, 3, 4, 5, 6}; unsigned char buf2[sizeof(buf1)]; @@ -7823,6 +7827,10 @@ int main(int argc, char **argv) { run_ellswift_tests(); #endif +#ifdef ENABLE_MODULE_EXPORT + run_export_tests(); +#endif + /* util tests */ run_secp256k1_memczero_test(); run_secp256k1_is_zero_array_test(); From 9acbafa9903325de7600c777bdf3fb08e43fb58c Mon Sep 17 00:00:00 2001 From: exfinen <47593166+exfinen@users.noreply.github.com> Date: Sun, 9 Feb 2025 21:22:34 +0900 Subject: [PATCH 2/4] make ecmult q*A instead of q*G --- src/modules/export/main_impl.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/modules/export/main_impl.h b/src/modules/export/main_impl.h index 4f1ea9c9c3..b2ceaea9a4 100644 --- a/src/modules/export/main_impl.h +++ b/src/modules/export/main_impl.h @@ -210,17 +210,14 @@ SECP256K1_API void secp256k1_export_group_sub( SECP256K1_API void secp256k1_export_group_ecmult( secp256k1_gej_alias *r, + const secp256k1_gej_alias* a, const secp256k1_scalar *q ) { - secp256k1_gej a; secp256k1_scalar zero; - - /* make a the identity element */ - secp256k1_gej_set_infinity(&a); secp256k1_scalar_set_int(&zero, 0); /* calculate qG */ - secp256k1_ecmult(UNALIAS_GEJ(r), &a, &zero, q); + secp256k1_ecmult(UNALIAS_GEJ(r), &a, q, &zero); } SECP256K1_API int secp256k1_export_group_is_valid( From e15eb1fe84869bb87b8de6e0c8efcaf47a51b697 Mon Sep 17 00:00:00 2001 From: exfinen <47593166+exfinen@users.noreply.github.com> Date: Sun, 9 Feb 2025 21:37:18 +0900 Subject: [PATCH 3/4] fix ecmult signature error --- include/secp256k1_export.h | 1 + src/modules/export/main_impl.h | 2 +- src/modules/export/tests_impl.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/secp256k1_export.h b/include/secp256k1_export.h index e2c471915a..376a3d87fe 100644 --- a/include/secp256k1_export.h +++ b/include/secp256k1_export.h @@ -196,6 +196,7 @@ SECP256K1_API void secp256k1_export_group_subtract( SECP256K1_API void secp256k1_export_group_ecmult( secp256k1_gej_alias *r, + const secp256k1_gej_alias* a, const secp256k1_scalar *q ); diff --git a/src/modules/export/main_impl.h b/src/modules/export/main_impl.h index b2ceaea9a4..45376a7fa1 100644 --- a/src/modules/export/main_impl.h +++ b/src/modules/export/main_impl.h @@ -217,7 +217,7 @@ SECP256K1_API void secp256k1_export_group_ecmult( secp256k1_scalar_set_int(&zero, 0); /* calculate qG */ - secp256k1_ecmult(UNALIAS_GEJ(r), &a, q, &zero); + secp256k1_ecmult(UNALIAS_GEJ(r), UNALIAS_GEJ(a), q, &zero); } SECP256K1_API int secp256k1_export_group_is_valid( diff --git a/src/modules/export/tests_impl.h b/src/modules/export/tests_impl.h index 588c886b1f..8622d82078 100644 --- a/src/modules/export/tests_impl.h +++ b/src/modules/export/tests_impl.h @@ -33,6 +33,7 @@ static void test_group_mult(void) { ); secp256k1_export_group_ecmult( &prod, + &g, &four ); From 8fb399462635b737e2263f9117f25e633f5c8341 Mon Sep 17 00:00:00 2001 From: exfinen <47593166+exfinen@users.noreply.github.com> Date: Sat, 15 Mar 2025 11:10:06 +0900 Subject: [PATCH 4/4] add field functions --- include/secp256k1_export.h | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/include/secp256k1_export.h b/include/secp256k1_export.h index 376a3d87fe..1b626c0eb6 100644 --- a/include/secp256k1_export.h +++ b/include/secp256k1_export.h @@ -22,9 +22,23 @@ extern "C" { * using 64-bit based arithmetic (even if we need to fall back to 32x32->64 based * multiplication logic). */ # define SECP256K1_WIDEMUL_INT128 1 +#endif + +/* Macro for restrict, when available and not in a VERIFY build. */ +#if defined(SECP256K1_BUILD) && defined(VERIFY) +# define SECP256K1_RESTRICT #else -/* Lastly, fall back to int64 based arithmetic. */ -# define SECP256K1_WIDEMUL_INT64 1 +# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if SECP256K1_GNUC_PREREQ(3,0) +# define SECP256K1_RESTRICT __restrict__ +# elif (defined(_MSC_VER) && _MSC_VER >= 1400) +# define SECP256K1_RESTRICT __restrict +# else +# define SECP256K1_RESTRICT +# endif +# else +# define SECP256K1_RESTRICT restrict +# endif #endif /* expose secp256k1_scalar to outside */ @@ -32,8 +46,6 @@ extern "C" { /* taken from "scalar.h" and extracted necessary part */ #if defined(SECP256K1_WIDEMUL_INT128) #include "../src/scalar_4x64.h" -#elif defined(SECP256K1_WIDEMUL_INT64) -#include "../src/scalar_8x32.h" #else #error "Please select wide multiplication implementation" #endif @@ -46,8 +58,6 @@ extern "C" { #if defined(SECP256K1_WIDEMUL_INT128) #include "../src/field_5x52.h" -#elif defined(SECP256K1_WIDEMUL_INT64) -#include "../src/field_10x26.h" #else #error "Please select wide multiplication implementation" #endif @@ -68,6 +78,20 @@ typedef struct { secp256k1_fe_storage y; } secp256k1_ge_storage_alias; +/* Field functions */ + +extern int secp256k1_fe_is_zero(const secp256k1_fe *a); + +extern void secp256k1_fe_set_int(secp256k1_fe *r, int a); + +extern void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a); + +extern void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); + +extern void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a); + +extern void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a); + /* Scalar functions */ SECP256K1_API void secp256k1_export_scalar_clear(