├── .cirrus.yml ├── .gitattributes ├── .github ├── actions │ ├── install-homebrew-valgrind │ │ └── action.yml │ └── run-in-docker-action │ │ └── action.yml └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── CMakeLists.txt ├── CMakePresets.json ├── CONTRIBUTING.md ├── COPYING ├── Makefile.am ├── README.md ├── SECURITY.md ├── autogen.sh ├── build-aux └── m4 │ └── bitcoin_secp.m4 ├── ci ├── ci.sh └── linux-debian.Dockerfile ├── cmake ├── AllTargetsCompileOptions.cmake ├── CheckArm32Assembly.cmake ├── CheckStringOptionValue.cmake ├── CheckX86_64Assembly.cmake ├── FindValgrind.cmake ├── GeneratePkgConfigFile.cmake ├── TryAppendCFlags.cmake ├── arm-linux-gnueabihf.toolchain.cmake ├── config.cmake.in ├── source_arm32.s └── x86_64-w64-mingw32.toolchain.cmake ├── configure.ac ├── contrib ├── lax_der_parsing.c ├── lax_der_parsing.h ├── lax_der_privatekey_parsing.c ├── lax_der_privatekey_parsing.h ├── musig2-vectors.py └── sync-upstream.sh ├── doc ├── ellswift.md ├── musig-spec.mediawiki ├── release-process.md └── safegcd_implementation.md ├── examples ├── CMakeLists.txt ├── EXAMPLES_COPYING ├── ecdh.c ├── ecdsa.c ├── examples_util.h ├── musig.c └── schnorr.c ├── include ├── secp256k1.h ├── secp256k1_bppp.h ├── secp256k1_ecdh.h ├── secp256k1_ecdsa_adaptor.h ├── secp256k1_ecdsa_s2c.h ├── secp256k1_ellswift.h ├── secp256k1_extrakeys.h ├── secp256k1_generator.h ├── secp256k1_musig.h ├── secp256k1_preallocated.h ├── secp256k1_rangeproof.h ├── secp256k1_recovery.h ├── secp256k1_schnorrsig.h ├── secp256k1_schnorrsig_halfagg.h ├── secp256k1_surjectionproof.h └── secp256k1_whitelist.h ├── libsecp256k1.pc.in ├── sage ├── gen_exhaustive_groups.sage ├── gen_split_lambda_constants.sage ├── group_prover.sage ├── prove_group_implementations.sage ├── secp256k1_params.sage ├── shallue_van_de_woestijne.sage └── weierstrass_prover.sage ├── src ├── CMakeLists.txt ├── asm │ └── field_10x26_arm.s ├── assumptions.h ├── bench.c ├── bench.h ├── bench_bppp.c ├── bench_ecmult.c ├── bench_generator.c ├── bench_internal.c ├── bench_rangeproof.c ├── bench_whitelist.c ├── checkmem.h ├── ctime_tests.c ├── eccommit.h ├── eccommit_impl.h ├── ecdsa.h ├── ecdsa_impl.h ├── eckey.h ├── eckey_impl.h ├── ecmult.h ├── ecmult_compute_table.h ├── ecmult_compute_table_impl.h ├── ecmult_const.h ├── ecmult_const_impl.h ├── ecmult_gen.h ├── ecmult_gen_compute_table.h ├── ecmult_gen_compute_table_impl.h ├── ecmult_gen_impl.h ├── ecmult_impl.h ├── field.h ├── field_10x26.h ├── field_10x26_impl.h ├── field_5x52.h ├── field_5x52_impl.h ├── field_5x52_int128_impl.h ├── field_impl.h ├── group.h ├── group_impl.h ├── hash.h ├── hash_impl.h ├── int128.h ├── int128_impl.h ├── int128_native.h ├── int128_native_impl.h ├── int128_struct.h ├── int128_struct_impl.h ├── modinv32.h ├── modinv32_impl.h ├── modinv64.h ├── modinv64_impl.h ├── modules │ ├── bppp │ │ ├── Makefile.am.include │ │ ├── bppp_norm_product_impl.h │ │ ├── bppp_transcript_impl.h │ │ ├── bppp_util.h │ │ ├── main.h │ │ ├── main_impl.h │ │ ├── test_vectors │ │ │ ├── prove.h │ │ │ └── verify.h │ │ └── tests_impl.h │ ├── ecdh │ │ ├── Makefile.am.include │ │ ├── bench_impl.h │ │ ├── main_impl.h │ │ └── tests_impl.h │ ├── ecdsa_adaptor │ │ ├── Makefile.am.include │ │ ├── dleq_impl.h │ │ ├── main_impl.h │ │ └── tests_impl.h │ ├── ecdsa_s2c │ │ ├── Makefile.am.include │ │ ├── main_impl.h │ │ └── tests_impl.h │ ├── ellswift │ │ ├── Makefile.am.include │ │ ├── bench_impl.h │ │ ├── main_impl.h │ │ ├── tests_exhaustive_impl.h │ │ └── tests_impl.h │ ├── extrakeys │ │ ├── Makefile.am.include │ │ ├── hsort.h │ │ ├── hsort_impl.h │ │ ├── main_impl.h │ │ ├── tests_exhaustive_impl.h │ │ └── tests_impl.h │ ├── generator │ │ ├── Makefile.am.include │ │ ├── main_impl.h │ │ ├── pedersen.h │ │ ├── pedersen_impl.h │ │ └── tests_impl.h │ ├── musig │ │ ├── Makefile.am.include │ │ ├── adaptor_impl.h │ │ ├── keyagg.h │ │ ├── keyagg_impl.h │ │ ├── main_impl.h │ │ ├── musig.md │ │ ├── session.h │ │ ├── session_impl.h │ │ ├── tests_impl.h │ │ └── vectors.h │ ├── rangeproof │ │ ├── Makefile.am.include │ │ ├── borromean.h │ │ ├── borromean_impl.h │ │ ├── main_impl.h │ │ ├── rangeproof.h │ │ ├── rangeproof_impl.h │ │ └── tests_impl.h │ ├── recovery │ │ ├── Makefile.am.include │ │ ├── bench_impl.h │ │ ├── main_impl.h │ │ ├── tests_exhaustive_impl.h │ │ └── tests_impl.h │ ├── schnorrsig │ │ ├── Makefile.am.include │ │ ├── bench_impl.h │ │ ├── main_impl.h │ │ ├── tests_exhaustive_impl.h │ │ └── tests_impl.h │ ├── schnorrsig_halfagg │ │ ├── Makefile.am.include │ │ ├── main_impl.h │ │ └── tests_impl.h │ ├── surjection │ │ ├── Makefile.am.include │ │ ├── main_impl.h │ │ ├── surjection.h │ │ ├── surjection.md │ │ ├── surjection_impl.h │ │ └── tests_impl.h │ └── whitelist │ │ ├── Makefile.am.include │ │ ├── main_impl.h │ │ ├── tests_impl.h │ │ ├── whitelist.md │ │ └── whitelist_impl.h ├── precompute_ecmult.c ├── precompute_ecmult_gen.c ├── precomputed_ecmult.c ├── precomputed_ecmult.h ├── precomputed_ecmult_gen.c ├── precomputed_ecmult_gen.h ├── scalar.h ├── scalar_4x64.h ├── scalar_4x64_impl.h ├── scalar_8x32.h ├── scalar_8x32_impl.h ├── scalar_impl.h ├── scalar_low.h ├── scalar_low_impl.h ├── scratch.h ├── scratch_impl.h ├── secp256k1.c ├── selftest.h ├── testrand.h ├── testrand_impl.h ├── tests.c ├── tests_exhaustive.c ├── testutil.h ├── util.h └── wycheproof │ ├── WYCHEPROOF_COPYING │ ├── ecdsa_secp256k1_sha256_bitcoin_test.h │ └── ecdsa_secp256k1_sha256_bitcoin_test.json └── tools ├── check-abi.sh └── tests_wycheproof_generate.py /.cirrus.yml: -------------------------------------------------------------------------------- 1 | env: 2 | ### cirrus config 3 | CIRRUS_CLONE_DEPTH: 1 4 | ### compiler options 5 | HOST: 6 | WRAPPER_CMD: 7 | # Specific warnings can be disabled with -Wno-error=foo. 8 | # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual. 9 | WERROR_CFLAGS: -Werror -pedantic-errors 10 | MAKEFLAGS: -j4 11 | BUILD: check 12 | ### secp256k1 config 13 | ECMULTWINDOW: auto 14 | ECMULTGENPRECISION: auto 15 | ASM: no 16 | WIDEMUL: auto 17 | WITH_VALGRIND: yes 18 | EXTRAFLAGS: 19 | ### secp256k1 modules 20 | EXPERIMENTAL: no 21 | ECDH: no 22 | RECOVERY: no 23 | SCHNORRSIG: no 24 | ELLSWIFT: no 25 | ### test options 26 | SECP256K1_TEST_ITERS: 27 | BENCH: yes 28 | SECP256K1_BENCH_ITERS: 2 29 | CTIMETESTS: yes 30 | # Compile and run the tests 31 | EXAMPLES: yes 32 | 33 | cat_logs_snippet: &CAT_LOGS 34 | always: 35 | cat_tests_log_script: 36 | - cat tests.log || true 37 | cat_noverify_tests_log_script: 38 | - cat noverify_tests.log || true 39 | cat_exhaustive_tests_log_script: 40 | - cat exhaustive_tests.log || true 41 | cat_ctime_tests_log_script: 42 | - cat ctime_tests.log || true 43 | cat_bench_log_script: 44 | - cat bench.log || true 45 | cat_config_log_script: 46 | - cat config.log || true 47 | cat_test_env_script: 48 | - cat test_env.log || true 49 | cat_ci_env_script: 50 | - env 51 | 52 | linux_arm64_container_snippet: &LINUX_ARM64_CONTAINER 53 | env_script: 54 | - env | tee /tmp/env 55 | build_script: 56 | - DOCKER_BUILDKIT=1 docker build --file "ci/linux-debian.Dockerfile" --tag="ci_secp256k1_arm" 57 | - docker image prune --force # Cleanup stale layers 58 | test_script: 59 | - docker run --rm --mount "type=bind,src=./,dst=/ci_secp256k1" --env-file /tmp/env --replace --name "ci_secp256k1_arm" "ci_secp256k1_arm" bash -c "cd /ci_secp256k1/ && ./ci/ci.sh" 60 | 61 | task: 62 | name: "ARM64: Linux (Debian stable)" 63 | persistent_worker: 64 | labels: 65 | type: arm64 66 | env: 67 | ECDH: yes 68 | RECOVERY: yes 69 | SCHNORRSIG: yes 70 | ELLSWIFT: yes 71 | matrix: 72 | # Currently only gcc-snapshot, the other compilers are tested on GHA with QEMU 73 | - env: { CC: 'gcc-snapshot' } 74 | << : *LINUX_ARM64_CONTAINER 75 | << : *CAT_LOGS 76 | 77 | task: 78 | name: "ARM64: Linux (Debian stable), Valgrind" 79 | persistent_worker: 80 | labels: 81 | type: arm64 82 | env: 83 | ECDH: yes 84 | RECOVERY: yes 85 | SCHNORRSIG: yes 86 | ELLSWIFT: yes 87 | WRAPPER_CMD: 'valgrind --error-exitcode=42' 88 | SECP256K1_TEST_ITERS: 2 89 | matrix: 90 | - env: { CC: 'gcc' } 91 | - env: { CC: 'clang' } 92 | - env: { CC: 'gcc-snapshot' } 93 | - env: { CC: 'clang-snapshot' } 94 | << : *LINUX_ARM64_CONTAINER 95 | << : *CAT_LOGS 96 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | src/precomputed_ecmult.c linguist-generated 2 | src/precomputed_ecmult_gen.c linguist-generated 3 | -------------------------------------------------------------------------------- /.github/actions/install-homebrew-valgrind/action.yml: -------------------------------------------------------------------------------- 1 | name: "Install Valgrind" 2 | description: "Install Homebrew's Valgrind package and cache it." 3 | runs: 4 | using: "composite" 5 | steps: 6 | - run: | 7 | brew tap LouisBrunner/valgrind 8 | brew fetch --HEAD LouisBrunner/valgrind/valgrind 9 | echo "CI_HOMEBREW_CELLAR_VALGRIND=$(brew --cellar valgrind)" >> "$GITHUB_ENV" 10 | shell: bash 11 | 12 | - run: | 13 | sw_vers > valgrind_fingerprint 14 | brew --version >> valgrind_fingerprint 15 | git -C "$(brew --cache)/valgrind--git" rev-parse HEAD >> valgrind_fingerprint 16 | cat valgrind_fingerprint 17 | shell: bash 18 | 19 | - uses: actions/cache@v3 20 | id: cache 21 | with: 22 | path: ${{ env.CI_HOMEBREW_CELLAR_VALGRIND }} 23 | key: ${{ github.job }}-valgrind-${{ hashFiles('valgrind_fingerprint') }} 24 | 25 | - if: steps.cache.outputs.cache-hit != 'true' 26 | run: | 27 | brew install --HEAD LouisBrunner/valgrind/valgrind 28 | shell: bash 29 | 30 | - if: steps.cache.outputs.cache-hit == 'true' 31 | run: | 32 | brew link valgrind 33 | shell: bash 34 | -------------------------------------------------------------------------------- /.github/actions/run-in-docker-action/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Run in Docker with environment' 2 | description: 'Run a command in a Docker container, while passing explicitly set environment variables into the container.' 3 | inputs: 4 | dockerfile: 5 | description: 'A Dockerfile that defines an image' 6 | required: true 7 | tag: 8 | description: 'A tag of an image' 9 | required: true 10 | command: 11 | description: 'A command to run in a container' 12 | required: false 13 | default: ./ci/ci.sh 14 | runs: 15 | using: "composite" 16 | steps: 17 | - uses: docker/setup-buildx-action@v3 18 | 19 | - uses: docker/build-push-action@v5 20 | id: main_builder 21 | continue-on-error: true 22 | with: 23 | context: . 24 | file: ${{ inputs.dockerfile }} 25 | tags: ${{ inputs.tag }} 26 | load: true 27 | cache-from: type=gha 28 | 29 | - uses: docker/build-push-action@v5 30 | id: retry_builder 31 | if: steps.main_builder.outcome == 'failure' 32 | with: 33 | context: . 34 | file: ${{ inputs.dockerfile }} 35 | tags: ${{ inputs.tag }} 36 | load: true 37 | cache-from: type=gha 38 | 39 | - # Tell Docker to pass environment variables in `env` into the container. 40 | run: > 41 | docker run \ 42 | $(echo '${{ toJSON(env) }}' | jq -r 'keys[] | "--env \(.) "') \ 43 | --volume ${{ github.workspace }}:${{ github.workspace }} \ 44 | --workdir ${{ github.workspace }} \ 45 | ${{ inputs.tag }} bash -c " 46 | git config --global --add safe.directory ${{ github.workspace }} 47 | ${{ inputs.command }} 48 | " 49 | shell: bash 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bench 2 | bench_bppp 3 | bench_ecmult 4 | bench_generator 5 | bench_rangeproof 6 | bench_internal 7 | bench_whitelist 8 | noverify_tests 9 | tests 10 | example_musig 11 | exhaustive_tests 12 | precompute_ecmult_gen 13 | precompute_ecmult 14 | ctime_tests 15 | ecdh_example 16 | ecdsa_example 17 | schnorr_example 18 | *.exe 19 | *.so 20 | *.a 21 | *.csv 22 | *.log 23 | *.trs 24 | *.sage.py 25 | 26 | Makefile 27 | configure 28 | .libs/ 29 | Makefile.in 30 | aclocal.m4 31 | autom4te.cache/ 32 | config.log 33 | config.status 34 | conftest* 35 | *.tar.gz 36 | *.la 37 | libtool 38 | .deps/ 39 | .dirstamp 40 | *.lo 41 | *.o 42 | *~ 43 | 44 | coverage/ 45 | coverage.html 46 | coverage.*.html 47 | *.gcda 48 | *.gcno 49 | *.gcov 50 | 51 | build-aux/ar-lib 52 | build-aux/config.guess 53 | build-aux/config.sub 54 | build-aux/depcomp 55 | build-aux/install-sh 56 | build-aux/ltmain.sh 57 | build-aux/m4/libtool.m4 58 | build-aux/m4/lt~obsolete.m4 59 | build-aux/m4/ltoptions.m4 60 | build-aux/m4/ltsugar.m4 61 | build-aux/m4/ltversion.m4 62 | build-aux/missing 63 | build-aux/compile 64 | build-aux/test-driver 65 | libsecp256k1.pc 66 | contrib/gh-pr-create.sh 67 | 68 | musig_example 69 | 70 | ### CMake 71 | /CMakeUserPresets.json 72 | # Default CMake build directory. 73 | /build 74 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmakeMinimumRequired": {"major": 3, "minor": 21, "patch": 0}, 3 | "version": 3, 4 | "configurePresets": [ 5 | { 6 | "name": "dev-mode", 7 | "displayName": "Development mode (intended only for developers of the library)", 8 | "cacheVariables": { 9 | "SECP256K1_EXPERIMENTAL": "ON", 10 | "SECP256K1_ENABLE_MODULE_RECOVERY": "ON", 11 | "SECP256K1_BUILD_EXAMPLES": "ON" 12 | }, 13 | "warnings": { 14 | "dev": true, 15 | "uninitialized": true 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Pieter Wuille 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | libsecp256k1-zkp 2 | ================ 3 | 4 | ![Dependencies: None](https://img.shields.io/badge/dependencies-none-success) 5 | 6 | A fork of [libsecp256k1](https://github.com/bitcoin-core/secp256k1) with support for advanced and experimental features such as Confidential Assets and MuSig2 7 | 8 | Added features: 9 | * Experimental module for ECDSA adaptor signatures. 10 | * Experimental module for ECDSA sign-to-contract. 11 | * Experimental module for [MuSig2](src/modules/musig/musig.md). 12 | * Experimental module for Confidential Assets (Pedersen commitments, range proofs, and [surjection proofs](src/modules/surjection/surjection.md)). 13 | * Experimental module for Bulletproofs++ range proofs. 14 | * Experimental module for [address whitelisting](src/modules/whitelist/whitelist.md). 15 | 16 | Experimental features are made available for testing and review by the community. The APIs of these features should not be considered stable. 17 | 18 | Build steps 19 | ----------- 20 | 21 | Building with Autotools 22 | ----------------------- 23 | 24 | $ ./autogen.sh 25 | $ ./configure 26 | $ make 27 | $ make check # run the test suite 28 | $ sudo make install # optional 29 | 30 | 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. For experimental modules, you will also need `--enable-experimental` as well as a flag for each individual module, e.g. `--enable-module-musig`. 31 | 32 | Building with CMake (experimental) 33 | ---------------------------------- 34 | 35 | To maintain a pristine source tree, CMake encourages to perform an out-of-source build by using a separate dedicated build tree. 36 | 37 | ### Building on POSIX systems 38 | 39 | $ mkdir build && cd build 40 | $ cmake .. 41 | $ cmake --build . 42 | $ ctest # run the test suite 43 | $ sudo cmake --build . --target install # optional 44 | 45 | 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. 46 | 47 | ### Cross compiling 48 | 49 | To alleviate issues with cross compiling, preconfigured toolchain files are available in the `cmake` directory. 50 | For example, to cross compile for Windows: 51 | 52 | $ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-w64-mingw32.toolchain.cmake 53 | 54 | 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): 55 | 56 | $ cmake .. -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 57 | 58 | ### Building on Windows 59 | 60 | 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. 61 | 62 | The following example assumes using of Visual Studio 2022 and CMake v3.21+. 63 | 64 | In "Developer Command Prompt for VS 2022": 65 | 66 | >cmake -G "Visual Studio 17 2022" -A x64 -S . -B build 67 | >cmake --build build --config RelWithDebInfo 68 | 69 | Usage examples 70 | ----------- 71 | 72 | Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`. 73 | * [ECDSA example](examples/ecdsa.c) 74 | * [Schnorr signatures example](examples/schnorr.c) 75 | * [Deriving a shared secret (ECDH) example](examples/ecdh.c) 76 | * [MuSig example](examples/musig.c) 77 | 78 | To compile the Schnorr signature, ECDH and MuSig examples, you need to enable the corresponding module by providing a flag to the `configure` script, for example `--enable-module-schnorrsig`. 79 | 80 | Benchmark 81 | ------------ 82 | If configured with `--enable-benchmark` (which is the default), binaries for benchmarking the libsecp256k1-zkp functions will be present in the root directory after the build. 83 | 84 | To print the benchmark result to the command line: 85 | 86 | $ ./bench_name 87 | 88 | To create a CSV file for the benchmark result : 89 | 90 | $ ./bench_name | sed '2d;s/ \{1,\}//g' > bench_name.csv 91 | 92 | Reporting a vulnerability 93 | ------------ 94 | 95 | See [SECURITY.md](SECURITY.md) 96 | 97 | Contributing to libsecp256k1 98 | ------------ 99 | 100 | See [CONTRIBUTING.md](CONTRIBUTING.md) 101 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | To report security issues send an email to secp256k1-security@bitcoincore.org (not for support). 6 | 7 | The following keys may be used to communicate sensitive information to developers: 8 | 9 | | Name | Fingerprint | 10 | |------|-------------| 11 | | Pieter Wuille | 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 | 12 | | Jonas Nick | 36C7 1A37 C9D9 88BD E825 08D9 B1A7 0E4F 8DCD 0366 | 13 | | Tim Ruffing | 09E0 3F87 1092 E40E 106E 902B 33BC 86AB 80FF 5516 | 14 | 15 | You can import a key by running the following command with that individual’s fingerprint: `gpg --keyserver hkps://keys.openpgp.org --recv-keys ""` Ensure that you put quotes around fingerprints containing spaces. 16 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | autoreconf -if --warnings=all 4 | -------------------------------------------------------------------------------- /build-aux/m4/bitcoin_secp.m4: -------------------------------------------------------------------------------- 1 | dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. 2 | AC_DEFUN([SECP_X86_64_ASM_CHECK],[ 3 | AC_MSG_CHECKING(for x86_64 assembly availability) 4 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[ 5 | #include ]],[[ 6 | uint64_t a = 11, tmp; 7 | __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); 8 | ]])], [has_x86_64_asm=yes], [has_x86_64_asm=no]) 9 | AC_MSG_RESULT([$has_x86_64_asm]) 10 | ]) 11 | 12 | AC_DEFUN([SECP_ARM32_ASM_CHECK], [ 13 | AC_MSG_CHECKING(for ARM32 assembly availability) 14 | SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS="$CFLAGS" 15 | CFLAGS="-x assembler" 16 | AC_LINK_IFELSE([AC_LANG_SOURCE([[ 17 | .syntax unified 18 | .eabi_attribute 24, 1 19 | .eabi_attribute 25, 1 20 | .text 21 | .global main 22 | main: 23 | ldr r0, =0x002A 24 | mov r7, #1 25 | swi 0 26 | ]])], [has_arm32_asm=yes], [has_arm32_asm=no]) 27 | AC_MSG_RESULT([$has_arm32_asm]) 28 | CFLAGS="$SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS" 29 | ]) 30 | 31 | AC_DEFUN([SECP_VALGRIND_CHECK],[ 32 | AC_MSG_CHECKING([for valgrind support]) 33 | if test x"$has_valgrind" != x"yes"; then 34 | CPPFLAGS_TEMP="$CPPFLAGS" 35 | CPPFLAGS="$VALGRIND_CPPFLAGS $CPPFLAGS" 36 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 37 | #include 38 | ]], [[ 39 | #if defined(NVALGRIND) 40 | # error "Valgrind does not support this platform." 41 | #endif 42 | ]])], [has_valgrind=yes]) 43 | CPPFLAGS="$CPPFLAGS_TEMP" 44 | fi 45 | AC_MSG_RESULT($has_valgrind) 46 | ]) 47 | 48 | dnl SECP_TRY_APPEND_CFLAGS(flags, VAR) 49 | dnl Append flags to VAR if CC accepts them. 50 | AC_DEFUN([SECP_TRY_APPEND_CFLAGS], [ 51 | AC_MSG_CHECKING([if ${CC} supports $1]) 52 | SECP_TRY_APPEND_CFLAGS_saved_CFLAGS="$CFLAGS" 53 | CFLAGS="$1 $CFLAGS" 54 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], [flag_works=yes], [flag_works=no]) 55 | AC_MSG_RESULT($flag_works) 56 | CFLAGS="$SECP_TRY_APPEND_CFLAGS_saved_CFLAGS" 57 | if test x"$flag_works" = x"yes"; then 58 | $2="$$2 $1" 59 | fi 60 | unset flag_works 61 | AC_SUBST($2) 62 | ]) 63 | 64 | dnl SECP_SET_DEFAULT(VAR, default, default-dev-mode) 65 | dnl Set VAR to default or default-dev-mode, depending on whether dev mode is enabled 66 | AC_DEFUN([SECP_SET_DEFAULT], [ 67 | if test "${enable_dev_mode+set}" != set; then 68 | AC_MSG_ERROR([[Set enable_dev_mode before calling SECP_SET_DEFAULT]]) 69 | fi 70 | if test x"$enable_dev_mode" = x"yes"; then 71 | $1="$3" 72 | else 73 | $1="$2" 74 | fi 75 | ]) 76 | -------------------------------------------------------------------------------- /ci/linux-debian.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stable-slim 2 | 3 | SHELL ["/bin/bash", "-c"] 4 | 5 | WORKDIR /root 6 | 7 | # A too high maximum number of file descriptors (with the default value 8 | # inherited from the docker host) can cause issues with some of our tools: 9 | # - sanitizers hanging: https://github.com/google/sanitizers/issues/1662 10 | # - valgrind crashing: https://stackoverflow.com/a/75293014 11 | # This is not be a problem on our CI hosts, but developers who run the image 12 | # on their machines may run into this (e.g., on Arch Linux), so warn them. 13 | # (Note that .bashrc is only executed in interactive bash shells.) 14 | RUN echo 'if [[ $(ulimit -n) -gt 200000 ]]; then echo "WARNING: Very high value reported by \"ulimit -n\". Consider passing \"--ulimit nofile=32768\" to \"docker run\"."; fi' >> /root/.bashrc 15 | 16 | RUN dpkg --add-architecture i386 && \ 17 | dpkg --add-architecture s390x && \ 18 | dpkg --add-architecture armhf && \ 19 | dpkg --add-architecture arm64 && \ 20 | dpkg --add-architecture ppc64el 21 | 22 | # dkpg-dev: to make pkg-config work in cross-builds 23 | # llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces 24 | RUN apt-get update && apt-get install --no-install-recommends -y \ 25 | git ca-certificates \ 26 | make automake libtool pkg-config dpkg-dev valgrind qemu-user \ 27 | gcc clang llvm libclang-rt-dev libc6-dbg \ 28 | g++ \ 29 | gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan8:i386 \ 30 | gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \ 31 | gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \ 32 | gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross libc6-dbg:ppc64el \ 33 | gcc-mingw-w64-x86-64-win32 wine64 wine \ 34 | gcc-mingw-w64-i686-win32 wine32 \ 35 | python3 && \ 36 | if ! ( dpkg --print-architecture | grep --quiet "arm64" ) ; then \ 37 | apt-get install --no-install-recommends -y \ 38 | gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 ;\ 39 | fi && \ 40 | apt-get clean && rm -rf /var/lib/apt/lists/* 41 | 42 | # Build and install gcc snapshot 43 | ARG GCC_SNAPSHOT_MAJOR=14 44 | RUN apt-get update && apt-get install --no-install-recommends -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ 45 | mkdir gcc && cd gcc && \ 46 | wget --progress=dot:giga --https-only --recursive --accept '*.tar.xz' --level 1 --no-directories "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}" && \ 47 | wget "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}/sha512.sum" && \ 48 | sha512sum --check --ignore-missing sha512.sum && \ 49 | # We should have downloaded exactly one tar.xz file 50 | ls && \ 51 | [ $(ls *.tar.xz | wc -l) -eq "1" ] && \ 52 | tar xf *.tar.xz && \ 53 | mkdir gcc-build && cd gcc-build && \ 54 | ../*/configure --prefix=/opt/gcc-snapshot --enable-languages=c --disable-bootstrap --disable-multilib --without-isl && \ 55 | make -j $(nproc) && \ 56 | make install && \ 57 | cd ../.. && rm -rf gcc && \ 58 | ln -s /opt/gcc-snapshot/bin/gcc /usr/bin/gcc-snapshot && \ 59 | apt-get autoremove -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ 60 | apt-get clean && rm -rf /var/lib/apt/lists/* 61 | 62 | # Install clang snapshot, see https://apt.llvm.org/ 63 | RUN \ 64 | # Setup GPG keys of LLVM repository 65 | apt-get update && apt-get install --no-install-recommends -y wget && \ 66 | wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ 67 | # Add repository for this Debian release 68 | . /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \ 69 | apt-get update && \ 70 | # Determine the version number of the LLVM development branch 71 | LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ 72 | # Install 73 | apt-get install --no-install-recommends -y "clang-${LLVM_VERSION}" && \ 74 | # Create symlink 75 | ln -s "/usr/bin/clang-${LLVM_VERSION}" /usr/bin/clang-snapshot && \ 76 | # Clean up 77 | apt-get autoremove -y wget && \ 78 | apt-get clean && rm -rf /var/lib/apt/lists/* 79 | 80 | -------------------------------------------------------------------------------- /cmake/AllTargetsCompileOptions.cmake: -------------------------------------------------------------------------------- 1 | # Add compile options to all targets added in the subdirectory. 2 | function(all_targets_compile_options dir options) 3 | get_directory_property(targets DIRECTORY ${dir} BUILDSYSTEM_TARGETS) 4 | separate_arguments(options) 5 | set(compiled_target_types STATIC_LIBRARY SHARED_LIBRARY OBJECT_LIBRARY EXECUTABLE) 6 | foreach(target ${targets}) 7 | get_target_property(type ${target} TYPE) 8 | if(type IN_LIST compiled_target_types) 9 | target_compile_options(${target} PRIVATE ${options}) 10 | endif() 11 | endforeach() 12 | endfunction() 13 | -------------------------------------------------------------------------------- /cmake/CheckArm32Assembly.cmake: -------------------------------------------------------------------------------- 1 | function(check_arm32_assembly) 2 | try_compile(HAVE_ARM32_ASM 3 | ${CMAKE_BINARY_DIR}/check_arm32_assembly 4 | SOURCES ${CMAKE_SOURCE_DIR}/cmake/source_arm32.s 5 | ) 6 | endfunction() 7 | -------------------------------------------------------------------------------- /cmake/CheckStringOptionValue.cmake: -------------------------------------------------------------------------------- 1 | function(check_string_option_value option) 2 | get_property(expected_values CACHE ${option} PROPERTY STRINGS) 3 | if(expected_values) 4 | if(${option} IN_LIST expected_values) 5 | return() 6 | endif() 7 | message(FATAL_ERROR "${option} value is \"${${option}}\", but must be one of ${expected_values}.") 8 | endif() 9 | message(AUTHOR_WARNING "The STRINGS property must be set before invoking `check_string_option_value' function.") 10 | endfunction() 11 | -------------------------------------------------------------------------------- /cmake/CheckX86_64Assembly.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCSourceCompiles) 2 | 3 | function(check_x86_64_assembly) 4 | check_c_source_compiles(" 5 | #include 6 | 7 | int main() 8 | { 9 | uint64_t a = 11, tmp; 10 | __asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\"); 11 | } 12 | " HAVE_X86_64_ASM) 13 | set(HAVE_X86_64_ASM ${HAVE_X86_64_ASM} PARENT_SCOPE) 14 | endfunction() 15 | -------------------------------------------------------------------------------- /cmake/FindValgrind.cmake: -------------------------------------------------------------------------------- 1 | if(CMAKE_HOST_APPLE) 2 | find_program(BREW_COMMAND brew) 3 | execute_process( 4 | COMMAND ${BREW_COMMAND} --prefix valgrind 5 | OUTPUT_VARIABLE valgrind_brew_prefix 6 | ERROR_QUIET 7 | OUTPUT_STRIP_TRAILING_WHITESPACE 8 | ) 9 | endif() 10 | 11 | set(hints_paths) 12 | if(valgrind_brew_prefix) 13 | set(hints_paths ${valgrind_brew_prefix}/include) 14 | endif() 15 | 16 | find_path(Valgrind_INCLUDE_DIR 17 | NAMES valgrind/memcheck.h 18 | HINTS ${hints_paths} 19 | ) 20 | 21 | if(Valgrind_INCLUDE_DIR) 22 | include(CheckCSourceCompiles) 23 | set(CMAKE_REQUIRED_INCLUDES ${Valgrind_INCLUDE_DIR}) 24 | check_c_source_compiles(" 25 | #include 26 | #if defined(NVALGRIND) 27 | # error \"Valgrind does not support this platform.\" 28 | #endif 29 | 30 | int main() {} 31 | " Valgrind_WORKS) 32 | endif() 33 | 34 | include(FindPackageHandleStandardArgs) 35 | find_package_handle_standard_args(Valgrind 36 | REQUIRED_VARS Valgrind_INCLUDE_DIR Valgrind_WORKS 37 | ) 38 | 39 | mark_as_advanced( 40 | Valgrind_INCLUDE_DIR 41 | ) 42 | -------------------------------------------------------------------------------- /cmake/GeneratePkgConfigFile.cmake: -------------------------------------------------------------------------------- 1 | function(generate_pkg_config_file in_file) 2 | set(prefix ${CMAKE_INSTALL_PREFIX}) 3 | set(exec_prefix \${prefix}) 4 | set(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR}) 5 | set(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR}) 6 | set(PACKAGE_VERSION ${PROJECT_VERSION}) 7 | configure_file(${in_file} ${PROJECT_NAME}.pc @ONLY) 8 | endfunction() 9 | -------------------------------------------------------------------------------- /cmake/TryAppendCFlags.cmake: -------------------------------------------------------------------------------- 1 | include(CheckCCompilerFlag) 2 | 3 | function(secp256k1_check_c_flags_internal flags output) 4 | string(MAKE_C_IDENTIFIER "${flags}" result) 5 | string(TOUPPER "${result}" result) 6 | set(result "C_SUPPORTS_${result}") 7 | if(NOT MSVC) 8 | set(CMAKE_REQUIRED_FLAGS "-Werror") 9 | endif() 10 | 11 | # This avoids running a linker. 12 | set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 13 | check_c_compiler_flag("${flags}" ${result}) 14 | 15 | set(${output} ${${result}} PARENT_SCOPE) 16 | endfunction() 17 | 18 | # Append flags to the COMPILE_OPTIONS directory property if CC accepts them. 19 | macro(try_append_c_flags) 20 | secp256k1_check_c_flags_internal("${ARGV}" result) 21 | if(result) 22 | add_compile_options(${ARGV}) 23 | endif() 24 | endmacro() 25 | -------------------------------------------------------------------------------- /cmake/arm-linux-gnueabihf.toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Linux) 2 | set(CMAKE_SYSTEM_PROCESSOR arm) 3 | set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) 4 | -------------------------------------------------------------------------------- /cmake/config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") 4 | 5 | check_required_components(@PROJECT_NAME@) 6 | -------------------------------------------------------------------------------- /cmake/source_arm32.s: -------------------------------------------------------------------------------- 1 | .syntax unified 2 | .eabi_attribute 24, 1 3 | .eabi_attribute 25, 1 4 | .text 5 | .global main 6 | main: 7 | ldr r0, =0x002A 8 | mov r7, #1 9 | swi 0 10 | -------------------------------------------------------------------------------- /cmake/x86_64-w64-mingw32.toolchain.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_SYSTEM_NAME Windows) 2 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 3 | set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) 4 | -------------------------------------------------------------------------------- /contrib/lax_der_parsing.c: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #include 8 | 9 | #include "lax_der_parsing.h" 10 | 11 | int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { 12 | size_t rpos, rlen, spos, slen; 13 | size_t pos = 0; 14 | size_t lenbyte; 15 | unsigned char tmpsig[64] = {0}; 16 | int overflow = 0; 17 | 18 | /* Hack to initialize sig with a correctly-parsed but invalid signature. */ 19 | secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); 20 | 21 | /* Sequence tag byte */ 22 | if (pos == inputlen || input[pos] != 0x30) { 23 | return 0; 24 | } 25 | pos++; 26 | 27 | /* Sequence length bytes */ 28 | if (pos == inputlen) { 29 | return 0; 30 | } 31 | lenbyte = input[pos++]; 32 | if (lenbyte & 0x80) { 33 | lenbyte -= 0x80; 34 | if (lenbyte > inputlen - pos) { 35 | return 0; 36 | } 37 | pos += lenbyte; 38 | } 39 | 40 | /* Integer tag byte for R */ 41 | if (pos == inputlen || input[pos] != 0x02) { 42 | return 0; 43 | } 44 | pos++; 45 | 46 | /* Integer length for R */ 47 | if (pos == inputlen) { 48 | return 0; 49 | } 50 | lenbyte = input[pos++]; 51 | if (lenbyte & 0x80) { 52 | lenbyte -= 0x80; 53 | if (lenbyte > inputlen - pos) { 54 | return 0; 55 | } 56 | while (lenbyte > 0 && input[pos] == 0) { 57 | pos++; 58 | lenbyte--; 59 | } 60 | if (lenbyte >= sizeof(size_t)) { 61 | return 0; 62 | } 63 | rlen = 0; 64 | while (lenbyte > 0) { 65 | rlen = (rlen << 8) + input[pos]; 66 | pos++; 67 | lenbyte--; 68 | } 69 | } else { 70 | rlen = lenbyte; 71 | } 72 | if (rlen > inputlen - pos) { 73 | return 0; 74 | } 75 | rpos = pos; 76 | pos += rlen; 77 | 78 | /* Integer tag byte for S */ 79 | if (pos == inputlen || input[pos] != 0x02) { 80 | return 0; 81 | } 82 | pos++; 83 | 84 | /* Integer length for S */ 85 | if (pos == inputlen) { 86 | return 0; 87 | } 88 | lenbyte = input[pos++]; 89 | if (lenbyte & 0x80) { 90 | lenbyte -= 0x80; 91 | if (lenbyte > inputlen - pos) { 92 | return 0; 93 | } 94 | while (lenbyte > 0 && input[pos] == 0) { 95 | pos++; 96 | lenbyte--; 97 | } 98 | if (lenbyte >= sizeof(size_t)) { 99 | return 0; 100 | } 101 | slen = 0; 102 | while (lenbyte > 0) { 103 | slen = (slen << 8) + input[pos]; 104 | pos++; 105 | lenbyte--; 106 | } 107 | } else { 108 | slen = lenbyte; 109 | } 110 | if (slen > inputlen - pos) { 111 | return 0; 112 | } 113 | spos = pos; 114 | 115 | /* Ignore leading zeroes in R */ 116 | while (rlen > 0 && input[rpos] == 0) { 117 | rlen--; 118 | rpos++; 119 | } 120 | /* Copy R value */ 121 | if (rlen > 32) { 122 | overflow = 1; 123 | } else if (rlen) { 124 | memcpy(tmpsig + 32 - rlen, input + rpos, rlen); 125 | } 126 | 127 | /* Ignore leading zeroes in S */ 128 | while (slen > 0 && input[spos] == 0) { 129 | slen--; 130 | spos++; 131 | } 132 | /* Copy S value */ 133 | if (slen > 32) { 134 | overflow = 1; 135 | } else if (slen) { 136 | memcpy(tmpsig + 64 - slen, input + spos, slen); 137 | } 138 | 139 | if (!overflow) { 140 | overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); 141 | } 142 | if (overflow) { 143 | memset(tmpsig, 0, 64); 144 | secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); 145 | } 146 | return 1; 147 | } 148 | 149 | -------------------------------------------------------------------------------- /contrib/lax_der_parsing.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | /**** 8 | * Please do not link this file directly. It is not part of the libsecp256k1 9 | * project and does not promise any stability in its API, functionality or 10 | * presence. Projects which use this code should instead copy this header 11 | * and its accompanying .c file directly into their codebase. 12 | ****/ 13 | 14 | /* This file defines a function that parses DER with various errors and 15 | * violations. This is not a part of the library itself, because the allowed 16 | * violations are chosen arbitrarily and do not follow or establish any 17 | * standard. 18 | * 19 | * In many places it matters that different implementations do not only accept 20 | * the same set of valid signatures, but also reject the same set of signatures. 21 | * The only means to accomplish that is by strictly obeying a standard, and not 22 | * accepting anything else. 23 | * 24 | * Nonetheless, sometimes there is a need for compatibility with systems that 25 | * use signatures which do not strictly obey DER. The snippet below shows how 26 | * certain violations are easily supported. You may need to adapt it. 27 | * 28 | * Do not use this for new systems. Use well-defined DER or compact signatures 29 | * instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and 30 | * secp256k1_ecdsa_signature_parse_compact). 31 | * 32 | * The supported violations are: 33 | * - All numbers are parsed as nonnegative integers, even though X.609-0207 34 | * section 8.3.3 specifies that integers are always encoded as two's 35 | * complement. 36 | * - Integers can have length 0, even though section 8.3.1 says they can't. 37 | * - Integers with overly long padding are accepted, violation section 38 | * 8.3.2. 39 | * - 127-byte long length descriptors are accepted, even though section 40 | * 8.1.3.5.c says that they are not. 41 | * - Trailing garbage data inside or after the signature is ignored. 42 | * - The length descriptor of the sequence is ignored. 43 | * 44 | * Compared to for example OpenSSL, many violations are NOT supported: 45 | * - Using overly long tag descriptors for the sequence or integers inside, 46 | * violating section 8.1.2.2. 47 | * - Encoding primitive integers as constructed values, violating section 48 | * 8.3.1. 49 | */ 50 | 51 | #ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H 52 | #define SECP256K1_CONTRIB_LAX_DER_PARSING_H 53 | 54 | /* #include secp256k1.h only when it hasn't been included yet. 55 | This enables this file to be #included directly in other project 56 | files (such as tests.c) without the need to set an explicit -I flag, 57 | which would be necessary to locate secp256k1.h. */ 58 | #ifndef SECP256K1_H 59 | #include 60 | #endif 61 | 62 | #ifdef __cplusplus 63 | extern "C" { 64 | #endif 65 | 66 | /** Parse a signature in "lax DER" format 67 | * 68 | * Returns: 1 when the signature could be parsed, 0 otherwise. 69 | * Args: ctx: a secp256k1 context object 70 | * Out: sig: pointer to a signature object 71 | * In: input: pointer to the signature to be parsed 72 | * inputlen: the length of the array pointed to be input 73 | * 74 | * This function will accept any valid DER encoded signature, even if the 75 | * encoded numbers are out of range. In addition, it will accept signatures 76 | * which violate the DER spec in various ways. Its purpose is to allow 77 | * validation of the Bitcoin blockchain, which includes non-DER signatures 78 | * from before the network rules were updated to enforce DER. Note that 79 | * the set of supported violations is a strict subset of what OpenSSL will 80 | * accept. 81 | * 82 | * After the call, sig will always be initialized. If parsing failed or the 83 | * encoded numbers are out of range, signature validation with it is 84 | * guaranteed to fail for every message and public key. 85 | */ 86 | int ecdsa_signature_parse_der_lax( 87 | const secp256k1_context* ctx, 88 | secp256k1_ecdsa_signature* sig, 89 | const unsigned char *input, 90 | size_t inputlen 91 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */ 98 | -------------------------------------------------------------------------------- /contrib/lax_der_privatekey_parsing.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014, 2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | /**** 8 | * Please do not link this file directly. It is not part of the libsecp256k1 9 | * project and does not promise any stability in its API, functionality or 10 | * presence. Projects which use this code should instead copy this header 11 | * and its accompanying .c file directly into their codebase. 12 | ****/ 13 | 14 | /* This file contains code snippets that parse DER private keys with 15 | * various errors and violations. This is not a part of the library 16 | * itself, because the allowed violations are chosen arbitrarily and 17 | * do not follow or establish any standard. 18 | * 19 | * It also contains code to serialize private keys in a compatible 20 | * manner. 21 | * 22 | * These functions are meant for compatibility with applications 23 | * that require BER encoded keys. When working with secp256k1-specific 24 | * code, the simple 32-byte private keys normally used by the 25 | * library are sufficient. 26 | */ 27 | 28 | #ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H 29 | #define SECP256K1_CONTRIB_BER_PRIVATEKEY_H 30 | 31 | /* #include secp256k1.h only when it hasn't been included yet. 32 | This enables this file to be #included directly in other project 33 | files (such as tests.c) without the need to set an explicit -I flag, 34 | which would be necessary to locate secp256k1.h. */ 35 | #ifndef SECP256K1_H 36 | #include 37 | #endif 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | 43 | /** Export a private key in DER format. 44 | * 45 | * Returns: 1 if the private key was valid. 46 | * Args: ctx: pointer to a context object (not secp256k1_context_static). 47 | * Out: privkey: pointer to an array for storing the private key in BER. 48 | * Should have space for 279 bytes, and cannot be NULL. 49 | * privkeylen: Pointer to an int where the length of the private key in 50 | * privkey will be stored. 51 | * In: seckey: pointer to a 32-byte secret key to export. 52 | * compressed: 1 if the key should be exported in 53 | * compressed format, 0 otherwise 54 | * 55 | * This function is purely meant for compatibility with applications that 56 | * require BER encoded keys. When working with secp256k1-specific code, the 57 | * simple 32-byte private keys are sufficient. 58 | * 59 | * Note that this function does not guarantee correct DER output. It is 60 | * guaranteed to be parsable by secp256k1_ec_privkey_import_der 61 | */ 62 | SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( 63 | const secp256k1_context* ctx, 64 | unsigned char *privkey, 65 | size_t *privkeylen, 66 | const unsigned char *seckey, 67 | int compressed 68 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 69 | 70 | /** Import a private key in DER format. 71 | * Returns: 1 if a private key was extracted. 72 | * Args: ctx: pointer to a context object (cannot be NULL). 73 | * Out: seckey: pointer to a 32-byte array for storing the private key. 74 | * (cannot be NULL). 75 | * In: privkey: pointer to a private key in DER format (cannot be NULL). 76 | * privkeylen: length of the DER private key pointed to be privkey. 77 | * 78 | * This function will accept more than just strict DER, and even allow some BER 79 | * violations. The public key stored inside the DER-encoded private key is not 80 | * verified for correctness, nor are the curve parameters. Use this function 81 | * only if you know in advance it is supposed to contain a secp256k1 private 82 | * key. 83 | */ 84 | SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( 85 | const secp256k1_context* ctx, 86 | unsigned char *seckey, 87 | const unsigned char *privkey, 88 | size_t privkeylen 89 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 90 | 91 | #ifdef __cplusplus 92 | } 93 | #endif 94 | 95 | #endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */ 96 | -------------------------------------------------------------------------------- /contrib/sync-upstream.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eou pipefail 4 | 5 | help() { 6 | echo "$0 [-b ] range [end]" 7 | echo " merges every merge commit present in upstream and missing in (default: master)." 8 | echo " If the optional [end] commit is provided, only merges up to [end]." 9 | echo " If the optional [-b branch] provided, then ." 10 | echo 11 | echo "$0 [-b ] select ... " 12 | echo " merges every selected merge commit into (default: master)" 13 | echo 14 | echo "This tool creates a branch and a script that can be executed to create the" 15 | echo "PR automatically. The script requires the github-cli tool (aka gh)." 16 | echo "" 17 | echo "Tip: \`git log --oneline upstream/master --merges\` shows merge commits." 18 | exit 1 19 | } 20 | 21 | REMOTE=upstream 22 | REMOTE_BRANCH="$REMOTE/master" 23 | LOCAL_BRANCH="master" 24 | # Makes sure you have a remote "upstream" that is up-to-date 25 | setup() { 26 | ret=0 27 | git fetch "$REMOTE" &> /dev/null || ret="$?" 28 | if [ ${ret} == 0 ]; then 29 | return 30 | fi 31 | echo "Adding remote \"$REMOTE\" with URL git@github.com:bitcoin-core/secp256k1.git. Continue with y" 32 | read -r yn 33 | case $yn in 34 | [Yy]* ) ;; 35 | * ) exit 1;; 36 | esac 37 | git remote add "$REMOTE" git@github.com:bitcoin-core/secp256k1.git &> /dev/null 38 | git fetch "$REMOTE" &> /dev/null 39 | } 40 | 41 | range() { 42 | RANGESTART_COMMIT=$(git merge-base "$REMOTE_BRANCH" "$LOCAL_BRANCH") 43 | RANGEEND_COMMIT=$(git rev-parse "$REMOTE_BRANCH") 44 | if [ "$#" = 1 ]; then 45 | RANGEEND_COMMIT=$1 46 | fi 47 | 48 | COMMITS=$(git --no-pager log --oneline --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT") 49 | COMMITS=$(echo "$COMMITS" | tac | awk '{ print $1 }' ORS=' ') 50 | echo "Merging $COMMITS. Continue with y" 51 | read -r yn 52 | case $yn in 53 | [Yy]* ) ;; 54 | * ) exit 1;; 55 | esac 56 | } 57 | 58 | # Process -b argument 59 | while getopts "b:" opt; do 60 | case $opt in 61 | b) 62 | LOCAL_BRANCH=$OPTARG 63 | ;; 64 | \?) 65 | echo "Invalid option: -$OPTARG" >&2 66 | ;; 67 | esac 68 | done 69 | 70 | # Shift off the processed options 71 | shift $((OPTIND -1)) 72 | 73 | if [ "$#" -lt 1 ]; then 74 | help 75 | fi 76 | 77 | case $1 in 78 | range) 79 | shift 80 | setup 81 | range "$@" 82 | REPRODUCE_COMMAND="$0 -b $LOCAL_BRANCH range $RANGEEND_COMMIT" 83 | ;; 84 | select) 85 | shift 86 | setup 87 | COMMITS=$* 88 | REPRODUCE_COMMAND="$0 -b $LOCAL_BRANCH select $@" 89 | ;; 90 | help) 91 | help 92 | ;; 93 | *) 94 | help 95 | esac 96 | 97 | TITLE="Upstream PRs" 98 | BODY="" 99 | for COMMIT in $COMMITS 100 | do 101 | PRNUM=$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\).*'/'\2'/) 102 | TITLE="$TITLE $PRNUM," 103 | BODY=$(printf "%s\n%s" "$BODY" "$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\)'/'[bitcoin-core\/secp256k1#\2]'/)") 104 | done 105 | # Remove trailing "," 106 | TITLE=${TITLE%?} 107 | BODY=$(printf "%s\n\n%s\n%s" "$BODY" "This PR can be recreated with \`$REPRODUCE_COMMAND\`." "Tip: Use \`git show --remerge-diff\` to show the changes manually added to the merge commit.") 108 | 109 | echo "-----------------------------------" 110 | echo "$TITLE" 111 | echo "-----------------------------------" 112 | echo "$BODY" 113 | echo "-----------------------------------" 114 | # Create branch from PR commit and create PR 115 | git checkout "$LOCAL_BRANCH" 116 | git pull --autostash 117 | git checkout -b temp-merge-"$PRNUM" 118 | 119 | # Escape single quote 120 | # ' -> '\'' 121 | quote() { 122 | local quoted=${1//\'/\'\\\'\'} 123 | printf "%s" "$quoted" 124 | } 125 | TITLE=$(quote "$TITLE") 126 | BODY=$(quote "$BODY") 127 | 128 | BASEDIR=$(dirname "$0") 129 | FNAME="$BASEDIR/gh-pr-create.sh" 130 | cat < "$FNAME" 131 | #!/bin/sh 132 | gh pr create -t '$TITLE' -b '$BODY' --web 133 | # Remove temporary branch 134 | git checkout "$LOCAL_BRANCH" 135 | git branch -D temp-merge-"$PRNUM" 136 | EOT 137 | chmod +x "$FNAME" 138 | echo Run "$FNAME" after solving the merge conflicts 139 | 140 | git merge --no-edit -m "Merge commits '$COMMITS' into temp-merge-$PRNUM" $COMMITS 141 | -------------------------------------------------------------------------------- /doc/musig-spec.mediawiki: -------------------------------------------------------------------------------- 1 | This document was moved to [https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki]. -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | function(add_example name) 2 | set(target_name ${name}_example) 3 | add_executable(${target_name} ${name}.c) 4 | target_include_directories(${target_name} PRIVATE 5 | ${PROJECT_SOURCE_DIR}/include 6 | ) 7 | target_link_libraries(${target_name} 8 | secp256k1 9 | $<$:bcrypt> 10 | ) 11 | set(test_name ${name}_example) 12 | add_test(NAME ${test_name} COMMAND ${target_name}) 13 | if(BUILD_SHARED_LIBS AND MSVC) 14 | # The DLL must reside either in the same folder where the executable is 15 | # or somewhere in PATH. Using the latter option. 16 | set_tests_properties(${test_name} PROPERTIES 17 | ENVIRONMENT "PATH=$;$ENV{PATH}" 18 | ) 19 | endif() 20 | endfunction() 21 | 22 | add_example(ecdsa) 23 | 24 | if(SECP256K1_ENABLE_MODULE_ECDH) 25 | add_example(ecdh) 26 | endif() 27 | 28 | if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) 29 | add_example(schnorr) 30 | endif() 31 | -------------------------------------------------------------------------------- /include/secp256k1_bppp.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_BPPP_H 2 | # define SECP256K1_BPPP_H 3 | 4 | # include "secp256k1.h" 5 | 6 | # ifdef __cplusplus 7 | extern "C" { 8 | # endif 9 | 10 | #include 11 | 12 | /** Opaque structure representing a large number of NUMS generators */ 13 | typedef struct secp256k1_bppp_generators secp256k1_bppp_generators; 14 | 15 | /** Allocates and initializes a list of NUMS generators. 16 | * Returns a list of generators, or calls the error callback if the allocation fails. 17 | * Args: ctx: pointer to a context object 18 | * n: number of NUMS generators to produce. 19 | * 20 | * TODO: In a followup range-proof PR, this is would still require 16 + 8 = 24 NUMS 21 | * points. We will later use G = H0(required for compatibility with pedersen_commitment DS) 22 | * in a separate commit to make review easier. 23 | */ 24 | SECP256K1_API secp256k1_bppp_generators *secp256k1_bppp_generators_create( 25 | const secp256k1_context *ctx, 26 | size_t n 27 | ) SECP256K1_ARG_NONNULL(1); 28 | 29 | /** Allocates a list of generators from a static array 30 | * Returns a list of generators or NULL in case of failure. 31 | * Args: ctx: pointer to a context object 32 | * In: data: data that came from `secp256k1_bppp_generators_serialize` 33 | * data_len: the length of the `data` buffer 34 | */ 35 | SECP256K1_API secp256k1_bppp_generators *secp256k1_bppp_generators_parse( 36 | const secp256k1_context *ctx, 37 | const unsigned char *data, 38 | size_t data_len 39 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); 40 | 41 | /** Serializes a list of generators to an array 42 | * Returns 1 on success, 0 if the provided array was not large enough 43 | * Args: ctx: pointer to a context object 44 | * gen: pointer to the generator set to be serialized 45 | * Out: data: pointer to buffer into which the generators will be serialized 46 | * In/Out: data_len: the length of the `data` buffer. Should be at least 47 | * k = 33 * num_gens. Will be set to k on successful return 48 | * 49 | * TODO: For ease of review, this setting G = H0 is not included in this commit. We will 50 | * add it in the follow-up rangeproof PR. 51 | */ 52 | SECP256K1_API int secp256k1_bppp_generators_serialize( 53 | const secp256k1_context *ctx, 54 | const secp256k1_bppp_generators *gen, 55 | unsigned char *data, 56 | size_t *data_len 57 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 58 | 59 | /** Destroys a list of NUMS generators, freeing allocated memory 60 | * Args: ctx: pointer to a context object 61 | * gen: pointer to the generator set to be destroyed 62 | * (can be NULL, in which case this function is a no-op) 63 | */ 64 | SECP256K1_API void secp256k1_bppp_generators_destroy( 65 | const secp256k1_context *ctx, 66 | secp256k1_bppp_generators *gen 67 | ) SECP256K1_ARG_NONNULL(1); 68 | 69 | # ifdef __cplusplus 70 | } 71 | # endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /include/secp256k1_ecdh.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_ECDH_H 2 | #define SECP256K1_ECDH_H 3 | 4 | #include "secp256k1.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** A pointer to a function that hashes an EC point to obtain an ECDH secret 11 | * 12 | * Returns: 1 if the point was successfully hashed. 13 | * 0 will cause secp256k1_ecdh to fail and return 0. 14 | * Other return values are not allowed, and the behaviour of 15 | * secp256k1_ecdh is undefined for other return values. 16 | * Out: output: pointer to an array to be filled by the function 17 | * In: x32: pointer to a 32-byte x coordinate 18 | * y32: pointer to a 32-byte y coordinate 19 | * data: arbitrary data pointer that is passed through 20 | */ 21 | typedef int (*secp256k1_ecdh_hash_function)( 22 | unsigned char *output, 23 | const unsigned char *x32, 24 | const unsigned char *y32, 25 | void *data 26 | ); 27 | 28 | /** An implementation of SHA256 hash function that applies to compressed public key. 29 | * Populates the output parameter with 32 bytes. */ 30 | SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256; 31 | 32 | /** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256). 33 | * Populates the output parameter with 32 bytes. */ 34 | SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default; 35 | 36 | /** Compute an EC Diffie-Hellman secret in constant time 37 | * 38 | * Returns: 1: exponentiation was successful 39 | * 0: scalar was invalid (zero or overflow) or hashfp returned 0 40 | * Args: ctx: pointer to a context object. 41 | * Out: output: pointer to an array to be filled by hashfp. 42 | * In: pubkey: pointer to a secp256k1_pubkey containing an initialized public key. 43 | * seckey: a 32-byte scalar with which to multiply the point. 44 | * hashfp: pointer to a hash function. If NULL, 45 | * secp256k1_ecdh_hash_function_sha256 is used 46 | * (in which case, 32 bytes will be written to output). 47 | * data: arbitrary data pointer that is passed through to hashfp 48 | * (can be NULL for secp256k1_ecdh_hash_function_sha256). 49 | */ 50 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( 51 | const secp256k1_context *ctx, 52 | unsigned char *output, 53 | const secp256k1_pubkey *pubkey, 54 | const unsigned char *seckey, 55 | secp256k1_ecdh_hash_function hashfp, 56 | void *data 57 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif /* SECP256K1_ECDH_H */ 64 | -------------------------------------------------------------------------------- /libsecp256k1.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libsecp256k1 7 | Description: Optimized C library for EC operations on curve secp256k1 8 | URL: https://github.com/bitcoin-core/secp256k1 9 | Version: @PACKAGE_VERSION@ 10 | Cflags: -I${includedir} 11 | Libs: -L${libdir} -lsecp256k1 12 | 13 | -------------------------------------------------------------------------------- /sage/gen_split_lambda_constants.sage: -------------------------------------------------------------------------------- 1 | """ Generates the constants used in secp256k1_scalar_split_lambda. 2 | 3 | See the comments for secp256k1_scalar_split_lambda in src/scalar_impl.h for detailed explanations. 4 | """ 5 | 6 | load("secp256k1_params.sage") 7 | 8 | def inf_norm(v): 9 | """Returns the infinity norm of a vector.""" 10 | return max(map(abs, v)) 11 | 12 | def gauss_reduction(i1, i2): 13 | v1, v2 = i1.copy(), i2.copy() 14 | while True: 15 | if inf_norm(v2) < inf_norm(v1): 16 | v1, v2 = v2, v1 17 | # This is essentially 18 | # m = round((v1[0]*v2[0] + v1[1]*v2[1]) / (inf_norm(v1)**2)) 19 | # (rounding to the nearest integer) without relying on floating point arithmetic. 20 | m = ((v1[0]*v2[0] + v1[1]*v2[1]) + (inf_norm(v1)**2) // 2) // (inf_norm(v1)**2) 21 | if m == 0: 22 | return v1, v2 23 | v2[0] -= m*v1[0] 24 | v2[1] -= m*v1[1] 25 | 26 | def find_split_constants_gauss(): 27 | """Find constants for secp256k1_scalar_split_lamdba using gauss reduction.""" 28 | (v11, v12), (v21, v22) = gauss_reduction([0, N], [1, int(LAMBDA)]) 29 | 30 | # We use related vectors in secp256k1_scalar_split_lambda. 31 | A1, B1 = -v21, -v11 32 | A2, B2 = v22, -v21 33 | 34 | return A1, B1, A2, B2 35 | 36 | def find_split_constants_explicit_tof(): 37 | """Find constants for secp256k1_scalar_split_lamdba using the trace of Frobenius. 38 | 39 | See Benjamin Smith: "Easy scalar decompositions for efficient scalar multiplication on 40 | elliptic curves and genus 2 Jacobians" (https://eprint.iacr.org/2013/672), Example 2 41 | """ 42 | assert P % 3 == 1 # The paper says P % 3 == 2 but that appears to be a mistake, see [10]. 43 | assert C.j_invariant() == 0 44 | 45 | t = C.trace_of_frobenius() 46 | 47 | c = Integer(sqrt((4*P - t**2)/3)) 48 | A1 = Integer((t - c)/2 - 1) 49 | B1 = c 50 | 51 | A2 = Integer((t + c)/2 - 1) 52 | B2 = Integer(1 - (t - c)/2) 53 | 54 | # We use a negated b values in secp256k1_scalar_split_lambda. 55 | B1, B2 = -B1, -B2 56 | 57 | return A1, B1, A2, B2 58 | 59 | A1, B1, A2, B2 = find_split_constants_explicit_tof() 60 | 61 | # For extra fun, use an independent method to recompute the constants. 62 | assert (A1, B1, A2, B2) == find_split_constants_gauss() 63 | 64 | # PHI : Z[l] -> Z_n where phi(a + b*l) == a + b*lambda mod n. 65 | def PHI(a,b): 66 | return Z(a + LAMBDA*b) 67 | 68 | # Check that (A1, B1) and (A2, B2) are in the kernel of PHI. 69 | assert PHI(A1, B1) == Z(0) 70 | assert PHI(A2, B2) == Z(0) 71 | 72 | # Check that the parallelogram generated by (A1, A2) and (B1, B2) 73 | # is a fundamental domain by containing exactly N points. 74 | # Since the LHS is the determinant and N != 0, this also checks that 75 | # (A1, A2) and (B1, B2) are linearly independent. By the previous 76 | # assertions, (A1, A2) and (B1, B2) are a basis of the kernel. 77 | assert A1*B2 - B1*A2 == N 78 | 79 | # Check that their components are short enough. 80 | assert (A1 + A2)/2 < sqrt(N) 81 | assert B1 < sqrt(N) 82 | assert B2 < sqrt(N) 83 | 84 | G1 = round((2**384)*B2/N) 85 | G2 = round((2**384)*(-B1)/N) 86 | 87 | def rnddiv2(v): 88 | if v & 1: 89 | v += 1 90 | return v >> 1 91 | 92 | def scalar_lambda_split(k): 93 | """Equivalent to secp256k1_scalar_lambda_split().""" 94 | c1 = rnddiv2((k * G1) >> 383) 95 | c2 = rnddiv2((k * G2) >> 383) 96 | c1 = (c1 * -B1) % N 97 | c2 = (c2 * -B2) % N 98 | r2 = (c1 + c2) % N 99 | r1 = (k + r2 * -LAMBDA) % N 100 | return (r1, r2) 101 | 102 | # The result of scalar_lambda_split can depend on the representation of k (mod n). 103 | SPECIAL = (2**383) // G2 + 1 104 | assert scalar_lambda_split(SPECIAL) != scalar_lambda_split(SPECIAL + N) 105 | 106 | print(' A1 =', hex(A1)) 107 | print(' -B1 =', hex(-B1)) 108 | print(' A2 =', hex(A2)) 109 | print(' -B2 =', hex(-B2)) 110 | print(' =', hex(Z(-B2))) 111 | print(' -LAMBDA =', hex(-LAMBDA)) 112 | 113 | print(' G1 =', hex(G1)) 114 | print(' G2 =', hex(G2)) 115 | -------------------------------------------------------------------------------- /sage/secp256k1_params.sage: -------------------------------------------------------------------------------- 1 | """Prime order of finite field underlying secp256k1 (2^256 - 2^32 - 977)""" 2 | P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F 3 | 4 | """Finite field underlying secp256k1""" 5 | F = FiniteField(P) 6 | 7 | """Elliptic curve secp256k1: y^2 = x^3 + 7""" 8 | C = EllipticCurve([F(0), F(7)]) 9 | 10 | """Base point of secp256k1""" 11 | G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) 12 | if int(G[1]) & 1: 13 | # G.y is even 14 | G = -G 15 | 16 | """Prime order of secp256k1""" 17 | N = C.order() 18 | 19 | """Finite field of scalars of secp256k1""" 20 | Z = FiniteField(N) 21 | 22 | """ Beta value of secp256k1 non-trivial endomorphism: lambda * (x, y) = (beta * x, y)""" 23 | BETA = F(2)^((P-1)/3) 24 | 25 | """ Lambda value of secp256k1 non-trivial endomorphism: lambda * (x, y) = (beta * x, y)""" 26 | LAMBDA = Z(3)^((N-1)/3) 27 | 28 | assert is_prime(P) 29 | assert is_prime(N) 30 | 31 | assert BETA != F(1) 32 | assert BETA^3 == F(1) 33 | assert BETA^2 + BETA + 1 == 0 34 | 35 | assert LAMBDA != Z(1) 36 | assert LAMBDA^3 == Z(1) 37 | assert LAMBDA^2 + LAMBDA + 1 == 0 38 | 39 | assert Integer(LAMBDA)*G == C(BETA*G[0], G[1]) 40 | -------------------------------------------------------------------------------- /sage/shallue_van_de_woestijne.sage: -------------------------------------------------------------------------------- 1 | 2 | ### http://www.di.ens.fr/~fouque/pub/latincrypt12.pdf 3 | 4 | # Parameters for secp256k1 5 | p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F 6 | a = 0 7 | b = 7 8 | F = FiniteField (p) 9 | C = EllipticCurve ([F(a), F(b)]) 10 | 11 | def svdw(t): 12 | sqrt_neg_3 = F(-3).nth_root(2) 13 | 14 | ## Compute candidate x values 15 | w = sqrt_neg_3 * t / (1 + b + t^2) 16 | x = [ F(0), F(0), F(0) ] 17 | x[0] = (-1 + sqrt_neg_3) / 2 - t * w 18 | x[1] = -1 - x[0] 19 | x[2] = 1 + 1 / w^2 20 | 21 | print 22 | print "On %2d" % t 23 | print " x1 %064x" % x[0] 24 | print " x2 %064x" % x[1] 25 | print " x3 %064x" % x[2] 26 | 27 | ## Select which to use 28 | alph = jacobi_symbol(x[0]^3 + b, p) 29 | beta = jacobi_symbol(x[1]^3 + b, p) 30 | if alph == 1 and beta == 1: 31 | i = 0 32 | elif alph == 1 and beta == -1: 33 | i = 0 34 | elif alph == -1 and beta == 1: 35 | i = 1 36 | elif alph == -1 and beta == -1: 37 | i = 2 38 | else: 39 | print "Help! I don't understand Python!" 40 | 41 | ## Expand to full point 42 | sign = 1 - 2 * (int(F(t)) % 2) 43 | ret_x = x[i] 44 | ret_y = sign * F(x[i]^3 + b).nth_root(2) 45 | return C.point((ret_x, ret_y)) 46 | 47 | 48 | ## main 49 | for i in range(1, 11): 50 | res = svdw(i) 51 | print "Result: %064x %064x" % res.xy() 52 | -------------------------------------------------------------------------------- /src/assumptions.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ASSUMPTIONS_H 8 | #define SECP256K1_ASSUMPTIONS_H 9 | 10 | #include 11 | 12 | #include "util.h" 13 | #if defined(SECP256K1_INT128_NATIVE) 14 | #include "int128_native.h" 15 | #endif 16 | 17 | /* This library, like most software, relies on a number of compiler implementation defined (but not undefined) 18 | behaviours. Although the behaviours we require are essentially universal we test them specifically here to 19 | reduce the odds of experiencing an unwelcome surprise. 20 | */ 21 | 22 | #if defined(__has_attribute) 23 | # if __has_attribute(__unavailable__) 24 | __attribute__((__unavailable__("Don't call this function. It only exists because STATIC_ASSERT cannot be used outside a function."))) 25 | # endif 26 | #endif 27 | static void secp256k1_assumption_checker(void) { 28 | /* Bytes are 8 bits. */ 29 | STATIC_ASSERT(CHAR_BIT == 8); 30 | 31 | /* No integer promotion for uint32_t. This ensures that we can multiply uintXX_t values where XX >= 32 32 | without signed overflow, which would be undefined behaviour. */ 33 | STATIC_ASSERT(UINT_MAX <= UINT32_MAX); 34 | 35 | /* Conversions from unsigned to signed outside of the bounds of the signed type are 36 | implementation-defined. Verify that they function as reinterpreting the lower 37 | bits of the input in two's complement notation. Do this for conversions: 38 | - from uint(N)_t to int(N)_t with negative result 39 | - from uint(2N)_t to int(N)_t with negative result 40 | - from int(2N)_t to int(N)_t with negative result 41 | - from int(2N)_t to int(N)_t with positive result */ 42 | 43 | /* To int8_t. */ 44 | STATIC_ASSERT(((int8_t)(uint8_t)0xAB == (int8_t)-(int8_t)0x55)); 45 | STATIC_ASSERT((int8_t)(uint16_t)0xABCD == (int8_t)-(int8_t)0x33); 46 | STATIC_ASSERT((int8_t)(int16_t)(uint16_t)0xCDEF == (int8_t)(uint8_t)0xEF); 47 | STATIC_ASSERT((int8_t)(int16_t)(uint16_t)0x9234 == (int8_t)(uint8_t)0x34); 48 | 49 | /* To int16_t. */ 50 | STATIC_ASSERT((int16_t)(uint16_t)0xBCDE == (int16_t)-(int16_t)0x4322); 51 | STATIC_ASSERT((int16_t)(uint32_t)0xA1B2C3D4 == (int16_t)-(int16_t)0x3C2C); 52 | STATIC_ASSERT((int16_t)(int32_t)(uint32_t)0xC1D2E3F4 == (int16_t)(uint16_t)0xE3F4); 53 | STATIC_ASSERT((int16_t)(int32_t)(uint32_t)0x92345678 == (int16_t)(uint16_t)0x5678); 54 | 55 | /* To int32_t. */ 56 | STATIC_ASSERT((int32_t)(uint32_t)0xB2C3D4E5 == (int32_t)-(int32_t)0x4D3C2B1B); 57 | STATIC_ASSERT((int32_t)(uint64_t)0xA123B456C789D012ULL == (int32_t)-(int32_t)0x38762FEE); 58 | STATIC_ASSERT((int32_t)(int64_t)(uint64_t)0xC1D2E3F4A5B6C7D8ULL == (int32_t)(uint32_t)0xA5B6C7D8); 59 | STATIC_ASSERT((int32_t)(int64_t)(uint64_t)0xABCDEF0123456789ULL == (int32_t)(uint32_t)0x23456789); 60 | 61 | /* To int64_t. */ 62 | STATIC_ASSERT((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL); 63 | #if defined(SECP256K1_INT128_NATIVE) 64 | STATIC_ASSERT((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL); 65 | STATIC_ASSERT(((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL); 66 | STATIC_ASSERT(((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL); 67 | 68 | /* To int128_t. */ 69 | STATIC_ASSERT((int128_t)(((uint128_t)0xB1234567C8901234ULL << 64) + 0xD5678901E2345678ULL) == (int128_t)(-(int128_t)0x8E1648B3F50E80DCULL * 0x8E1648B3F50E80DDULL + 0x5EA688D5482F9464ULL)); 70 | #endif 71 | 72 | /* Right shift on negative signed values is implementation defined. Verify that it 73 | acts as a right shift in two's complement with sign extension (i.e duplicating 74 | the top bit into newly added bits). */ 75 | STATIC_ASSERT((((int8_t)0xE8) >> 2) == (int8_t)(uint8_t)0xFA); 76 | STATIC_ASSERT((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A); 77 | STATIC_ASSERT((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48); 78 | STATIC_ASSERT((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL); 79 | #if defined(SECP256K1_INT128_NATIVE) 80 | STATIC_ASSERT((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)); 81 | #endif 82 | 83 | /* This function is not supposed to be called. */ 84 | VERIFY_CHECK(0); 85 | } 86 | 87 | #endif /* SECP256K1_ASSUMPTIONS_H */ 88 | -------------------------------------------------------------------------------- /src/bench_bppp.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2020 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #include 8 | 9 | #include "../include/secp256k1_bppp.h" 10 | #include "util.h" 11 | #include "bench.h" 12 | 13 | typedef struct { 14 | secp256k1_context* ctx; 15 | } bench_bppp_data; 16 | 17 | static void bench_bppp_setup(void* arg) { 18 | (void) arg; 19 | } 20 | 21 | static void bench_bppp(void* arg, int iters) { 22 | bench_bppp_data *data = (bench_bppp_data*)arg; 23 | 24 | (void) data; 25 | (void) iters; 26 | } 27 | 28 | int main(void) { 29 | bench_bppp_data data; 30 | int iters = get_iters(32); 31 | 32 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 33 | 34 | run_benchmark("bppp_verify_bit", bench_bppp, bench_bppp_setup, NULL, &data, 10, iters); 35 | 36 | secp256k1_context_destroy(data.ctx); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /src/bench_generator.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2016 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #include 8 | #include 9 | 10 | #include "../include/secp256k1_generator.h" 11 | #include "util.h" 12 | #include "bench.h" 13 | 14 | typedef struct { 15 | secp256k1_context* ctx; 16 | unsigned char key[32]; 17 | unsigned char blind[32]; 18 | } bench_generator_t; 19 | 20 | static void bench_generator_setup(void* arg) { 21 | bench_generator_t *data = (bench_generator_t*)arg; 22 | memset(data->key, 0x31, 32); 23 | memset(data->blind, 0x13, 32); 24 | } 25 | 26 | static void bench_generator_generate(void* arg, int iters) { 27 | int i; 28 | bench_generator_t *data = (bench_generator_t*)arg; 29 | 30 | for (i = 0; i < iters; i++) { 31 | secp256k1_generator gen; 32 | CHECK(secp256k1_generator_generate(data->ctx, &gen, data->key)); 33 | data->key[i & 31]++; 34 | } 35 | } 36 | 37 | static void bench_generator_generate_blinded(void* arg, int iters) { 38 | int i; 39 | bench_generator_t *data = (bench_generator_t*)arg; 40 | 41 | for (i = 0; i < iters; i++) { 42 | secp256k1_generator gen; 43 | CHECK(secp256k1_generator_generate_blinded(data->ctx, &gen, data->key, data->blind)); 44 | data->key[1 + (i & 30)]++; 45 | data->blind[1 + (i & 30)]++; 46 | } 47 | } 48 | 49 | int main(void) { 50 | bench_generator_t data; 51 | int iters = get_iters(20000); 52 | 53 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 54 | 55 | run_benchmark("generator_generate", bench_generator_generate, bench_generator_setup, NULL, &data, 10, iters); 56 | run_benchmark("generator_generate_blinded", bench_generator_generate_blinded, bench_generator_setup, NULL, &data, 10, iters); 57 | 58 | secp256k1_context_destroy(data.ctx); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /src/bench_rangeproof.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2014, 2015 Pieter Wuille, Gregory Maxwell * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #include 8 | 9 | #include "../include/secp256k1_rangeproof.h" 10 | #include "util.h" 11 | #include "bench.h" 12 | 13 | typedef struct { 14 | secp256k1_context* ctx; 15 | secp256k1_pedersen_commitment commit; 16 | unsigned char proof[5134]; 17 | unsigned char blind[32]; 18 | size_t len; 19 | int min_bits; 20 | uint64_t v; 21 | } bench_rangeproof_t; 22 | 23 | static void bench_rangeproof_setup(void* arg) { 24 | int i; 25 | uint64_t minv; 26 | uint64_t maxv; 27 | bench_rangeproof_t *data = (bench_rangeproof_t*)arg; 28 | 29 | data->v = 0; 30 | for (i = 0; i < 32; i++) data->blind[i] = i + 1; 31 | CHECK(secp256k1_pedersen_commit(data->ctx, &data->commit, data->blind, data->v, secp256k1_generator_h)); 32 | data->len = 5134; 33 | CHECK(secp256k1_rangeproof_sign(data->ctx, data->proof, &data->len, 0, &data->commit, data->blind, (const unsigned char*)&data->commit, 0, data->min_bits, data->v, NULL, 0, NULL, 0, secp256k1_generator_h)); 34 | CHECK(secp256k1_rangeproof_verify(data->ctx, &minv, &maxv, &data->commit, data->proof, data->len, NULL, 0, secp256k1_generator_h)); 35 | } 36 | 37 | static void bench_rangeproof(void* arg, int iters) { 38 | int i; 39 | bench_rangeproof_t *data = (bench_rangeproof_t*)arg; 40 | 41 | for (i = 0; i < iters/data->min_bits; i++) { 42 | int j; 43 | uint64_t minv; 44 | uint64_t maxv; 45 | j = secp256k1_rangeproof_verify(data->ctx, &minv, &maxv, &data->commit, data->proof, data->len, NULL, 0, secp256k1_generator_h); 46 | for (j = 0; j < 4; j++) { 47 | data->proof[j + 2 + 32 *((data->min_bits + 1) >> 1) - 4] = (i >> 8)&255; 48 | } 49 | } 50 | } 51 | 52 | int main(void) { 53 | bench_rangeproof_t data; 54 | int iters; 55 | 56 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 57 | 58 | data.min_bits = 32; 59 | iters = data.min_bits*get_iters(32); 60 | 61 | run_benchmark("rangeproof_verify_bit", bench_rangeproof, bench_rangeproof_setup, NULL, &data, 10, iters); 62 | 63 | secp256k1_context_destroy(data.ctx); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /src/bench_whitelist.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2017 Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | #include 7 | 8 | #include "../include/secp256k1.h" 9 | 10 | #include "../include/secp256k1_whitelist.h" 11 | #include "util.h" 12 | #include "bench.h" 13 | #include "hash_impl.h" 14 | #include "int128_impl.h" 15 | #include "scalar_impl.h" 16 | #include "testrand_impl.h" 17 | 18 | #define MAX_N_KEYS 30 19 | 20 | typedef struct { 21 | secp256k1_context* ctx; 22 | unsigned char online_seckey[MAX_N_KEYS][32]; 23 | unsigned char summed_seckey[MAX_N_KEYS][32]; 24 | secp256k1_pubkey online_pubkeys[MAX_N_KEYS]; 25 | secp256k1_pubkey offline_pubkeys[MAX_N_KEYS]; 26 | unsigned char csub[32]; 27 | secp256k1_pubkey sub_pubkey; 28 | secp256k1_whitelist_signature sig; 29 | size_t n_keys; 30 | } bench_data; 31 | 32 | static void bench_whitelist(void* arg, int iters) { 33 | bench_data* data = (bench_data*)arg; 34 | int i; 35 | for (i = 0; i < iters; i++) { 36 | CHECK(secp256k1_whitelist_verify(data->ctx, &data->sig, data->online_pubkeys, data->offline_pubkeys, data->n_keys, &data->sub_pubkey) == 1); 37 | } 38 | } 39 | 40 | static void bench_whitelist_setup(void* arg) { 41 | bench_data* data = (bench_data*)arg; 42 | int i = 0; 43 | CHECK(secp256k1_whitelist_sign(data->ctx, &data->sig, data->online_pubkeys, data->offline_pubkeys, data->n_keys, &data->sub_pubkey, data->online_seckey[i], data->summed_seckey[i], i)); 44 | } 45 | 46 | static void run_test(bench_data* data, int iters) { 47 | char str[32]; 48 | sprintf(str, "whitelist_%i", (int)data->n_keys); 49 | run_benchmark(str, bench_whitelist, bench_whitelist_setup, NULL, data, 100, iters); 50 | } 51 | 52 | static void random_scalar_order(secp256k1_scalar *num) { 53 | do { 54 | unsigned char b32[32]; 55 | int overflow = 0; 56 | secp256k1_testrand256(b32); 57 | secp256k1_scalar_set_b32(num, b32, &overflow); 58 | if (overflow || secp256k1_scalar_is_zero(num)) { 59 | continue; 60 | } 61 | break; 62 | } while(1); 63 | } 64 | 65 | int main(void) { 66 | bench_data data; 67 | size_t i; 68 | size_t n_keys = 30; 69 | secp256k1_scalar ssub; 70 | int iters = get_iters(5); 71 | 72 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 73 | 74 | /* Start with subkey */ 75 | random_scalar_order(&ssub); 76 | secp256k1_scalar_get_b32(data.csub, &ssub); 77 | CHECK(secp256k1_ec_seckey_verify(data.ctx, data.csub) == 1); 78 | CHECK(secp256k1_ec_pubkey_create(data.ctx, &data.sub_pubkey, data.csub) == 1); 79 | /* Then offline and online whitelist keys */ 80 | for (i = 0; i < n_keys; i++) { 81 | secp256k1_scalar son, soff; 82 | 83 | /* Create two keys */ 84 | random_scalar_order(&son); 85 | secp256k1_scalar_get_b32(data.online_seckey[i], &son); 86 | CHECK(secp256k1_ec_seckey_verify(data.ctx, data.online_seckey[i]) == 1); 87 | CHECK(secp256k1_ec_pubkey_create(data.ctx, &data.online_pubkeys[i], data.online_seckey[i]) == 1); 88 | 89 | random_scalar_order(&soff); 90 | secp256k1_scalar_get_b32(data.summed_seckey[i], &soff); 91 | CHECK(secp256k1_ec_seckey_verify(data.ctx, data.summed_seckey[i]) == 1); 92 | CHECK(secp256k1_ec_pubkey_create(data.ctx, &data.offline_pubkeys[i], data.summed_seckey[i]) == 1); 93 | 94 | /* Make summed_seckey correspond to the sum of offline_pubkey and sub_pubkey */ 95 | secp256k1_scalar_add(&soff, &soff, &ssub); 96 | secp256k1_scalar_get_b32(data.summed_seckey[i], &soff); 97 | CHECK(secp256k1_ec_seckey_verify(data.ctx, data.summed_seckey[i]) == 1); 98 | } 99 | 100 | /* Run test */ 101 | for (i = 1; i <= n_keys; ++i) { 102 | data.n_keys = i; 103 | run_test(&data, iters); 104 | } 105 | 106 | secp256k1_context_destroy(data.ctx); 107 | return(0); 108 | } 109 | -------------------------------------------------------------------------------- /src/checkmem.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2022 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | /* The code here is inspired by Kris Kwiatkowski's approach in 8 | * https://github.com/kriskwiatkowski/pqc/blob/main/src/common/ct_check.h 9 | * to provide a general interface for memory-checking mechanisms, primarily 10 | * for constant-time checking. 11 | */ 12 | 13 | /* These macros are defined by this header file: 14 | * 15 | * - SECP256K1_CHECKMEM_ENABLED: 16 | * - 1 if memory-checking integration is available, 0 otherwise. 17 | * This is just a compile-time macro. Use the next macro to check it is actually 18 | * available at runtime. 19 | * - SECP256K1_CHECKMEM_RUNNING(): 20 | * - Acts like a function call, returning 1 if memory checking is available 21 | * at runtime. 22 | * - SECP256K1_CHECKMEM_CHECK(p, len): 23 | * - Assert or otherwise fail in case the len-byte memory block pointed to by p is 24 | * not considered entirely defined. 25 | * - SECP256K1_CHECKMEM_CHECK_VERIFY(p, len): 26 | * - Like SECP256K1_CHECKMEM_CHECK, but only works in VERIFY mode. 27 | * - SECP256K1_CHECKMEM_UNDEFINE(p, len): 28 | * - marks the len-byte memory block pointed to by p as undefined data (secret data, 29 | * in the context of constant-time checking). 30 | * - SECP256K1_CHECKMEM_DEFINE(p, len): 31 | * - marks the len-byte memory pointed to by p as defined data (public data, in the 32 | * context of constant-time checking). 33 | * 34 | */ 35 | 36 | #ifndef SECP256K1_CHECKMEM_H 37 | #define SECP256K1_CHECKMEM_H 38 | 39 | /* Define a statement-like macro that ignores the arguments. */ 40 | #define SECP256K1_CHECKMEM_NOOP(p, len) do { (void)(p); (void)(len); } while(0) 41 | 42 | /* If compiling under msan, map the SECP256K1_CHECKMEM_* functionality to msan. 43 | * Choose this preferentially, even when VALGRIND is defined, as msan-compiled 44 | * binaries can't be run under valgrind anyway. */ 45 | #if defined(__has_feature) 46 | # if __has_feature(memory_sanitizer) 47 | # include 48 | # define SECP256K1_CHECKMEM_ENABLED 1 49 | # define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len)) 50 | # define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len)) 51 | # define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len)) 52 | # define SECP256K1_CHECKMEM_RUNNING() (1) 53 | # endif 54 | #endif 55 | 56 | /* If valgrind integration is desired (through the VALGRIND define), implement the 57 | * SECP256K1_CHECKMEM_* macros using valgrind. */ 58 | #if !defined SECP256K1_CHECKMEM_ENABLED 59 | # if defined VALGRIND 60 | # include 61 | # if defined(__clang__) && defined(__APPLE__) 62 | # pragma clang diagnostic push 63 | # pragma clang diagnostic ignored "-Wreserved-identifier" 64 | # endif 65 | # include 66 | # if defined(__clang__) && defined(__APPLE__) 67 | # pragma clang diagnostic pop 68 | # endif 69 | # define SECP256K1_CHECKMEM_ENABLED 1 70 | # define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len)) 71 | # define SECP256K1_CHECKMEM_DEFINE(p, len) VALGRIND_MAKE_MEM_DEFINED((p), (len)) 72 | # define SECP256K1_CHECKMEM_CHECK(p, len) VALGRIND_CHECK_MEM_IS_DEFINED((p), (len)) 73 | /* VALGRIND_MAKE_MEM_DEFINED returns 0 iff not running on memcheck. 74 | * This is more precise than the RUNNING_ON_VALGRIND macro, which 75 | * checks for valgrind in general instead of memcheck specifically. */ 76 | # define SECP256K1_CHECKMEM_RUNNING() (VALGRIND_MAKE_MEM_DEFINED(NULL, 0) != 0) 77 | # endif 78 | #endif 79 | 80 | /* As a fall-back, map these macros to dummy statements. */ 81 | #if !defined SECP256K1_CHECKMEM_ENABLED 82 | # define SECP256K1_CHECKMEM_ENABLED 0 83 | # define SECP256K1_CHECKMEM_UNDEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 84 | # define SECP256K1_CHECKMEM_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 85 | # define SECP256K1_CHECKMEM_CHECK(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 86 | # define SECP256K1_CHECKMEM_RUNNING() (0) 87 | #endif 88 | 89 | #if defined VERIFY 90 | #define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_CHECK((p), (len)) 91 | #else 92 | #define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) 93 | #endif 94 | 95 | #endif /* SECP256K1_CHECKMEM_H */ 96 | -------------------------------------------------------------------------------- /src/eccommit.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2020 The libsecp256k1-zkp Developers * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECCOMMIT_H 8 | #define SECP256K1_ECCOMMIT_H 9 | 10 | /** Helper function to add a 32-byte value to a scalar */ 11 | static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak); 12 | /** Helper function to add a 32-byte value, times G, to an EC point */ 13 | static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak); 14 | 15 | /** Serializes elem as a 33 byte array. This is non-constant time with respect to 16 | * whether pubp is the point at infinity. Thus, you may need to declassify 17 | * pubp->infinity before calling this function. */ 18 | static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33); 19 | /** Compute an ec commitment tweak as hash(pubkey, data). */ 20 | static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size); 21 | /** Compute an ec commitment as pubkey + hash(pubkey, data)*G. */ 22 | static int secp256k1_ec_commit(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size); 23 | /** Compute a secret key commitment as seckey + hash(pubkey, data). */ 24 | static int secp256k1_ec_commit_seckey(const secp256k1_ecmult_gen_context* ecmult_gen_ctx, secp256k1_scalar* seckey, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size); 25 | /** Verify an ec commitment as pubkey + hash(pubkey, data)*G ?= commitment. */ 26 | static int secp256k1_ec_commit_verify(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size); 27 | 28 | #endif /* SECP256K1_ECCOMMIT_H */ 29 | -------------------------------------------------------------------------------- /src/eccommit_impl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2020 The libsecp256k1 Developers * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #include 8 | 9 | #include "eckey.h" 10 | #include "hash.h" 11 | 12 | /* from secp256k1.c */ 13 | static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak); 14 | static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *pubp, const unsigned char *tweak); 15 | 16 | static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33) { 17 | if (secp256k1_ge_is_infinity(pubp)) { 18 | return 0; 19 | } 20 | secp256k1_fe_normalize(&pubp->x); 21 | secp256k1_fe_normalize(&pubp->y); 22 | secp256k1_fe_get_b32(&buf33[1], &pubp->x); 23 | buf33[0] = secp256k1_fe_is_odd(&pubp->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; 24 | return 1; 25 | } 26 | 27 | /* Compute an ec commitment tweak as hash(pubp, data). */ 28 | static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) 29 | { 30 | unsigned char rbuf[33]; 31 | 32 | if (!secp256k1_ec_commit_pubkey_serialize_const(pubp, rbuf)) { 33 | return 0; 34 | } 35 | secp256k1_sha256_write(sha, rbuf, sizeof(rbuf)); 36 | secp256k1_sha256_write(sha, data, data_size); 37 | secp256k1_sha256_finalize(sha, tweak32); 38 | return 1; 39 | } 40 | 41 | /* Compute an ec commitment as pubp + hash(pubp, data)*G. */ 42 | static int secp256k1_ec_commit(secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { 43 | unsigned char tweak[32]; 44 | 45 | *commitp = *pubp; 46 | return secp256k1_ec_commit_tweak(tweak, commitp, sha, data, data_size) 47 | && secp256k1_ec_pubkey_tweak_add_helper(commitp, tweak); 48 | } 49 | 50 | /* Compute the seckey of an ec commitment from the original secret key of the pubkey as seckey + 51 | * hash(pubp, data). */ 52 | static int secp256k1_ec_commit_seckey(secp256k1_scalar* seckey, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { 53 | unsigned char tweak[32]; 54 | return secp256k1_ec_commit_tweak(tweak, pubp, sha, data, data_size) 55 | && secp256k1_ec_seckey_tweak_add_helper(seckey, tweak); 56 | } 57 | 58 | /* Verify an ec commitment as pubp + hash(pubp, data)*G ?= commitment. */ 59 | static int secp256k1_ec_commit_verify(const secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { 60 | secp256k1_gej pj; 61 | secp256k1_ge p; 62 | 63 | if (!secp256k1_ec_commit(&p, pubp, sha, data, data_size)) { 64 | return 0; 65 | } 66 | 67 | /* Return p == commitp */ 68 | secp256k1_ge_neg(&p, &p); 69 | secp256k1_gej_set_ge(&pj, &p); 70 | secp256k1_gej_add_ge_var(&pj, &pj, commitp, NULL); 71 | return secp256k1_gej_is_infinity(&pj); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/ecdsa.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECDSA_H 8 | #define SECP256K1_ECDSA_H 9 | 10 | #include 11 | 12 | #include "scalar.h" 13 | #include "group.h" 14 | #include "ecmult.h" 15 | 16 | static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); 17 | static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); 18 | static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); 19 | static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); 20 | 21 | #endif /* SECP256K1_ECDSA_H */ 22 | -------------------------------------------------------------------------------- /src/eckey.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECKEY_H 8 | #define SECP256K1_ECKEY_H 9 | 10 | #include 11 | 12 | #include "group.h" 13 | #include "scalar.h" 14 | #include "ecmult.h" 15 | #include "ecmult_gen.h" 16 | 17 | static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); 18 | static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); 19 | 20 | static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); 21 | static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak); 22 | static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); 23 | static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak); 24 | 25 | #endif /* SECP256K1_ECKEY_H */ 26 | -------------------------------------------------------------------------------- /src/eckey_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECKEY_IMPL_H 8 | #define SECP256K1_ECKEY_IMPL_H 9 | 10 | #include "eckey.h" 11 | 12 | #include "scalar.h" 13 | #include "field.h" 14 | #include "group.h" 15 | #include "ecmult_gen.h" 16 | 17 | static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { 18 | if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { 19 | secp256k1_fe x; 20 | return secp256k1_fe_set_b32_limit(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD); 21 | } else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { 22 | secp256k1_fe x, y; 23 | if (!secp256k1_fe_set_b32_limit(&x, pub+1) || !secp256k1_fe_set_b32_limit(&y, pub+33)) { 24 | return 0; 25 | } 26 | secp256k1_ge_set_xy(elem, &x, &y); 27 | if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && 28 | secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { 29 | return 0; 30 | } 31 | return secp256k1_ge_is_valid_var(elem); 32 | } else { 33 | return 0; 34 | } 35 | } 36 | 37 | static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { 38 | if (secp256k1_ge_is_infinity(elem)) { 39 | return 0; 40 | } 41 | secp256k1_fe_normalize_var(&elem->x); 42 | secp256k1_fe_normalize_var(&elem->y); 43 | secp256k1_fe_get_b32(&pub[1], &elem->x); 44 | if (compressed) { 45 | *size = 33; 46 | pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; 47 | } else { 48 | *size = 65; 49 | pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; 50 | secp256k1_fe_get_b32(&pub[33], &elem->y); 51 | } 52 | return 1; 53 | } 54 | 55 | static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { 56 | secp256k1_scalar_add(key, key, tweak); 57 | return !secp256k1_scalar_is_zero(key); 58 | } 59 | 60 | static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak) { 61 | secp256k1_gej pt; 62 | secp256k1_gej_set_ge(&pt, key); 63 | secp256k1_ecmult(&pt, &pt, &secp256k1_scalar_one, tweak); 64 | 65 | if (secp256k1_gej_is_infinity(&pt)) { 66 | return 0; 67 | } 68 | secp256k1_ge_set_gej(key, &pt); 69 | return 1; 70 | } 71 | 72 | static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) { 73 | int ret; 74 | ret = !secp256k1_scalar_is_zero(tweak); 75 | 76 | secp256k1_scalar_mul(key, key, tweak); 77 | return ret; 78 | } 79 | 80 | static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak) { 81 | secp256k1_gej pt; 82 | if (secp256k1_scalar_is_zero(tweak)) { 83 | return 0; 84 | } 85 | 86 | secp256k1_gej_set_ge(&pt, key); 87 | secp256k1_ecmult(&pt, &pt, tweak, &secp256k1_scalar_zero); 88 | secp256k1_ge_set_gej(key, &pt); 89 | return 1; 90 | } 91 | 92 | #endif /* SECP256K1_ECKEY_IMPL_H */ 93 | -------------------------------------------------------------------------------- /src/ecmult.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_H 8 | #define SECP256K1_ECMULT_H 9 | 10 | #include "group.h" 11 | #include "scalar.h" 12 | #include "scratch.h" 13 | 14 | #ifndef ECMULT_WINDOW_SIZE 15 | # define ECMULT_WINDOW_SIZE 15 16 | # ifdef DEBUG_CONFIG 17 | # pragma message DEBUG_CONFIG_MSG("ECMULT_WINDOW_SIZE undefined, assuming default value") 18 | # endif 19 | #endif 20 | 21 | #ifdef DEBUG_CONFIG 22 | # pragma message DEBUG_CONFIG_DEF(ECMULT_WINDOW_SIZE) 23 | #endif 24 | 25 | /* No one will ever need more than a window size of 24. The code might 26 | * be correct for larger values of ECMULT_WINDOW_SIZE but this is not 27 | * tested. 28 | * 29 | * The following limitations are known, and there are probably more: 30 | * If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect 31 | * because the size of the memory object that we allocate (in bytes) 32 | * will not fit in a size_t. 33 | * If WINDOW_G > 31 and int has 32 bits, then the code is incorrect 34 | * because certain expressions will overflow. 35 | */ 36 | #if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24 37 | # error Set ECMULT_WINDOW_SIZE to an integer in range [2..24]. 38 | #endif 39 | 40 | /** The number of entries a table with precomputed multiples needs to have. */ 41 | #define ECMULT_TABLE_SIZE(w) (1L << ((w)-2)) 42 | 43 | /** Double multiply: R = na*A + ng*G */ 44 | static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); 45 | 46 | typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data); 47 | 48 | /** 49 | * Multi-multiply: R = inp_g_sc * G + sum_i ni * Ai. 50 | * Chooses the right algorithm for a given number of points and scratch space 51 | * size. Resets and overwrites the given scratch space. If the points do not 52 | * fit in the scratch space the algorithm is repeatedly run with batches of 53 | * points. If no scratch space is given then a simple algorithm is used that 54 | * simply multiplies the points with the corresponding scalars and adds them up. 55 | * Returns: 1 on success (including when inp_g_sc is NULL and n is 0) 56 | * 0 if there is not enough scratch space for a single point or 57 | * callback returns 0 58 | */ 59 | static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n); 60 | 61 | #endif /* SECP256K1_ECMULT_H */ 62 | -------------------------------------------------------------------------------- /src/ecmult_compute_table.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *****************************************************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_COMPUTE_TABLE_H 8 | #define SECP256K1_ECMULT_COMPUTE_TABLE_H 9 | 10 | /* Construct table of all odd multiples of gen in range 1..(2**(window_g-1)-1). */ 11 | static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen); 12 | 13 | /* Like secp256k1_ecmult_compute_table, but one for both gen and gen*2^128. */ 14 | static void secp256k1_ecmult_compute_two_tables(secp256k1_ge_storage* table, secp256k1_ge_storage* table_128, int window_g, const secp256k1_ge* gen); 15 | 16 | #endif /* SECP256K1_ECMULT_COMPUTE_TABLE_H */ 17 | -------------------------------------------------------------------------------- /src/ecmult_compute_table_impl.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *****************************************************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H 8 | #define SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H 9 | 10 | #include "ecmult_compute_table.h" 11 | #include "group_impl.h" 12 | #include "field_impl.h" 13 | #include "ecmult.h" 14 | #include "util.h" 15 | 16 | static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen) { 17 | secp256k1_gej gj; 18 | secp256k1_ge ge, dgen; 19 | int j; 20 | 21 | gj = *gen; 22 | secp256k1_ge_set_gej_var(&ge, &gj); 23 | secp256k1_ge_to_storage(&table[0], &ge); 24 | 25 | secp256k1_gej_double_var(&gj, gen, NULL); 26 | secp256k1_ge_set_gej_var(&dgen, &gj); 27 | 28 | for (j = 1; j < ECMULT_TABLE_SIZE(window_g); ++j) { 29 | secp256k1_gej_set_ge(&gj, &ge); 30 | secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL); 31 | secp256k1_ge_set_gej_var(&ge, &gj); 32 | secp256k1_ge_to_storage(&table[j], &ge); 33 | } 34 | } 35 | 36 | /* Like secp256k1_ecmult_compute_table, but one for both gen and gen*2^128. */ 37 | static void secp256k1_ecmult_compute_two_tables(secp256k1_ge_storage* table, secp256k1_ge_storage* table_128, int window_g, const secp256k1_ge* gen) { 38 | secp256k1_gej gj; 39 | int i; 40 | 41 | secp256k1_gej_set_ge(&gj, gen); 42 | secp256k1_ecmult_compute_table(table, window_g, &gj); 43 | for (i = 0; i < 128; ++i) { 44 | secp256k1_gej_double_var(&gj, &gj, NULL); 45 | } 46 | secp256k1_ecmult_compute_table(table_128, window_g, &gj); 47 | } 48 | 49 | #endif /* SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H */ 50 | -------------------------------------------------------------------------------- /src/ecmult_const.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_CONST_H 8 | #define SECP256K1_ECMULT_CONST_H 9 | 10 | #include "scalar.h" 11 | #include "group.h" 12 | 13 | /** 14 | * Multiply: R = q*A (in constant-time for q) 15 | */ 16 | static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); 17 | 18 | /** 19 | * Same as secp256k1_ecmult_const, but takes in an x coordinate of the base point 20 | * only, specified as fraction n/d (numerator/denominator). Only the x coordinate of the result is 21 | * returned. 22 | * 23 | * If known_on_curve is 0, a verification is performed that n/d is a valid X 24 | * coordinate, and 0 is returned if not. Otherwise, 1 is returned. 25 | * 26 | * d being NULL is interpreted as d=1. If non-NULL, d must not be zero. q must not be zero. 27 | * 28 | * Constant time in the value of q, but not any other inputs. 29 | */ 30 | static int secp256k1_ecmult_const_xonly( 31 | secp256k1_fe *r, 32 | const secp256k1_fe *n, 33 | const secp256k1_fe *d, 34 | const secp256k1_scalar *q, 35 | int known_on_curve 36 | ); 37 | 38 | #endif /* SECP256K1_ECMULT_CONST_H */ 39 | -------------------------------------------------------------------------------- /src/ecmult_gen.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_GEN_H 8 | #define SECP256K1_ECMULT_GEN_H 9 | 10 | #include "scalar.h" 11 | #include "group.h" 12 | 13 | #ifndef ECMULT_GEN_PREC_BITS 14 | # define ECMULT_GEN_PREC_BITS 4 15 | # ifdef DEBUG_CONFIG 16 | # pragma message DEBUG_CONFIG_MSG("ECMULT_GEN_PREC_BITS undefined, assuming default value") 17 | # endif 18 | #endif 19 | 20 | #ifdef DEBUG_CONFIG 21 | # pragma message DEBUG_CONFIG_DEF(ECMULT_GEN_PREC_BITS) 22 | #endif 23 | 24 | #if ECMULT_GEN_PREC_BITS != 2 && ECMULT_GEN_PREC_BITS != 4 && ECMULT_GEN_PREC_BITS != 8 25 | # error "Set ECMULT_GEN_PREC_BITS to 2, 4 or 8." 26 | #endif 27 | 28 | #define ECMULT_GEN_PREC_G(bits) (1 << bits) 29 | #define ECMULT_GEN_PREC_N(bits) (256 / bits) 30 | 31 | typedef struct { 32 | /* Whether the context has been built. */ 33 | int built; 34 | 35 | /* Blinding values used when computing (n-b)G + bG. */ 36 | secp256k1_scalar blind; /* -b */ 37 | secp256k1_gej initial; /* bG */ 38 | } secp256k1_ecmult_gen_context; 39 | 40 | static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx); 41 | static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); 42 | 43 | /** Multiply with the generator: R = a*G */ 44 | static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); 45 | 46 | static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); 47 | 48 | #endif /* SECP256K1_ECMULT_GEN_H */ 49 | -------------------------------------------------------------------------------- /src/ecmult_gen_compute_table.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H 8 | #define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H 9 | 10 | #include "ecmult_gen.h" 11 | 12 | static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits); 13 | 14 | #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */ 15 | -------------------------------------------------------------------------------- /src/ecmult_gen_compute_table_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H 8 | #define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H 9 | 10 | #include "ecmult_gen_compute_table.h" 11 | #include "group_impl.h" 12 | #include "field_impl.h" 13 | #include "ecmult_gen.h" 14 | #include "util.h" 15 | 16 | static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits) { 17 | int g = ECMULT_GEN_PREC_G(bits); 18 | int n = ECMULT_GEN_PREC_N(bits); 19 | 20 | secp256k1_ge* prec = checked_malloc(&default_error_callback, n * g * sizeof(*prec)); 21 | secp256k1_gej gj; 22 | secp256k1_gej nums_gej; 23 | int i, j; 24 | 25 | VERIFY_CHECK(g > 0); 26 | VERIFY_CHECK(n > 0); 27 | 28 | /* get the generator */ 29 | secp256k1_gej_set_ge(&gj, gen); 30 | 31 | /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ 32 | { 33 | static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; 34 | secp256k1_fe nums_x; 35 | secp256k1_ge nums_ge; 36 | int r; 37 | r = secp256k1_fe_set_b32_limit(&nums_x, nums_b32); 38 | (void)r; 39 | VERIFY_CHECK(r); 40 | r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); 41 | (void)r; 42 | VERIFY_CHECK(r); 43 | secp256k1_gej_set_ge(&nums_gej, &nums_ge); 44 | /* Add G to make the bits in x uniformly distributed. */ 45 | secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, gen, NULL); 46 | } 47 | 48 | /* compute prec. */ 49 | { 50 | secp256k1_gej gbase; 51 | secp256k1_gej numsbase; 52 | secp256k1_gej* precj = checked_malloc(&default_error_callback, n * g * sizeof(*precj)); /* Jacobian versions of prec. */ 53 | gbase = gj; /* PREC_G^j * G */ 54 | numsbase = nums_gej; /* 2^j * nums. */ 55 | for (j = 0; j < n; j++) { 56 | /* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */ 57 | precj[j*g] = numsbase; 58 | for (i = 1; i < g; i++) { 59 | secp256k1_gej_add_var(&precj[j*g + i], &precj[j*g + i - 1], &gbase, NULL); 60 | } 61 | /* Multiply gbase by PREC_G. */ 62 | for (i = 0; i < bits; i++) { 63 | secp256k1_gej_double_var(&gbase, &gbase, NULL); 64 | } 65 | /* Multiply numbase by 2. */ 66 | secp256k1_gej_double_var(&numsbase, &numsbase, NULL); 67 | if (j == n - 2) { 68 | /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ 69 | secp256k1_gej_neg(&numsbase, &numsbase); 70 | secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); 71 | } 72 | } 73 | secp256k1_ge_set_all_gej_var(prec, precj, n * g); 74 | free(precj); 75 | } 76 | for (j = 0; j < n; j++) { 77 | for (i = 0; i < g; i++) { 78 | secp256k1_ge_to_storage(&table[j*g + i], &prec[j*g + i]); 79 | } 80 | } 81 | free(prec); 82 | } 83 | 84 | #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H */ 85 | -------------------------------------------------------------------------------- /src/field_10x26.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_FIELD_REPR_H 8 | #define SECP256K1_FIELD_REPR_H 9 | 10 | #include 11 | 12 | /** This field implementation represents the value as 10 uint32_t limbs in base 13 | * 2^26. */ 14 | typedef struct { 15 | /* A field element f represents the sum(i=0..9, f.n[i] << (i*26)) mod p, 16 | * where p is the field modulus, 2^256 - 2^32 - 977. 17 | * 18 | * The individual limbs f.n[i] can exceed 2^26; the field's magnitude roughly 19 | * corresponds to how much excess is allowed. The value 20 | * sum(i=0..9, f.n[i] << (i*26)) may exceed p, unless the field element is 21 | * normalized. */ 22 | uint32_t n[10]; 23 | /* 24 | * Magnitude m requires: 25 | * n[i] <= 2 * m * (2^26 - 1) for i=0..8 26 | * n[9] <= 2 * m * (2^22 - 1) 27 | * 28 | * Normalized requires: 29 | * n[i] <= (2^26 - 1) for i=0..8 30 | * sum(i=0..9, n[i] << (i*26)) < p 31 | * (together these imply n[9] <= 2^22 - 1) 32 | */ 33 | SECP256K1_FE_VERIFY_FIELDS 34 | } secp256k1_fe; 35 | 36 | /* Unpacks a constant into a overlapping multi-limbed FE element. */ 37 | #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ 38 | (d0) & 0x3FFFFFFUL, \ 39 | (((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \ 40 | (((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \ 41 | (((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \ 42 | (((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \ 43 | (((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \ 44 | (((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \ 45 | (((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \ 46 | (((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \ 47 | (((uint32_t)d7) >> 10) \ 48 | } 49 | 50 | typedef struct { 51 | uint32_t n[8]; 52 | } secp256k1_fe_storage; 53 | 54 | #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} 55 | #define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] 56 | 57 | #endif /* SECP256K1_FIELD_REPR_H */ 58 | -------------------------------------------------------------------------------- /src/field_5x52.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_FIELD_REPR_H 8 | #define SECP256K1_FIELD_REPR_H 9 | 10 | #include 11 | 12 | /** This field implementation represents the value as 5 uint64_t limbs in base 13 | * 2^52. */ 14 | typedef struct { 15 | /* A field element f represents the sum(i=0..4, f.n[i] << (i*52)) mod p, 16 | * where p is the field modulus, 2^256 - 2^32 - 977. 17 | * 18 | * The individual limbs f.n[i] can exceed 2^52; the field's magnitude roughly 19 | * corresponds to how much excess is allowed. The value 20 | * sum(i=0..4, f.n[i] << (i*52)) may exceed p, unless the field element is 21 | * normalized. */ 22 | uint64_t n[5]; 23 | /* 24 | * Magnitude m requires: 25 | * n[i] <= 2 * m * (2^52 - 1) for i=0..3 26 | * n[4] <= 2 * m * (2^48 - 1) 27 | * 28 | * Normalized requires: 29 | * n[i] <= (2^52 - 1) for i=0..3 30 | * sum(i=0..4, n[i] << (i*52)) < p 31 | * (together these imply n[4] <= 2^48 - 1) 32 | */ 33 | SECP256K1_FE_VERIFY_FIELDS 34 | } secp256k1_fe; 35 | 36 | /* Unpacks a constant into a overlapping multi-limbed FE element. */ 37 | #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ 38 | (d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \ 39 | ((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \ 40 | ((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \ 41 | ((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \ 42 | ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \ 43 | } 44 | 45 | typedef struct { 46 | uint64_t n[4]; 47 | } secp256k1_fe_storage; 48 | 49 | #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ 50 | (d0) | (((uint64_t)(d1)) << 32), \ 51 | (d2) | (((uint64_t)(d3)) << 32), \ 52 | (d4) | (((uint64_t)(d5)) << 32), \ 53 | (d6) | (((uint64_t)(d7)) << 32) \ 54 | }} 55 | 56 | #define SECP256K1_FE_STORAGE_CONST_GET(d) \ 57 | (uint32_t)(d.n[3] >> 32), (uint32_t)d.n[3], \ 58 | (uint32_t)(d.n[2] >> 32), (uint32_t)d.n[2], \ 59 | (uint32_t)(d.n[1] >> 32), (uint32_t)d.n[1], \ 60 | (uint32_t)(d.n[0] >> 32), (uint32_t)d.n[0] 61 | 62 | #endif /* SECP256K1_FIELD_REPR_H */ 63 | -------------------------------------------------------------------------------- /src/hash.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_HASH_H 8 | #define SECP256K1_HASH_H 9 | 10 | #include 11 | #include 12 | 13 | typedef struct { 14 | uint32_t s[8]; 15 | unsigned char buf[64]; 16 | uint64_t bytes; 17 | } secp256k1_sha256; 18 | 19 | static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); 20 | static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); 21 | static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); 22 | 23 | typedef struct { 24 | secp256k1_sha256 inner, outer; 25 | } secp256k1_hmac_sha256; 26 | 27 | static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); 28 | static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); 29 | static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); 30 | 31 | typedef struct { 32 | unsigned char v[32]; 33 | unsigned char k[32]; 34 | int retry; 35 | } secp256k1_rfc6979_hmac_sha256; 36 | 37 | static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); 38 | static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); 39 | static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); 40 | 41 | #endif /* SECP256K1_HASH_H */ 42 | -------------------------------------------------------------------------------- /src/int128.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_H 2 | #define SECP256K1_INT128_H 3 | 4 | #include "util.h" 5 | 6 | #if defined(SECP256K1_WIDEMUL_INT128) 7 | # if defined(SECP256K1_INT128_NATIVE) 8 | # include "int128_native.h" 9 | # elif defined(SECP256K1_INT128_STRUCT) 10 | # include "int128_struct.h" 11 | # else 12 | # error "Please select int128 implementation" 13 | # endif 14 | 15 | /* Construct an unsigned 128-bit value from a high and a low 64-bit value. */ 16 | static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo); 17 | 18 | /* Multiply two unsigned 64-bit values a and b and write the result to r. */ 19 | static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b); 20 | 21 | /* Multiply two unsigned 64-bit values a and b and add the result to r. 22 | * The final result is taken modulo 2^128. 23 | */ 24 | static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b); 25 | 26 | /* Add an unsigned 64-bit value a to r. 27 | * The final result is taken modulo 2^128. 28 | */ 29 | static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a); 30 | 31 | /* Unsigned (logical) right shift. 32 | * Non-constant time in n. 33 | */ 34 | static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n); 35 | 36 | /* Return the low 64-bits of a 128-bit value as an unsigned 64-bit value. */ 37 | static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a); 38 | 39 | /* Return the high 64-bits of a 128-bit value as an unsigned 64-bit value. */ 40 | static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a); 41 | 42 | /* Write an unsigned 64-bit value to r. */ 43 | static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a); 44 | 45 | /* Tests if r is strictly less than to 2^n. 46 | * n must be strictly less than 128. 47 | */ 48 | static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n); 49 | 50 | /* Construct an signed 128-bit value from a high and a low 64-bit value. */ 51 | static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo); 52 | 53 | /* Multiply two signed 64-bit values a and b and write the result to r. */ 54 | static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b); 55 | 56 | /* Multiply two signed 64-bit values a and b and add the result to r. 57 | * Overflow or underflow from the addition is undefined behaviour. 58 | */ 59 | static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b); 60 | 61 | /* Compute a*d - b*c from signed 64-bit values and write the result to r. */ 62 | static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d); 63 | 64 | /* Signed (arithmetic) right shift. 65 | * Non-constant time in b. 66 | */ 67 | static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int b); 68 | 69 | /* Return the input value modulo 2^64. */ 70 | static SECP256K1_INLINE uint64_t secp256k1_i128_to_u64(const secp256k1_int128 *a); 71 | 72 | /* Return the value as a signed 64-bit value. 73 | * Requires the input to be between INT64_MIN and INT64_MAX. 74 | */ 75 | static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a); 76 | 77 | /* Write a signed 64-bit value to r. */ 78 | static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a); 79 | 80 | /* Compare two 128-bit values for equality. */ 81 | static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b); 82 | 83 | /* Tests if r is equal to sign*2^n (sign must be 1 or -1). 84 | * n must be strictly less than 127. 85 | */ 86 | static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign); 87 | 88 | #endif 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/int128_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_IMPL_H 2 | #define SECP256K1_INT128_IMPL_H 3 | 4 | #include "util.h" 5 | 6 | #include "int128.h" 7 | 8 | #if defined(SECP256K1_WIDEMUL_INT128) 9 | # if defined(SECP256K1_INT128_NATIVE) 10 | # include "int128_native_impl.h" 11 | # elif defined(SECP256K1_INT128_STRUCT) 12 | # include "int128_struct_impl.h" 13 | # else 14 | # error "Please select int128 implementation" 15 | # endif 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/int128_native.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_NATIVE_H 2 | #define SECP256K1_INT128_NATIVE_H 3 | 4 | #include 5 | #include "util.h" 6 | 7 | #if !defined(UINT128_MAX) && defined(__SIZEOF_INT128__) 8 | SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; 9 | SECP256K1_GNUC_EXT typedef __int128 int128_t; 10 | # define UINT128_MAX ((uint128_t)(-1)) 11 | # define INT128_MAX ((int128_t)(UINT128_MAX >> 1)) 12 | # define INT128_MIN (-INT128_MAX - 1) 13 | /* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */ 14 | #endif 15 | 16 | typedef uint128_t secp256k1_uint128; 17 | typedef int128_t secp256k1_int128; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/int128_native_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_NATIVE_IMPL_H 2 | #define SECP256K1_INT128_NATIVE_IMPL_H 3 | 4 | #include "int128.h" 5 | #include "util.h" 6 | 7 | static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) { 8 | *r = (((uint128_t)hi) << 64) + lo; 9 | } 10 | 11 | static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) { 12 | *r = (uint128_t)a * b; 13 | } 14 | 15 | static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) { 16 | *r += (uint128_t)a * b; 17 | } 18 | 19 | static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) { 20 | *r += a; 21 | } 22 | 23 | static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n) { 24 | VERIFY_CHECK(n < 128); 25 | *r >>= n; 26 | } 27 | 28 | static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) { 29 | return (uint64_t)(*a); 30 | } 31 | 32 | static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a) { 33 | return (uint64_t)(*a >> 64); 34 | } 35 | 36 | static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) { 37 | *r = a; 38 | } 39 | 40 | static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n) { 41 | VERIFY_CHECK(n < 128); 42 | return (*r >> n == 0); 43 | } 44 | 45 | static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo) { 46 | *r = (((uint128_t)(uint64_t)hi) << 64) + lo; 47 | } 48 | 49 | static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) { 50 | *r = (int128_t)a * b; 51 | } 52 | 53 | static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) { 54 | int128_t ab = (int128_t)a * b; 55 | VERIFY_CHECK(0 <= ab ? *r <= INT128_MAX - ab : INT128_MIN - ab <= *r); 56 | *r += ab; 57 | } 58 | 59 | static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) { 60 | int128_t ad = (int128_t)a * d; 61 | int128_t bc = (int128_t)b * c; 62 | VERIFY_CHECK(0 <= bc ? INT128_MIN + bc <= ad : ad <= INT128_MAX + bc); 63 | *r = ad - bc; 64 | } 65 | 66 | static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int n) { 67 | VERIFY_CHECK(n < 128); 68 | *r >>= n; 69 | } 70 | 71 | static SECP256K1_INLINE uint64_t secp256k1_i128_to_u64(const secp256k1_int128 *a) { 72 | return (uint64_t)*a; 73 | } 74 | 75 | static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) { 76 | VERIFY_CHECK(INT64_MIN <= *a && *a <= INT64_MAX); 77 | return *a; 78 | } 79 | 80 | static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) { 81 | *r = a; 82 | } 83 | 84 | static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b) { 85 | return *a == *b; 86 | } 87 | 88 | static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) { 89 | VERIFY_CHECK(n < 127); 90 | VERIFY_CHECK(sign == 1 || sign == -1); 91 | return (*r == (int128_t)((uint128_t)sign << n)); 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/int128_struct.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_INT128_STRUCT_H 2 | #define SECP256K1_INT128_STRUCT_H 3 | 4 | #include 5 | #include "util.h" 6 | 7 | typedef struct { 8 | uint64_t lo; 9 | uint64_t hi; 10 | } secp256k1_uint128; 11 | 12 | typedef secp256k1_uint128 secp256k1_int128; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/modinv32.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Peter Dettman * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODINV32_H 8 | #define SECP256K1_MODINV32_H 9 | 10 | #include "util.h" 11 | 12 | /* A signed 30-bit limb representation of integers. 13 | * 14 | * Its value is sum(v[i] * 2^(30*i), i=0..8). */ 15 | typedef struct { 16 | int32_t v[9]; 17 | } secp256k1_modinv32_signed30; 18 | 19 | typedef struct { 20 | /* The modulus in signed30 notation, must be odd and in [3, 2^256]. */ 21 | secp256k1_modinv32_signed30 modulus; 22 | 23 | /* modulus^{-1} mod 2^30 */ 24 | uint32_t modulus_inv30; 25 | } secp256k1_modinv32_modinfo; 26 | 27 | /* Replace x with its modular inverse mod modinfo->modulus. x must be in range [0, modulus). 28 | * If x is zero, the result will be zero as well. If not, the inverse must exist (i.e., the gcd of 29 | * x and modulus must be 1). These rules are automatically satisfied if the modulus is prime. 30 | * 31 | * On output, all of x's limbs will be in [0, 2^30). 32 | */ 33 | static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); 34 | 35 | /* Same as secp256k1_modinv32_var, but constant time in x (not in the modulus). */ 36 | static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); 37 | 38 | /* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus 39 | * cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result 40 | * cannot be computed. */ 41 | static int secp256k1_jacobi32_maybe_var(const secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); 42 | 43 | #endif /* SECP256K1_MODINV32_H */ 44 | -------------------------------------------------------------------------------- /src/modinv64.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Peter Dettman * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODINV64_H 8 | #define SECP256K1_MODINV64_H 9 | 10 | #include "util.h" 11 | 12 | #ifndef SECP256K1_WIDEMUL_INT128 13 | #error "modinv64 requires 128-bit wide multiplication support" 14 | #endif 15 | 16 | /* A signed 62-bit limb representation of integers. 17 | * 18 | * Its value is sum(v[i] * 2^(62*i), i=0..4). */ 19 | typedef struct { 20 | int64_t v[5]; 21 | } secp256k1_modinv64_signed62; 22 | 23 | typedef struct { 24 | /* The modulus in signed62 notation, must be odd and in [3, 2^256]. */ 25 | secp256k1_modinv64_signed62 modulus; 26 | 27 | /* modulus^{-1} mod 2^62 */ 28 | uint64_t modulus_inv62; 29 | } secp256k1_modinv64_modinfo; 30 | 31 | /* Replace x with its modular inverse mod modinfo->modulus. x must be in range [0, modulus). 32 | * If x is zero, the result will be zero as well. If not, the inverse must exist (i.e., the gcd of 33 | * x and modulus must be 1). These rules are automatically satisfied if the modulus is prime. 34 | * 35 | * On output, all of x's limbs will be in [0, 2^62). 36 | */ 37 | static void secp256k1_modinv64_var(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); 38 | 39 | /* Same as secp256k1_modinv64_var, but constant time in x (not in the modulus). */ 40 | static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); 41 | 42 | /* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus 43 | * cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result 44 | * cannot be computed. */ 45 | static int secp256k1_jacobi64_maybe_var(const secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); 46 | 47 | #endif /* SECP256K1_MODINV64_H */ 48 | -------------------------------------------------------------------------------- /src/modules/bppp/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_bppp.h 2 | noinst_HEADERS += src/modules/bppp/bppp_util.h 3 | noinst_HEADERS += src/modules/bppp/main_impl.h 4 | noinst_HEADERS += src/modules/bppp/bppp_transcript_impl.h 5 | noinst_HEADERS += src/modules/bppp/bppp_norm_product_impl.h 6 | noinst_HEADERS += src/modules/bppp/tests_impl.h 7 | 8 | if USE_BENCHMARK 9 | noinst_PROGRAMS += bench_bppp 10 | bench_bppp_SOURCES = src/bench_bppp.c 11 | bench_bppp_LDADD = libsecp256k1.la 12 | bench_bppp_CPPFLAGS = $(SECP_CONFIG_DEFINES) 13 | endif 14 | -------------------------------------------------------------------------------- /src/modules/bppp/bppp_transcript_impl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2022 Sanket Kanjalkar * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | #ifndef SECP256K1_MODULE_BPPP_PP_TRANSCRIPT_IMPL_H 7 | #define SECP256K1_MODULE_BPPP_PP_TRANSCRIPT_IMPL_H 8 | 9 | #include "../../group.h" 10 | #include "../../scalar.h" 11 | #include "bppp_util.h" 12 | 13 | /* Initializes SHA256 with fixed midstate. This midstate was computed by applying 14 | * SHA256 to SHA256("Bulletproofs_pp/v0/commitment")||SHA256("Bulletproofs_pp/v0/commitment"). 15 | */ 16 | static void secp256k1_bppp_sha256_tagged_commitment_init(secp256k1_sha256 *sha) { 17 | secp256k1_sha256_initialize(sha); 18 | sha->s[0] = 0x52fc8185ul; 19 | sha->s[1] = 0x0e7debf0ul; 20 | sha->s[2] = 0xb0967270ul; 21 | sha->s[3] = 0x6f5abfe1ul; 22 | sha->s[4] = 0x822bdec0ul; 23 | sha->s[5] = 0x36db8beful; 24 | sha->s[6] = 0x03d9e1f1ul; 25 | sha->s[7] = 0x8a5cef6ful; 26 | 27 | sha->bytes = 64; 28 | } 29 | 30 | /* Obtain a challenge scalar from the current transcript.*/ 31 | static void secp256k1_bppp_challenge_scalar(secp256k1_scalar* ch, const secp256k1_sha256 *transcript, uint64_t idx) { 32 | unsigned char buf[32]; 33 | secp256k1_sha256 sha = *transcript; 34 | secp256k1_bppp_le64(buf, idx); 35 | secp256k1_sha256_write(&sha, buf, 8); 36 | secp256k1_sha256_finalize(&sha, buf); 37 | secp256k1_scalar_set_b32(ch, buf, NULL); 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/modules/bppp/bppp_util.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2020 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_BPPP_UTIL_H 8 | #define SECP256K1_MODULE_BPPP_UTIL_H 9 | 10 | #include "../../field.h" 11 | #include "../../group.h" 12 | #include "../../hash.h" 13 | #include "../../eckey.h" 14 | 15 | /* Outputs a pair of points, amortizing the parity byte between them 16 | * Assumes both points' coordinates have been normalized. 17 | */ 18 | static void secp256k1_bppp_serialize_points(unsigned char *output, secp256k1_ge *lpt, secp256k1_ge *rpt) { 19 | unsigned char tmp[33]; 20 | secp256k1_ge_serialize_ext(tmp, lpt); 21 | output[0] = (tmp[0] & 1) << 1; 22 | memcpy(&output[1], &tmp[1], 32); 23 | secp256k1_ge_serialize_ext(tmp, rpt); 24 | output[0] |= (tmp[0] & 1); 25 | memcpy(&output[33], &tmp[1], 32); 26 | } 27 | 28 | static int secp256k1_bppp_parse_one_of_points(secp256k1_ge *pt, const unsigned char *in65, int idx) { 29 | unsigned char tmp[33] = { 0 }; 30 | if (in65[0] > 3) { 31 | return 0; 32 | } 33 | /* Check if the input array encodes the point at infinity */ 34 | if ((secp256k1_memcmp_var(tmp, &in65[1 + 32*idx], 32)) != 0) { 35 | tmp[0] = 2 | ((in65[0] & (2 - idx)) >> (1 - idx)); 36 | memcpy(&tmp[1], &in65[1 + 32*idx], 32); 37 | } else { 38 | /* If we're parsing the point at infinity, enforce that the sign bit is 39 | * 0. */ 40 | if ((in65[0] & (2 - idx)) != 0) { 41 | return 0; 42 | } 43 | } 44 | return secp256k1_ge_parse_ext(pt, tmp); 45 | } 46 | 47 | /* Outputs a serialized point in compressed form. Returns 0 at point at infinity. 48 | */ 49 | static int secp256k1_bppp_serialize_pt(unsigned char *output, secp256k1_ge *lpt) { 50 | size_t size; 51 | return secp256k1_eckey_pubkey_serialize(lpt, output, &size, 1 /*compressed*/); 52 | } 53 | 54 | /* little-endian encodes a uint64 */ 55 | static void secp256k1_bppp_le64(unsigned char *output, const uint64_t n) { 56 | output[0] = n; 57 | output[1] = n >> 8; 58 | output[2] = n >> 16; 59 | output[3] = n >> 24; 60 | output[4] = n >> 32; 61 | output[5] = n >> 40; 62 | output[6] = n >> 48; 63 | output[7] = n >> 56; 64 | } 65 | 66 | /* Check if n is power of two*/ 67 | static int secp256k1_is_power_of_two(size_t n) { 68 | return n > 0 && (n & (n - 1)) == 0; 69 | } 70 | 71 | /* Compute the log2 of n. n must NOT be 0. If n is not a power of two, it 72 | * returns the largest `k` such that 2^k <= n. Assumes 0 < n < 2^64. In 73 | * Bulletproofs, this is bounded by len of input vectors which can be safely 74 | * assumed to be less than 2^64. 75 | */ 76 | static size_t secp256k1_bppp_log2(size_t n) { 77 | return 64 - 1 - secp256k1_clz64_var((uint64_t)n); 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/modules/bppp/main.h: -------------------------------------------------------------------------------- 1 | #ifndef SECP256K1_MODULE_BPPP_MAIN_H 2 | #define SECP256K1_MODULE_BPPP_MAIN_H 3 | 4 | /* this type must be completed before any of the modules/bppp includes */ 5 | struct secp256k1_bppp_generators { 6 | size_t n; 7 | /* n total generators; includes both G_i and H_i */ 8 | /* For BP++, the generators are G_i from [0..(n - 8)] and the last 8 values 9 | are generators are for H_i */ 10 | secp256k1_ge* gens; 11 | }; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/modules/bppp/main_impl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2020 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_BPPP_MAIN_IMPL_H 8 | #define SECP256K1_MODULE_BPPP_MAIN_IMPL_H 9 | 10 | #include "../../../include/secp256k1_bppp.h" 11 | #include "../../../include/secp256k1_generator.h" 12 | #include "../generator/main_impl.h" /* for generator_{load, save} */ 13 | #include "../../hash.h" 14 | #include "../../util.h" 15 | #include "../bppp/main.h" 16 | #include "../bppp/bppp_norm_product_impl.h" 17 | 18 | secp256k1_bppp_generators *secp256k1_bppp_generators_create(const secp256k1_context *ctx, size_t n) { 19 | secp256k1_bppp_generators *ret; 20 | secp256k1_rfc6979_hmac_sha256 rng; 21 | unsigned char seed[64]; 22 | size_t i; 23 | 24 | VERIFY_CHECK(ctx != NULL); 25 | 26 | ret = (secp256k1_bppp_generators *)checked_malloc(&ctx->error_callback, sizeof(*ret)); 27 | if (ret == NULL) { 28 | return NULL; 29 | } 30 | ret->gens = (secp256k1_ge*)checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens)); 31 | if (ret->gens == NULL) { 32 | free(ret); 33 | return NULL; 34 | } 35 | ret->n = n; 36 | 37 | secp256k1_fe_get_b32(&seed[0], &secp256k1_ge_const_g.x); 38 | secp256k1_fe_get_b32(&seed[32], &secp256k1_ge_const_g.y); 39 | 40 | secp256k1_rfc6979_hmac_sha256_initialize(&rng, seed, 64); 41 | for (i = 0; i < n; i++) { 42 | secp256k1_generator gen; 43 | unsigned char tmp[32] = { 0 }; 44 | secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32); 45 | CHECK(secp256k1_generator_generate(ctx, &gen, tmp)); 46 | secp256k1_generator_load(&ret->gens[i], &gen); 47 | } 48 | 49 | return ret; 50 | } 51 | 52 | secp256k1_bppp_generators* secp256k1_bppp_generators_parse(const secp256k1_context* ctx, const unsigned char* data, size_t data_len) { 53 | size_t n = data_len / 33; 54 | secp256k1_bppp_generators* ret; 55 | 56 | VERIFY_CHECK(ctx != NULL); 57 | ARG_CHECK(data != NULL); 58 | 59 | if (data_len % 33 != 0) { 60 | return NULL; 61 | } 62 | 63 | ret = (secp256k1_bppp_generators *)checked_malloc(&ctx->error_callback, sizeof(*ret)); 64 | if (ret == NULL) { 65 | return NULL; 66 | } 67 | ret->n = n; 68 | ret->gens = (secp256k1_ge*)checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens)); 69 | if (ret->gens == NULL) { 70 | free(ret); 71 | return NULL; 72 | } 73 | 74 | while (n--) { 75 | secp256k1_generator gen; 76 | if (!secp256k1_generator_parse(ctx, &gen, &data[33 * n])) { 77 | free(ret->gens); 78 | free(ret); 79 | return NULL; 80 | } 81 | secp256k1_generator_load(&ret->gens[n], &gen); 82 | } 83 | return ret; 84 | } 85 | 86 | int secp256k1_bppp_generators_serialize(const secp256k1_context* ctx, const secp256k1_bppp_generators* gens, unsigned char* data, size_t *data_len) { 87 | size_t i; 88 | 89 | VERIFY_CHECK(ctx != NULL); 90 | ARG_CHECK(gens != NULL); 91 | ARG_CHECK(data != NULL); 92 | ARG_CHECK(data_len != NULL); 93 | ARG_CHECK(*data_len >= 33 * gens->n); 94 | 95 | memset(data, 0, *data_len); 96 | for (i = 0; i < gens->n; i++) { 97 | secp256k1_generator gen; 98 | secp256k1_generator_save(&gen, &gens->gens[i]); 99 | secp256k1_generator_serialize(ctx, &data[33 * i], &gen); 100 | } 101 | 102 | *data_len = 33 * gens->n; 103 | return 1; 104 | } 105 | 106 | void secp256k1_bppp_generators_destroy(const secp256k1_context* ctx, secp256k1_bppp_generators *gens) { 107 | VERIFY_CHECK(ctx != NULL); 108 | (void) ctx; 109 | if (gens != NULL) { 110 | free(gens->gens); 111 | free(gens); 112 | } 113 | } 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /src/modules/ecdh/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_ecdh.h 2 | noinst_HEADERS += src/modules/ecdh/main_impl.h 3 | noinst_HEADERS += src/modules/ecdh/tests_impl.h 4 | noinst_HEADERS += src/modules/ecdh/bench_impl.h 5 | -------------------------------------------------------------------------------- /src/modules/ecdh/bench_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_ECDH_BENCH_H 8 | #define SECP256K1_MODULE_ECDH_BENCH_H 9 | 10 | #include "../../../include/secp256k1_ecdh.h" 11 | 12 | typedef struct { 13 | secp256k1_context *ctx; 14 | secp256k1_pubkey point; 15 | unsigned char scalar[32]; 16 | } bench_ecdh_data; 17 | 18 | static void bench_ecdh_setup(void* arg) { 19 | int i; 20 | bench_ecdh_data *data = (bench_ecdh_data*)arg; 21 | const unsigned char point[] = { 22 | 0x03, 23 | 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, 24 | 0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, 25 | 0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, 26 | 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f 27 | }; 28 | 29 | for (i = 0; i < 32; i++) { 30 | data->scalar[i] = i + 1; 31 | } 32 | CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); 33 | } 34 | 35 | static void bench_ecdh(void* arg, int iters) { 36 | int i; 37 | unsigned char res[32]; 38 | bench_ecdh_data *data = (bench_ecdh_data*)arg; 39 | 40 | for (i = 0; i < iters; i++) { 41 | CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar, NULL, NULL) == 1); 42 | } 43 | } 44 | 45 | static void run_ecdh_bench(int iters, int argc, char** argv) { 46 | bench_ecdh_data data; 47 | int d = argc == 1; 48 | 49 | /* create a context with no capabilities */ 50 | data.ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); 51 | 52 | if (d || have_flag(argc, argv, "ecdh")) run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters); 53 | 54 | secp256k1_context_destroy(data.ctx); 55 | } 56 | 57 | #endif /* SECP256K1_MODULE_ECDH_BENCH_H */ 58 | -------------------------------------------------------------------------------- /src/modules/ecdh/main_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_ECDH_MAIN_H 8 | #define SECP256K1_MODULE_ECDH_MAIN_H 9 | 10 | #include "../../../include/secp256k1_ecdh.h" 11 | #include "../../ecmult_const_impl.h" 12 | 13 | static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { 14 | unsigned char version = (y32[31] & 0x01) | 0x02; 15 | secp256k1_sha256 sha; 16 | (void)data; 17 | 18 | secp256k1_sha256_initialize(&sha); 19 | secp256k1_sha256_write(&sha, &version, 1); 20 | secp256k1_sha256_write(&sha, x32, 32); 21 | secp256k1_sha256_finalize(&sha, output); 22 | 23 | return 1; 24 | } 25 | 26 | const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256 = ecdh_hash_function_sha256; 27 | const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default = ecdh_hash_function_sha256; 28 | 29 | int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pubkey *point, const unsigned char *scalar, secp256k1_ecdh_hash_function hashfp, void *data) { 30 | int ret = 0; 31 | int overflow = 0; 32 | secp256k1_gej res; 33 | secp256k1_ge pt; 34 | secp256k1_scalar s; 35 | unsigned char x[32]; 36 | unsigned char y[32]; 37 | 38 | VERIFY_CHECK(ctx != NULL); 39 | ARG_CHECK(output != NULL); 40 | ARG_CHECK(point != NULL); 41 | ARG_CHECK(scalar != NULL); 42 | 43 | if (hashfp == NULL) { 44 | hashfp = secp256k1_ecdh_hash_function_default; 45 | } 46 | 47 | secp256k1_pubkey_load(ctx, &pt, point); 48 | secp256k1_scalar_set_b32(&s, scalar, &overflow); 49 | 50 | overflow |= secp256k1_scalar_is_zero(&s); 51 | secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow); 52 | 53 | secp256k1_ecmult_const(&res, &pt, &s); 54 | secp256k1_ge_set_gej(&pt, &res); 55 | 56 | /* Compute a hash of the point */ 57 | secp256k1_fe_normalize(&pt.x); 58 | secp256k1_fe_normalize(&pt.y); 59 | secp256k1_fe_get_b32(x, &pt.x); 60 | secp256k1_fe_get_b32(y, &pt.y); 61 | 62 | ret = hashfp(output, x, y, data); 63 | 64 | memset(x, 0, 32); 65 | memset(y, 0, 32); 66 | secp256k1_scalar_clear(&s); 67 | 68 | return !!ret & !overflow; 69 | } 70 | 71 | #endif /* SECP256K1_MODULE_ECDH_MAIN_H */ 72 | -------------------------------------------------------------------------------- /src/modules/ecdsa_adaptor/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_ecdsa_adaptor.h 2 | noinst_HEADERS += src/modules/ecdsa_adaptor/main_impl.h 3 | noinst_HEADERS += src/modules/ecdsa_adaptor/dleq_impl.h 4 | noinst_HEADERS += src/modules/ecdsa_adaptor/tests_impl.h 5 | -------------------------------------------------------------------------------- /src/modules/ecdsa_s2c/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_ecdsa_s2c.h 2 | noinst_HEADERS += src/modules/ecdsa_s2c/main_impl.h 3 | noinst_HEADERS += src/modules/ecdsa_s2c/tests_impl.h 4 | -------------------------------------------------------------------------------- /src/modules/ellswift/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_ellswift.h 2 | noinst_HEADERS += src/modules/ellswift/bench_impl.h 3 | noinst_HEADERS += src/modules/ellswift/main_impl.h 4 | noinst_HEADERS += src/modules/ellswift/tests_impl.h 5 | noinst_HEADERS += src/modules/ellswift/tests_exhaustive_impl.h 6 | -------------------------------------------------------------------------------- /src/modules/ellswift/bench_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 4 | ***********************************************************************/ 5 | 6 | #ifndef SECP256K1_MODULE_ELLSWIFT_BENCH_H 7 | #define SECP256K1_MODULE_ELLSWIFT_BENCH_H 8 | 9 | #include "../../../include/secp256k1_ellswift.h" 10 | 11 | typedef struct { 12 | secp256k1_context *ctx; 13 | secp256k1_pubkey point[256]; 14 | unsigned char rnd64[64]; 15 | } bench_ellswift_data; 16 | 17 | static void bench_ellswift_setup(void *arg) { 18 | int i; 19 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 20 | static const unsigned char init[64] = { 21 | 0x78, 0x1f, 0xb7, 0xd4, 0x67, 0x7f, 0x08, 0x68, 22 | 0xdb, 0xe3, 0x1d, 0x7f, 0x1b, 0xb0, 0xf6, 0x9e, 23 | 0x0a, 0x64, 0xca, 0x32, 0x9e, 0xc6, 0x20, 0x79, 24 | 0x03, 0xf3, 0xd0, 0x46, 0x7a, 0x0f, 0xd2, 0x21, 25 | 0xb0, 0x2c, 0x46, 0xd8, 0xba, 0xca, 0x26, 0x4f, 26 | 0x8f, 0x8c, 0xd4, 0xdd, 0x2d, 0x04, 0xbe, 0x30, 27 | 0x48, 0x51, 0x1e, 0xd4, 0x16, 0xfd, 0x42, 0x85, 28 | 0x62, 0xc9, 0x02, 0xf9, 0x89, 0x84, 0xff, 0xdc 29 | }; 30 | memcpy(data->rnd64, init, 64); 31 | for (i = 0; i < 256; ++i) { 32 | int j; 33 | CHECK(secp256k1_ellswift_decode(data->ctx, &data->point[i], data->rnd64)); 34 | for (j = 0; j < 64; ++j) { 35 | data->rnd64[j] += 1; 36 | } 37 | } 38 | CHECK(secp256k1_ellswift_encode(data->ctx, data->rnd64, &data->point[255], init + 16)); 39 | } 40 | 41 | static void bench_ellswift_encode(void *arg, int iters) { 42 | int i; 43 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 44 | 45 | for (i = 0; i < iters; i++) { 46 | CHECK(secp256k1_ellswift_encode(data->ctx, data->rnd64, &data->point[i & 255], data->rnd64 + 16)); 47 | } 48 | } 49 | 50 | static void bench_ellswift_create(void *arg, int iters) { 51 | int i; 52 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 53 | 54 | for (i = 0; i < iters; i++) { 55 | unsigned char buf[64]; 56 | CHECK(secp256k1_ellswift_create(data->ctx, buf, data->rnd64, data->rnd64 + 32)); 57 | memcpy(data->rnd64, buf, 64); 58 | } 59 | } 60 | 61 | static void bench_ellswift_decode(void *arg, int iters) { 62 | int i; 63 | secp256k1_pubkey out; 64 | size_t len; 65 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 66 | 67 | for (i = 0; i < iters; i++) { 68 | CHECK(secp256k1_ellswift_decode(data->ctx, &out, data->rnd64) == 1); 69 | len = 33; 70 | CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->rnd64 + (i % 32), &len, &out, SECP256K1_EC_COMPRESSED)); 71 | } 72 | } 73 | 74 | static void bench_ellswift_xdh(void *arg, int iters) { 75 | int i; 76 | bench_ellswift_data *data = (bench_ellswift_data*)arg; 77 | 78 | for (i = 0; i < iters; i++) { 79 | int party = i & 1; 80 | CHECK(secp256k1_ellswift_xdh(data->ctx, 81 | data->rnd64 + (i % 33), 82 | data->rnd64, 83 | data->rnd64, 84 | data->rnd64 + ((i + 16) % 33), 85 | party, 86 | secp256k1_ellswift_xdh_hash_function_bip324, 87 | NULL) == 1); 88 | } 89 | } 90 | 91 | void run_ellswift_bench(int iters, int argc, char **argv) { 92 | bench_ellswift_data data; 93 | int d = argc == 1; 94 | 95 | /* create a context with signing capabilities */ 96 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 97 | 98 | if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "encode") || have_flag(argc, argv, "ellswift_encode")) run_benchmark("ellswift_encode", bench_ellswift_encode, bench_ellswift_setup, NULL, &data, 10, iters); 99 | if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_decode")) run_benchmark("ellswift_decode", bench_ellswift_decode, bench_ellswift_setup, NULL, &data, 10, iters); 100 | if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "keygen") || have_flag(argc, argv, "ellswift_keygen")) run_benchmark("ellswift_keygen", bench_ellswift_create, bench_ellswift_setup, NULL, &data, 10, iters); 101 | if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ecdh") || have_flag(argc, argv, "ellswift_ecdh")) run_benchmark("ellswift_ecdh", bench_ellswift_xdh, bench_ellswift_setup, NULL, &data, 10, iters); 102 | 103 | secp256k1_context_destroy(data.ctx); 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /src/modules/ellswift/tests_exhaustive_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 4 | ***********************************************************************/ 5 | 6 | #ifndef SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H 7 | #define SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H 8 | 9 | #include "../../../include/secp256k1_ellswift.h" 10 | #include "main_impl.h" 11 | 12 | static void test_exhaustive_ellswift(const secp256k1_context *ctx, const secp256k1_ge *group) { 13 | int i; 14 | 15 | /* Note that SwiftEC/ElligatorSwift are inherently curve operations, not 16 | * group operations, and this test only checks the curve points which are in 17 | * a tiny subgroup. In that sense it can't be really seen as exhaustive as 18 | * it doesn't (and for computational reasons obviously cannot) test the 19 | * entire domain ellswift operates under. */ 20 | for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { 21 | secp256k1_scalar scalar_i; 22 | unsigned char sec32[32]; 23 | unsigned char ell64[64]; 24 | secp256k1_pubkey pub_decoded; 25 | secp256k1_ge ge_decoded; 26 | 27 | /* Construct ellswift pubkey from exhaustive loop scalar i. */ 28 | secp256k1_scalar_set_int(&scalar_i, i); 29 | secp256k1_scalar_get_b32(sec32, &scalar_i); 30 | CHECK(secp256k1_ellswift_create(ctx, ell64, sec32, NULL)); 31 | 32 | /* Decode ellswift pubkey and check that it matches the precomputed group element. */ 33 | secp256k1_ellswift_decode(ctx, &pub_decoded, ell64); 34 | secp256k1_pubkey_load(ctx, &ge_decoded, &pub_decoded); 35 | CHECK(secp256k1_ge_eq_var(&ge_decoded, &group[i])); 36 | } 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/modules/extrakeys/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_extrakeys.h 2 | noinst_HEADERS += src/modules/extrakeys/tests_impl.h 3 | noinst_HEADERS += src/modules/extrakeys/tests_exhaustive_impl.h 4 | noinst_HEADERS += src/modules/extrakeys/main_impl.h 5 | noinst_HEADERS += src/modules/extrakeys/hsort.h 6 | noinst_HEADERS += src/modules/extrakeys/hsort_impl.h 7 | -------------------------------------------------------------------------------- /src/modules/extrakeys/hsort.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2021 Russell O'Connor, Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_HSORT_H 8 | #define SECP256K1_HSORT_H 9 | 10 | #include 11 | #include 12 | 13 | /* In-place, iterative heapsort with an interface matching glibc's qsort_r. This 14 | * is preferred over standard library implementations because they generally 15 | * make no guarantee about being fast for malicious inputs. 16 | * 17 | * See the qsort_r manpage for a description of the interface. 18 | */ 19 | static void secp256k1_hsort(void *ptr, size_t count, size_t size, 20 | int (*cmp)(const void *, const void *, void *), 21 | void *cmp_data); 22 | #endif 23 | -------------------------------------------------------------------------------- /src/modules/extrakeys/hsort_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2021 Russell O'Connor, Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_HSORT_IMPL_H 8 | #define SECP256K1_HSORT_IMPL_H 9 | 10 | #include "hsort.h" 11 | 12 | /* An array is a heap when, for all non-zero indexes i, the element at index i 13 | * compares as less than or equal to the element at index parent(i) = (i-1)/2. 14 | */ 15 | 16 | static SECP256K1_INLINE size_t child1(size_t i) { 17 | VERIFY_CHECK(i <= (SIZE_MAX - 1)/2); 18 | return 2*i + 1; 19 | } 20 | 21 | static SECP256K1_INLINE size_t child2(size_t i) { 22 | VERIFY_CHECK(i <= SIZE_MAX/2 - 1); 23 | return child1(i)+1; 24 | } 25 | 26 | static SECP256K1_INLINE void heap_swap64(unsigned char *a, size_t i, size_t j, size_t stride) { 27 | unsigned char tmp[64]; 28 | VERIFY_CHECK(stride <= 64); 29 | memcpy(tmp, a + i*stride, stride); 30 | memmove(a + i*stride, a + j*stride, stride); 31 | memcpy(a + j*stride, tmp, stride); 32 | } 33 | 34 | static SECP256K1_INLINE void heap_swap(unsigned char *a, size_t i, size_t j, size_t stride) { 35 | while (64 < stride) { 36 | heap_swap64(a + (stride - 64), i, j, 64); 37 | stride -= 64; 38 | } 39 | heap_swap64(a, i, j, stride); 40 | } 41 | 42 | static SECP256K1_INLINE void heap_down(unsigned char *a, size_t i, size_t heap_size, size_t stride, 43 | int (*cmp)(const void *, const void *, void *), void *cmp_data) { 44 | while (i < heap_size/2) { 45 | VERIFY_CHECK(i <= SIZE_MAX/2 - 1); 46 | /* Proof: 47 | * i < heap_size/2 48 | * i + 1 <= heap_size/2 49 | * 2*i + 2 <= heap_size <= SIZE_MAX 50 | * 2*i <= SIZE_MAX - 2 51 | */ 52 | 53 | VERIFY_CHECK(child1(i) < heap_size); 54 | /* Proof: 55 | * i < heap_size/2 56 | * i + 1 <= heap_size/2 57 | * 2*i + 2 <= heap_size 58 | * 2*i + 1 < heap_size 59 | * child1(i) < heap_size 60 | */ 61 | 62 | /* Let [x] be notation for the contents at a[x*stride]. 63 | * 64 | * If [child1(i)] > [i] and [child2(i)] > [i], 65 | * swap [i] with the larger child to ensure the new parent is larger 66 | * than both children. When [child1(i)] == [child2(i)], swap [i] with 67 | * [child2(i)]. 68 | * Else if [child1(i)] > [i], swap [i] with [child1(i)]. 69 | * Else if [child2(i)] > [i], swap [i] with [child2(i)]. 70 | */ 71 | if (child2(i) < heap_size 72 | && 0 <= cmp(a + child2(i)*stride, a + child1(i)*stride, cmp_data)) { 73 | if (0 < cmp(a + child2(i)*stride, a + i*stride, cmp_data)) { 74 | heap_swap(a, i, child2(i), stride); 75 | i = child2(i); 76 | } else { 77 | /* At this point we have [child2(i)] >= [child1(i)] and we have 78 | * [child2(i)] <= [i], and thus [child1(i)] <= [i] which means 79 | * that the next comparison can be skipped. */ 80 | return; 81 | } 82 | } else if (0 < cmp(a + child1(i)*stride, a + i*stride, cmp_data)) { 83 | heap_swap(a, i, child1(i), stride); 84 | i = child1(i); 85 | } else { 86 | return; 87 | } 88 | } 89 | /* heap_size/2 <= i 90 | * heap_size/2 < i + 1 91 | * heap_size < 2*i + 2 92 | * heap_size <= 2*i + 1 93 | * heap_size <= child1(i) 94 | * Thus child1(i) and child2(i) are now out of bounds and we are at a leaf. 95 | */ 96 | } 97 | 98 | /* In-place heap sort. */ 99 | static void secp256k1_hsort(void *ptr, size_t count, size_t size, 100 | int (*cmp)(const void *, const void *, void *), 101 | void *cmp_data ) { 102 | size_t i; 103 | 104 | for(i = count/2; 0 < i; --i) { 105 | heap_down(ptr, i-1, count, size, cmp, cmp_data); 106 | } 107 | for(i = count; 1 < i; --i) { 108 | /* Extract the largest value from the heap */ 109 | heap_swap(ptr, 0, i-1, size); 110 | 111 | /* Repair the heap condition */ 112 | heap_down(ptr, 0, i-1, size, cmp, cmp_data); 113 | } 114 | } 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /src/modules/extrakeys/tests_exhaustive_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H 8 | #define SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H 9 | 10 | #include "../../../include/secp256k1_extrakeys.h" 11 | #include "main_impl.h" 12 | 13 | static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp256k1_ge* group) { 14 | secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; 15 | secp256k1_pubkey pubkey[EXHAUSTIVE_TEST_ORDER - 1]; 16 | secp256k1_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; 17 | int parities[EXHAUSTIVE_TEST_ORDER - 1]; 18 | unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; 19 | int i; 20 | 21 | for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { 22 | secp256k1_fe fe; 23 | secp256k1_scalar scalar_i; 24 | unsigned char buf[33]; 25 | int parity; 26 | 27 | secp256k1_scalar_set_int(&scalar_i, i); 28 | secp256k1_scalar_get_b32(buf, &scalar_i); 29 | 30 | /* Construct pubkey and keypair. */ 31 | CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf)); 32 | CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey[i - 1], buf)); 33 | 34 | /* Construct serialized xonly_pubkey from keypair. */ 35 | CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parities[i - 1], &keypair[i - 1])); 36 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); 37 | 38 | /* Parse the xonly_pubkey back and verify it matches the previously serialized value. */ 39 | CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1])); 40 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); 41 | CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); 42 | 43 | /* Construct the xonly_pubkey from the pubkey, and verify it matches the same. */ 44 | CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1])); 45 | CHECK(parity == parities[i - 1]); 46 | CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); 47 | CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); 48 | 49 | /* Compare the xonly_pubkey bytes against the precomputed group. */ 50 | secp256k1_fe_set_b32_mod(&fe, xonly_pubkey_bytes[i - 1]); 51 | CHECK(secp256k1_fe_equal(&fe, &group[i].x)); 52 | 53 | /* Check the parity against the precomputed group. */ 54 | fe = group[i].y; 55 | secp256k1_fe_normalize_var(&fe); 56 | CHECK(secp256k1_fe_is_odd(&fe) == parities[i - 1]); 57 | 58 | /* Verify that the higher half is identical to the lower half mirrored. */ 59 | if (i > EXHAUSTIVE_TEST_ORDER / 2) { 60 | CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0); 61 | CHECK(parities[i - 1] == 1 - parities[EXHAUSTIVE_TEST_ORDER - i - 1]); 62 | } 63 | } 64 | 65 | /* TODO: keypair/xonly_pubkey tweak tests */ 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/modules/generator/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_generator.h 2 | noinst_HEADERS += src/modules/generator/pedersen.h 3 | noinst_HEADERS += src/modules/generator/pedersen_impl.h 4 | noinst_HEADERS += src/modules/generator/main_impl.h 5 | noinst_HEADERS += src/modules/generator/tests_impl.h 6 | if USE_BENCHMARK 7 | noinst_PROGRAMS += bench_generator 8 | bench_generator_SOURCES = src/bench_generator.c 9 | bench_generator_LDADD = libsecp256k1.la 10 | bench_generator_CPPFLAGS = $(SECP_CONFIG_DEFINES) 11 | endif 12 | -------------------------------------------------------------------------------- /src/modules/generator/pedersen.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2014, 2015 Gregory Maxwell * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_PEDERSEN_H 8 | #define SECP256K1_PEDERSEN_H 9 | 10 | #include "../../ecmult_gen.h" 11 | #include "../../group.h" 12 | #include "../../scalar.h" 13 | 14 | #include 15 | 16 | /** Multiply a small number with the generator: r = gn*G2 */ 17 | static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn, const secp256k1_ge* genp); 18 | 19 | /* sec * G + value * G2. */ 20 | static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value, const secp256k1_ge* genp); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/modules/generator/pedersen_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015 Gregory Maxwell * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php. * 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_PEDERSEN_IMPL_H 8 | #define SECP256K1_PEDERSEN_IMPL_H 9 | 10 | #include 11 | 12 | #include "../../eckey.h" 13 | #include "../../ecmult_const.h" 14 | #include "../../ecmult_gen.h" 15 | #include "../../group.h" 16 | #include "../../field.h" 17 | #include "../../scalar.h" 18 | #include "../../util.h" 19 | 20 | static void secp256k1_pedersen_scalar_set_u64(secp256k1_scalar *sec, uint64_t value) { 21 | unsigned char data[32]; 22 | int i; 23 | for (i = 0; i < 24; i++) { 24 | data[i] = 0; 25 | } 26 | for (; i < 32; i++) { 27 | data[i] = value >> 56; 28 | value <<= 8; 29 | } 30 | secp256k1_scalar_set_b32(sec, data, NULL); 31 | memset(data, 0, 32); 32 | } 33 | 34 | static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn, const secp256k1_ge* genp) { 35 | secp256k1_scalar s; 36 | secp256k1_pedersen_scalar_set_u64(&s, gn); 37 | secp256k1_ecmult_const(r, genp, &s); 38 | secp256k1_scalar_clear(&s); 39 | } 40 | 41 | /* sec * G + value * G2. */ 42 | SECP256K1_INLINE static void secp256k1_pedersen_ecmult(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_gej *rj, const secp256k1_scalar *sec, uint64_t value, const secp256k1_ge* genp) { 43 | secp256k1_gej vj; 44 | secp256k1_ecmult_gen(ecmult_gen_ctx, rj, sec); 45 | secp256k1_pedersen_ecmult_small(&vj, value, genp); 46 | /* FIXME: constant time. */ 47 | secp256k1_gej_add_var(rj, rj, &vj, NULL); 48 | secp256k1_gej_clear(&vj); 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/modules/musig/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_musig.h 2 | noinst_HEADERS += src/modules/musig/main_impl.h 3 | noinst_HEADERS += src/modules/musig/keyagg.h 4 | noinst_HEADERS += src/modules/musig/keyagg_impl.h 5 | noinst_HEADERS += src/modules/musig/session.h 6 | noinst_HEADERS += src/modules/musig/session_impl.h 7 | noinst_HEADERS += src/modules/musig/adaptor_impl.h 8 | noinst_HEADERS += src/modules/musig/tests_impl.h 9 | -------------------------------------------------------------------------------- /src/modules/musig/adaptor_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2021 Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H 8 | #define SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H 9 | 10 | #include 11 | 12 | #include "../../../include/secp256k1.h" 13 | #include "../../../include/secp256k1_musig.h" 14 | 15 | #include "session.h" 16 | #include "../../scalar.h" 17 | 18 | int secp256k1_musig_nonce_parity(const secp256k1_context* ctx, int *nonce_parity, const secp256k1_musig_session *session) { 19 | secp256k1_musig_session_internal session_i; 20 | VERIFY_CHECK(ctx != NULL); 21 | ARG_CHECK(nonce_parity != NULL); 22 | ARG_CHECK(session != NULL); 23 | 24 | if (!secp256k1_musig_session_load(ctx, &session_i, session)) { 25 | return 0; 26 | } 27 | *nonce_parity = session_i.fin_nonce_parity; 28 | return 1; 29 | } 30 | 31 | int secp256k1_musig_adapt(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *pre_sig64, const unsigned char *sec_adaptor32, int nonce_parity) { 32 | secp256k1_scalar s; 33 | secp256k1_scalar t; 34 | int overflow; 35 | int ret = 1; 36 | 37 | VERIFY_CHECK(ctx != NULL); 38 | ARG_CHECK(sig64 != NULL); 39 | ARG_CHECK(pre_sig64 != NULL); 40 | ARG_CHECK(sec_adaptor32 != NULL); 41 | ARG_CHECK(nonce_parity == 0 || nonce_parity == 1); 42 | 43 | secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow); 44 | if (overflow) { 45 | return 0; 46 | } 47 | secp256k1_scalar_set_b32(&t, sec_adaptor32, &overflow); 48 | ret &= !overflow; 49 | 50 | /* Determine if the secret adaptor should be negated. 51 | * 52 | * The musig_session stores the X-coordinate and the parity of the "final nonce" 53 | * (r + t)*G, where r*G is the aggregate public nonce and t is the secret adaptor. 54 | * 55 | * Since a BIP340 signature requires an x-only public nonce, in the case where 56 | * (r + t)*G has odd Y-coordinate (i.e. nonce_parity == 1), the x-only public nonce 57 | * corresponding to the signature is actually (-r - t)*G. Thus adapting a 58 | * pre-signature requires negating t in this case. 59 | */ 60 | if (nonce_parity) { 61 | secp256k1_scalar_negate(&t, &t); 62 | } 63 | 64 | secp256k1_scalar_add(&s, &s, &t); 65 | secp256k1_scalar_get_b32(&sig64[32], &s); 66 | memmove(sig64, pre_sig64, 32); 67 | secp256k1_scalar_clear(&t); 68 | return ret; 69 | } 70 | 71 | int secp256k1_musig_extract_adaptor(const secp256k1_context* ctx, unsigned char *sec_adaptor32, const unsigned char *sig64, const unsigned char *pre_sig64, int nonce_parity) { 72 | secp256k1_scalar t; 73 | secp256k1_scalar s; 74 | int overflow; 75 | int ret = 1; 76 | 77 | VERIFY_CHECK(ctx != NULL); 78 | ARG_CHECK(sec_adaptor32 != NULL); 79 | ARG_CHECK(sig64 != NULL); 80 | ARG_CHECK(pre_sig64 != NULL); 81 | ARG_CHECK(nonce_parity == 0 || nonce_parity == 1); 82 | 83 | secp256k1_scalar_set_b32(&t, &sig64[32], &overflow); 84 | ret &= !overflow; 85 | secp256k1_scalar_negate(&t, &t); 86 | 87 | secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow); 88 | if (overflow) { 89 | return 0; 90 | } 91 | secp256k1_scalar_add(&t, &t, &s); 92 | 93 | if (!nonce_parity) { 94 | secp256k1_scalar_negate(&t, &t); 95 | } 96 | secp256k1_scalar_get_b32(sec_adaptor32, &t); 97 | secp256k1_scalar_clear(&t); 98 | return ret; 99 | } 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/modules/musig/keyagg.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2021 Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_MUSIG_KEYAGG_H 8 | #define SECP256K1_MODULE_MUSIG_KEYAGG_H 9 | 10 | #include "../../../include/secp256k1.h" 11 | #include "../../../include/secp256k1_musig.h" 12 | 13 | #include "../../field.h" 14 | #include "../../group.h" 15 | #include "../../scalar.h" 16 | 17 | typedef struct { 18 | secp256k1_ge pk; 19 | /* If there is no "second" public key, second_pk is set to the point at 20 | * infinity */ 21 | secp256k1_ge second_pk; 22 | unsigned char pk_hash[32]; 23 | /* tweak is identical to value tacc[v] in the specification. */ 24 | secp256k1_scalar tweak; 25 | /* parity_acc corresponds to gacc[v] in the spec. If gacc[v] is -1, 26 | * parity_acc is 1. Otherwise, parity_acc is 0. */ 27 | int parity_acc; 28 | } secp256k1_keyagg_cache_internal; 29 | 30 | /* point_save_ext and point_load_ext are identical to point_save and point_load 31 | * except that they allow saving and loading the point at infinity */ 32 | static void secp256k1_point_save_ext(unsigned char *data, secp256k1_ge *ge); 33 | 34 | static void secp256k1_point_load_ext(secp256k1_ge *ge, const unsigned char *data); 35 | 36 | static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache); 37 | 38 | static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/modules/musig/main_impl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Andrew Poelstra, Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_MUSIG_MAIN_H 8 | #define SECP256K1_MODULE_MUSIG_MAIN_H 9 | 10 | #include "keyagg_impl.h" 11 | #include "session_impl.h" 12 | #include "adaptor_impl.h" 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/modules/musig/musig.md: -------------------------------------------------------------------------------- 1 | Notes on the musig module API 2 | =========================== 3 | 4 | The following sections contain additional notes on the API of the musig module (`include/secp256k1_musig.h`). 5 | A usage example can be found in `examples/musig.c`. 6 | 7 | # API misuse 8 | 9 | The musig API is designed to be as misuse resistant as possible. 10 | However, the MuSig protocol has some additional failure modes (mainly due to interactivity) that do not appear in single-signing. 11 | While the results can be catastrophic (e.g. leaking of the secret key), it is unfortunately not possible for the musig implementation to rule out all such failure modes. 12 | 13 | Therefore, users of the musig module must take great care to make sure of the following: 14 | 15 | 1. A unique nonce per signing session is generated in `secp256k1_musig_nonce_gen`. 16 | See the corresponding comment in `include/secp256k1_musig.h` for how to ensure that. 17 | 2. The `secp256k1_musig_secnonce` structure is never copied or serialized. 18 | See also the comment on `secp256k1_musig_secnonce` in `include/secp256k1_musig.h`. 19 | 3. Opaque data structures are never written to or read from directly. 20 | Instead, only the provided accessor functions are used. 21 | 4. If adaptor signatures are used, all partial signatures are verified. 22 | 23 | # Key Aggregation and (Taproot) Tweaking 24 | 25 | Given a set of public keys, the aggregate public key is computed with `secp256k1_musig_pubkey_agg`. 26 | A (Taproot) tweak can be added to the resulting public key with `secp256k1_xonly_pubkey_tweak_add` and a plain tweak can be added with `secp256k1_ec_pubkey_tweak_add`. 27 | 28 | # Signing 29 | 30 | This is covered by `examples/musig.c`. 31 | Essentially, the protocol proceeds in the following steps: 32 | 33 | 1. Generate a keypair with `secp256k1_keypair_create` and obtain the public key with `secp256k1_keypair_pub`. 34 | 2. Call `secp256k1_musig_pubkey_agg` with the pubkeys of all participants. 35 | 3. Optionally add a (Taproot) tweak with `secp256k1_musig_pubkey_xonly_tweak_add` and a plain tweak with `secp256k1_musig_pubkey_ec_tweak_add`. 36 | 4. Generate a pair of secret and public nonce with `secp256k1_musig_nonce_gen` and send the public nonce to the other signers. 37 | 5. Someone (not necessarily the signer) aggregates the public nonce with `secp256k1_musig_nonce_agg` and sends it to the signers. 38 | 6. Process the aggregate nonce with `secp256k1_musig_nonce_process`. 39 | 7. Create a partial signature with `secp256k1_musig_partial_sign`. 40 | 8. Verify the partial signatures (optional in some scenarios) with `secp256k1_musig_partial_sig_verify`. 41 | 9. Someone (not necessarily the signer) obtains all partial signatures and aggregates them into the final Schnorr signature using `secp256k1_musig_partial_sig_agg`. 42 | 43 | The aggregate signature can be verified with `secp256k1_schnorrsig_verify`. 44 | 45 | Note that steps 1 to 5 can happen before the message to be signed is known to the signers. 46 | Therefore, the communication round to exchange nonces can be viewed as a pre-processing step that is run whenever convenient to the signers. 47 | This disables some of the defense-in-depth measures that may protect against API misuse in some cases. 48 | Similarly, the API supports an alternative protocol flow where generating the aggregate key (steps 1 to 3) is allowed to happen after exchanging nonces (steps 4 to 5). 49 | 50 | # Verification 51 | 52 | A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7. 53 | 54 | # Atomic Swaps 55 | 56 | The signing API supports the production of "adaptor signatures", modified partial signatures 57 | which are offset by an auxiliary secret known to one party. That is, 58 | 1. One party generates a (secret) adaptor `t` with corresponding (public) adaptor `T = t*G`. 59 | 2. When calling `secp256k1_musig_nonce_process`, the public adaptor `T` is provided as the `adaptor` argument. 60 | 3. The party who is going to extract the secret adaptor `t` later must verify all partial signatures. 61 | 4. Due to step 2, the signature output of `secp256k1_musig_partial_sig_agg` is a pre-signature and not a valid Schnorr signature. All parties involved extract this session's `nonce_parity` with `secp256k1_musig_nonce_parity`. 62 | 5. The party who knows `t` must "adapt" the pre-signature with `t` (and the `nonce_parity` using `secp256k1_musig_adapt` to complete the signature. 63 | 6. Any party who sees both the final signature and the pre-signature (and has the `nonce_parity`) can extract `t` with `secp256k1_musig_extract_adaptor`. 64 | -------------------------------------------------------------------------------- /src/modules/musig/session.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2021 Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_MUSIG_SESSION_H 8 | #define SECP256K1_MODULE_MUSIG_SESSION_H 9 | 10 | #include "../../../include/secp256k1.h" 11 | #include "../../../include/secp256k1_musig.h" 12 | 13 | #include "../../scalar.h" 14 | 15 | typedef struct { 16 | int fin_nonce_parity; 17 | unsigned char fin_nonce[32]; 18 | secp256k1_scalar noncecoef; 19 | secp256k1_scalar challenge; 20 | secp256k1_scalar s_part; 21 | } secp256k1_musig_session_internal; 22 | 23 | static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/modules/rangeproof/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_rangeproof.h 2 | noinst_HEADERS += src/modules/rangeproof/main_impl.h 3 | noinst_HEADERS += src/modules/rangeproof/borromean.h 4 | noinst_HEADERS += src/modules/rangeproof/borromean_impl.h 5 | noinst_HEADERS += src/modules/rangeproof/rangeproof.h 6 | noinst_HEADERS += src/modules/rangeproof/rangeproof_impl.h 7 | noinst_HEADERS += src/modules/rangeproof/tests_impl.h 8 | if USE_BENCHMARK 9 | noinst_PROGRAMS += bench_rangeproof 10 | bench_rangeproof_SOURCES = src/bench_rangeproof.c 11 | bench_rangeproof_LDADD = libsecp256k1.la 12 | bench_rangeproof_CPPFLAGS = $(SECP_CONFIG_DEFINES) 13 | endif 14 | -------------------------------------------------------------------------------- /src/modules/rangeproof/borromean.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2014, 2015 Gregory Maxwell * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | 8 | #ifndef SECP256K1_BORROMEAN_H 9 | #define SECP256K1_BORROMEAN_H 10 | 11 | #include "../../scalar.h" 12 | #include "../../field.h" 13 | #include "../../group.h" 14 | #include "../../ecmult.h" 15 | #include "../../ecmult_gen.h" 16 | 17 | static int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s, 18 | const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen); 19 | 20 | static int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, 21 | unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec, 22 | const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/modules/rangeproof/rangeproof.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2015 Gregory Maxwell * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_RANGEPROOF_H 8 | #define SECP256K1_RANGEPROOF_H 9 | 10 | #include "../../scalar.h" 11 | #include "../../group.h" 12 | #include "../../ecmult.h" 13 | #include "../../ecmult_gen.h" 14 | 15 | static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_gen_context* ecmult_gen_ctx, 16 | unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce, 17 | uint64_t *min_value, uint64_t *max_value, const secp256k1_ge *commit, const unsigned char *proof, size_t plen, 18 | const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/modules/recovery/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_recovery.h 2 | noinst_HEADERS += src/modules/recovery/main_impl.h 3 | noinst_HEADERS += src/modules/recovery/tests_impl.h 4 | noinst_HEADERS += src/modules/recovery/tests_exhaustive_impl.h 5 | noinst_HEADERS += src/modules/recovery/bench_impl.h 6 | -------------------------------------------------------------------------------- /src/modules/recovery/bench_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014-2015 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_RECOVERY_BENCH_H 8 | #define SECP256K1_MODULE_RECOVERY_BENCH_H 9 | 10 | #include "../../../include/secp256k1_recovery.h" 11 | 12 | typedef struct { 13 | secp256k1_context *ctx; 14 | unsigned char msg[32]; 15 | unsigned char sig[64]; 16 | } bench_recover_data; 17 | 18 | static void bench_recover(void* arg, int iters) { 19 | int i; 20 | bench_recover_data *data = (bench_recover_data*)arg; 21 | secp256k1_pubkey pubkey; 22 | unsigned char pubkeyc[33]; 23 | 24 | for (i = 0; i < iters; i++) { 25 | int j; 26 | size_t pubkeylen = 33; 27 | secp256k1_ecdsa_recoverable_signature sig; 28 | CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); 29 | CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); 30 | CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); 31 | for (j = 0; j < 32; j++) { 32 | data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ 33 | data->msg[j] = data->sig[j]; /* Move former R to message. */ 34 | data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ 35 | } 36 | } 37 | } 38 | 39 | static void bench_recover_setup(void* arg) { 40 | int i; 41 | bench_recover_data *data = (bench_recover_data*)arg; 42 | 43 | for (i = 0; i < 32; i++) { 44 | data->msg[i] = 1 + i; 45 | } 46 | for (i = 0; i < 64; i++) { 47 | data->sig[i] = 65 + i; 48 | } 49 | } 50 | 51 | static void run_recovery_bench(int iters, int argc, char** argv) { 52 | bench_recover_data data; 53 | int d = argc == 1; 54 | 55 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 56 | 57 | if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters); 58 | 59 | secp256k1_context_destroy(data.ctx); 60 | } 61 | 62 | #endif /* SECP256K1_MODULE_RECOVERY_BENCH_H */ 63 | -------------------------------------------------------------------------------- /src/modules/schnorrsig/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_schnorrsig.h 2 | noinst_HEADERS += src/modules/schnorrsig/main_impl.h 3 | noinst_HEADERS += src/modules/schnorrsig/tests_impl.h 4 | noinst_HEADERS += src/modules/schnorrsig/tests_exhaustive_impl.h 5 | noinst_HEADERS += src/modules/schnorrsig/bench_impl.h 6 | -------------------------------------------------------------------------------- /src/modules/schnorrsig/bench_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_MODULE_SCHNORRSIG_BENCH_H 8 | #define SECP256K1_MODULE_SCHNORRSIG_BENCH_H 9 | 10 | #include "../../../include/secp256k1_schnorrsig.h" 11 | 12 | #define MSGLEN 32 13 | 14 | typedef struct { 15 | secp256k1_context *ctx; 16 | int n; 17 | 18 | const secp256k1_keypair **keypairs; 19 | const unsigned char **pk; 20 | const unsigned char **sigs; 21 | const unsigned char **msgs; 22 | } bench_schnorrsig_data; 23 | 24 | static void bench_schnorrsig_sign(void* arg, int iters) { 25 | bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; 26 | int i; 27 | unsigned char msg[MSGLEN] = {0}; 28 | unsigned char sig[64]; 29 | 30 | for (i = 0; i < iters; i++) { 31 | msg[0] = i; 32 | msg[1] = i >> 8; 33 | CHECK(secp256k1_schnorrsig_sign_custom(data->ctx, sig, msg, MSGLEN, data->keypairs[i], NULL)); 34 | } 35 | } 36 | 37 | static void bench_schnorrsig_verify(void* arg, int iters) { 38 | bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; 39 | int i; 40 | 41 | for (i = 0; i < iters; i++) { 42 | secp256k1_xonly_pubkey pk; 43 | CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pk[i]) == 1); 44 | CHECK(secp256k1_schnorrsig_verify(data->ctx, data->sigs[i], data->msgs[i], MSGLEN, &pk)); 45 | } 46 | } 47 | 48 | static void run_schnorrsig_bench(int iters, int argc, char** argv) { 49 | int i; 50 | bench_schnorrsig_data data; 51 | int d = argc == 1; 52 | 53 | data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); 54 | data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *)); 55 | data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); 56 | data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); 57 | data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); 58 | 59 | CHECK(MSGLEN >= 4); 60 | for (i = 0; i < iters; i++) { 61 | unsigned char sk[32]; 62 | unsigned char *msg = (unsigned char *)malloc(MSGLEN); 63 | unsigned char *sig = (unsigned char *)malloc(64); 64 | secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair)); 65 | unsigned char *pk_char = (unsigned char *)malloc(32); 66 | secp256k1_xonly_pubkey pk; 67 | msg[0] = sk[0] = i; 68 | msg[1] = sk[1] = i >> 8; 69 | msg[2] = sk[2] = i >> 16; 70 | msg[3] = sk[3] = i >> 24; 71 | memset(&msg[4], 'm', MSGLEN - 4); 72 | memset(&sk[4], 's', 28); 73 | 74 | data.keypairs[i] = keypair; 75 | data.pk[i] = pk_char; 76 | data.msgs[i] = msg; 77 | data.sigs[i] = sig; 78 | 79 | CHECK(secp256k1_keypair_create(data.ctx, keypair, sk)); 80 | CHECK(secp256k1_schnorrsig_sign_custom(data.ctx, sig, msg, MSGLEN, keypair, NULL)); 81 | CHECK(secp256k1_keypair_xonly_pub(data.ctx, &pk, NULL, keypair)); 82 | CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1); 83 | } 84 | 85 | if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "schnorrsig_sign")) run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters); 86 | if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "schnorrsig_verify")) run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters); 87 | 88 | for (i = 0; i < iters; i++) { 89 | free((void *)data.keypairs[i]); 90 | free((void *)data.pk[i]); 91 | free((void *)data.msgs[i]); 92 | free((void *)data.sigs[i]); 93 | } 94 | 95 | /* Casting to (void *) avoids a stupid warning in MSVC. */ 96 | free((void *)data.keypairs); 97 | free((void *)data.pk); 98 | free((void *)data.msgs); 99 | free((void *)data.sigs); 100 | 101 | secp256k1_context_destroy(data.ctx); 102 | } 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /src/modules/schnorrsig_halfagg/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_schnorrsig_halfagg.h 2 | noinst_HEADERS += src/modules/schnorrsig_halfagg/main_impl.h 3 | noinst_HEADERS += src/modules/schnorrsig_halfagg/tests_impl.h 4 | -------------------------------------------------------------------------------- /src/modules/surjection/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_surjectionproof.h 2 | noinst_HEADERS += src/modules/surjection/main_impl.h 3 | noinst_HEADERS += src/modules/surjection/surjection.h 4 | noinst_HEADERS += src/modules/surjection/surjection_impl.h 5 | noinst_HEADERS += src/modules/surjection/tests_impl.h 6 | 7 | -------------------------------------------------------------------------------- /src/modules/surjection/surjection.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2016 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_SURJECTION_H 8 | #define SECP256K1_SURJECTION_H 9 | 10 | #include "../../group.h" 11 | #include "../../scalar.h" 12 | 13 | SECP256K1_INLINE static int secp256k1_surjection_genmessage(unsigned char *msg32, secp256k1_ge *ephemeral_input_tags, size_t n_input_tags, secp256k1_ge *ephemeral_output_tag); 14 | 15 | SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key); 16 | 17 | SECP256K1_INLINE static int secp256k1_surjection_compute_public_keys(secp256k1_gej *pubkeys, size_t n_pubkeys, const secp256k1_ge *input_tags, size_t n_input_tags, const unsigned char *used_tags, const secp256k1_ge *output_tag, size_t input_index, size_t *ring_input_index); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/modules/surjection/surjection_impl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2016 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef SECP256K1_SURJECTION_IMPL_H 8 | #define SECP256K1_SURJECTION_IMPL_H 9 | 10 | #include 11 | #include 12 | 13 | #include "../../eckey.h" 14 | #include "../../group.h" 15 | #include "../../scalar.h" 16 | #include "../../hash.h" 17 | 18 | SECP256K1_INLINE static void secp256k1_surjection_genmessage(unsigned char *msg32, const secp256k1_generator *ephemeral_input_tags, size_t n_input_tags, const secp256k1_generator *ephemeral_output_tag) { 19 | /* compute message */ 20 | size_t i; 21 | unsigned char pk_ser[33]; 22 | size_t pk_len = sizeof(pk_ser); 23 | secp256k1_sha256 sha256_en; 24 | 25 | secp256k1_sha256_initialize(&sha256_en); 26 | for (i = 0; i < n_input_tags; i++) { 27 | pk_ser[0] = 2 + (ephemeral_input_tags[i].data[63] & 1); 28 | memcpy(&pk_ser[1], &ephemeral_input_tags[i].data[0], 32); 29 | secp256k1_sha256_write(&sha256_en, pk_ser, pk_len); 30 | } 31 | pk_ser[0] = 2 + (ephemeral_output_tag->data[63] & 1); 32 | memcpy(&pk_ser[1], &ephemeral_output_tag->data[0], 32); 33 | secp256k1_sha256_write(&sha256_en, pk_ser, pk_len); 34 | secp256k1_sha256_finalize(&sha256_en, msg32); 35 | } 36 | 37 | SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key) { 38 | size_t i; 39 | unsigned char sec_input[36]; 40 | secp256k1_sha256 sha256_en; 41 | 42 | /* compute s values */ 43 | secp256k1_scalar_get_b32(&sec_input[4], blinding_key); 44 | for (i = 0; i < ns; i++) { 45 | int overflow = 0; 46 | sec_input[0] = i; 47 | sec_input[1] = i >> 8; 48 | sec_input[2] = i >> 16; 49 | sec_input[3] = i >> 24; 50 | 51 | secp256k1_sha256_initialize(&sha256_en); 52 | secp256k1_sha256_write(&sha256_en, sec_input, 36); 53 | secp256k1_sha256_finalize(&sha256_en, sec_input); 54 | secp256k1_scalar_set_b32(&s[i], sec_input, &overflow); 55 | if (overflow == 1) { 56 | memset(sec_input, 0, 32); 57 | return 0; 58 | } 59 | } 60 | memset(sec_input, 0, 32); 61 | return 1; 62 | } 63 | 64 | SECP256K1_INLINE static int secp256k1_surjection_compute_public_keys(secp256k1_gej *pubkeys, size_t n_pubkeys, const secp256k1_generator *input_tags, size_t n_input_tags, const unsigned char *used_tags, const secp256k1_generator *output_tag, size_t input_index, size_t *ring_input_index) { 65 | size_t i; 66 | size_t j = 0; 67 | for (i = 0; i < n_input_tags; i++) { 68 | if (used_tags[i / 8] & (1 << (i % 8))) { 69 | secp256k1_ge tmpge; 70 | secp256k1_generator_load(&tmpge, &input_tags[i]); 71 | secp256k1_ge_neg(&tmpge, &tmpge); 72 | 73 | VERIFY_CHECK(j < SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS); 74 | VERIFY_CHECK(j < n_pubkeys); 75 | secp256k1_gej_set_ge(&pubkeys[j], &tmpge); 76 | 77 | secp256k1_generator_load(&tmpge, output_tag); 78 | secp256k1_gej_add_ge_var(&pubkeys[j], &pubkeys[j], &tmpge, NULL); 79 | if (ring_input_index != NULL && input_index == i) { 80 | *ring_input_index = j; 81 | } 82 | j++; 83 | } 84 | } 85 | #ifdef VERIFY 86 | /* Caller needs to ensure that the number of set bits in used_tags (which we counted in j) equals n_pubkeys. */ 87 | VERIFY_CHECK(j == n_pubkeys); 88 | #else 89 | (void)n_pubkeys; 90 | #endif 91 | return 1; 92 | } 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /src/modules/whitelist/Makefile.am.include: -------------------------------------------------------------------------------- 1 | include_HEADERS += include/secp256k1_whitelist.h 2 | noinst_HEADERS += src/modules/whitelist/whitelist_impl.h 3 | noinst_HEADERS += src/modules/whitelist/main_impl.h 4 | noinst_HEADERS += src/modules/whitelist/tests_impl.h 5 | if USE_BENCHMARK 6 | noinst_PROGRAMS += bench_whitelist 7 | bench_whitelist_SOURCES = src/bench_whitelist.c 8 | bench_whitelist_LDADD = libsecp256k1.la 9 | bench_generator_CPPFLAGS = $(SECP_CONFIG_DEFINES) 10 | endif 11 | -------------------------------------------------------------------------------- /src/precompute_ecmult.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *****************************************************************************************************/ 6 | 7 | #include 8 | #include 9 | 10 | #include "../include/secp256k1.h" 11 | 12 | #include "assumptions.h" 13 | #include "util.h" 14 | 15 | #include "field_impl.h" 16 | #include "group_impl.h" 17 | #include "int128_impl.h" 18 | #include "ecmult.h" 19 | #include "ecmult_compute_table_impl.h" 20 | 21 | static void print_table(FILE *fp, const char *name, int window_g, const secp256k1_ge_storage* table) { 22 | int j; 23 | int i; 24 | 25 | fprintf(fp, "const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name); 26 | fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 27 | ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n", 28 | SECP256K1_GE_STORAGE_CONST_GET(table[0])); 29 | 30 | j = 1; 31 | for(i = 3; i <= window_g; ++i) { 32 | fprintf(fp, "#if WINDOW_G > %d\n", i-1); 33 | for(;j < ECMULT_TABLE_SIZE(i); ++j) { 34 | fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 35 | ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n", 36 | SECP256K1_GE_STORAGE_CONST_GET(table[j])); 37 | } 38 | fprintf(fp, "#endif\n"); 39 | } 40 | fprintf(fp, "};\n"); 41 | } 42 | 43 | static void print_two_tables(FILE *fp, int window_g) { 44 | secp256k1_ge_storage* table = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(secp256k1_ge_storage)); 45 | secp256k1_ge_storage* table_128 = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(secp256k1_ge_storage)); 46 | 47 | secp256k1_ecmult_compute_two_tables(table, table_128, window_g, &secp256k1_ge_const_g); 48 | 49 | print_table(fp, "secp256k1_pre_g", window_g, table); 50 | print_table(fp, "secp256k1_pre_g_128", window_g, table_128); 51 | 52 | free(table); 53 | free(table_128); 54 | } 55 | 56 | int main(void) { 57 | /* Always compute all tables for window sizes up to 15. */ 58 | int window_g = (ECMULT_WINDOW_SIZE < 15) ? 15 : ECMULT_WINDOW_SIZE; 59 | const char outfile[] = "src/precomputed_ecmult.c"; 60 | FILE* fp; 61 | 62 | fp = fopen(outfile, "w"); 63 | if (fp == NULL) { 64 | fprintf(stderr, "Could not open %s for writing!\n", outfile); 65 | return -1; 66 | } 67 | 68 | fprintf(fp, "/* This file was automatically generated by precompute_ecmult. */\n"); 69 | fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n"); 70 | fprintf(fp, " * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n"); 71 | fprintf(fp, " */\n"); 72 | fprintf(fp, "#include \"group.h\"\n"); 73 | fprintf(fp, "#include \"ecmult.h\"\n"); 74 | fprintf(fp, "#include \"precomputed_ecmult.h\"\n"); 75 | fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); 76 | fprintf(fp, "#if ECMULT_WINDOW_SIZE > %d\n", window_g); 77 | fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting precomputed_ecmult.c before the build.\n"); 78 | fprintf(fp, "#endif\n"); 79 | fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n"); 80 | fprintf(fp, "# error Cannot compile precomputed_ecmult.c in exhaustive test mode\n"); 81 | fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); 82 | fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n"); 83 | 84 | print_two_tables(fp, window_g); 85 | 86 | fprintf(fp, "#undef S\n"); 87 | fclose(fp); 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /src/precompute_ecmult_gen.c: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2013, 2014, 2015, 2021 Thomas Daede, Cory Fields, Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *********************************************************************************/ 6 | 7 | #include 8 | #include 9 | 10 | #include "../include/secp256k1.h" 11 | 12 | #include "assumptions.h" 13 | #include "util.h" 14 | 15 | #include "group.h" 16 | #include "int128_impl.h" 17 | #include "ecmult_gen.h" 18 | #include "ecmult_gen_compute_table_impl.h" 19 | 20 | int main(int argc, char **argv) { 21 | const char outfile[] = "src/precomputed_ecmult_gen.c"; 22 | FILE* fp; 23 | int bits; 24 | 25 | (void)argc; 26 | (void)argv; 27 | 28 | fp = fopen(outfile, "w"); 29 | if (fp == NULL) { 30 | fprintf(stderr, "Could not open %s for writing!\n", outfile); 31 | return -1; 32 | } 33 | 34 | fprintf(fp, "/* This file was automatically generated by precompute_ecmult_gen. */\n"); 35 | fprintf(fp, "/* See ecmult_gen_impl.h for details about the contents of this file. */\n"); 36 | fprintf(fp, "#include \"group.h\"\n"); 37 | fprintf(fp, "#include \"ecmult_gen.h\"\n"); 38 | fprintf(fp, "#include \"precomputed_ecmult_gen.h\"\n"); 39 | fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n"); 40 | fprintf(fp, "# error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode\n"); 41 | fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); 42 | fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); 43 | fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {\n"); 44 | 45 | for (bits = 2; bits <= 8; bits *= 2) { 46 | int g = ECMULT_GEN_PREC_G(bits); 47 | int n = ECMULT_GEN_PREC_N(bits); 48 | int inner, outer; 49 | 50 | secp256k1_ge_storage* table = checked_malloc(&default_error_callback, n * g * sizeof(secp256k1_ge_storage)); 51 | secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, bits); 52 | 53 | fprintf(fp, "#if ECMULT_GEN_PREC_BITS == %d\n", bits); 54 | for(outer = 0; outer != n; outer++) { 55 | fprintf(fp,"{"); 56 | for(inner = 0; inner != g; inner++) { 57 | fprintf(fp, "S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 58 | ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")", 59 | SECP256K1_GE_STORAGE_CONST_GET(table[outer * g + inner])); 60 | if (inner != g - 1) { 61 | fprintf(fp,",\n"); 62 | } 63 | } 64 | if (outer != n - 1) { 65 | fprintf(fp,"},\n"); 66 | } else { 67 | fprintf(fp,"}\n"); 68 | } 69 | } 70 | fprintf(fp, "#endif\n"); 71 | free(table); 72 | } 73 | 74 | fprintf(fp, "};\n"); 75 | fprintf(fp, "#undef S\n"); 76 | fclose(fp); 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /src/precomputed_ecmult.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************************** 2 | * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *****************************************************************************************************/ 6 | 7 | #ifndef SECP256K1_PRECOMPUTED_ECMULT_H 8 | #define SECP256K1_PRECOMPUTED_ECMULT_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include "ecmult.h" 15 | #include "group.h" 16 | #if defined(EXHAUSTIVE_TEST_ORDER) 17 | # if EXHAUSTIVE_TEST_ORDER == 7 18 | # define WINDOW_G 3 19 | # elif EXHAUSTIVE_TEST_ORDER == 13 20 | # define WINDOW_G 4 21 | # elif EXHAUSTIVE_TEST_ORDER == 199 22 | # define WINDOW_G 8 23 | # else 24 | # error No known generator for the specified exhaustive test group order. 25 | # endif 26 | static secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; 27 | static secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; 28 | #else /* !defined(EXHAUSTIVE_TEST_ORDER) */ 29 | # define WINDOW_G ECMULT_WINDOW_SIZE 30 | extern const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; 31 | extern const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; 32 | #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* SECP256K1_PRECOMPUTED_ECMULT_H */ 39 | -------------------------------------------------------------------------------- /src/precomputed_ecmult_gen.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright (c) 2013, 2014, 2015, 2021 Thomas Daede, Cory Fields, Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php. * 5 | *********************************************************************************/ 6 | 7 | #ifndef SECP256K1_PRECOMPUTED_ECMULT_GEN_H 8 | #define SECP256K1_PRECOMPUTED_ECMULT_GEN_H 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #include "group.h" 15 | #include "ecmult_gen.h" 16 | #ifdef EXHAUSTIVE_TEST_ORDER 17 | static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)]; 18 | #else 19 | extern const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)]; 20 | #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* SECP256K1_PRECOMPUTED_ECMULT_GEN_H */ 27 | -------------------------------------------------------------------------------- /src/scalar_4x64.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCALAR_REPR_H 8 | #define SECP256K1_SCALAR_REPR_H 9 | 10 | #include 11 | 12 | /** A scalar modulo the group order of the secp256k1 curve. */ 13 | typedef struct { 14 | uint64_t d[4]; 15 | } secp256k1_scalar; 16 | 17 | #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} 18 | 19 | #endif /* SECP256K1_SCALAR_REPR_H */ 20 | -------------------------------------------------------------------------------- /src/scalar_8x32.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCALAR_REPR_H 8 | #define SECP256K1_SCALAR_REPR_H 9 | 10 | #include 11 | 12 | /** A scalar modulo the group order of the secp256k1 curve. */ 13 | typedef struct { 14 | uint32_t d[8]; 15 | } secp256k1_scalar; 16 | 17 | #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} 18 | 19 | #endif /* SECP256K1_SCALAR_REPR_H */ 20 | -------------------------------------------------------------------------------- /src/scalar_low.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2015, 2022 Andrew Poelstra, Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCALAR_REPR_H 8 | #define SECP256K1_SCALAR_REPR_H 9 | 10 | #include 11 | 12 | /** A scalar modulo the group order of the secp256k1 curve. */ 13 | typedef uint32_t secp256k1_scalar; 14 | 15 | /* A compile-time constant equal to 2^32 (modulo order). */ 16 | #define SCALAR_2P32 ((0xffffffffUL % EXHAUSTIVE_TEST_ORDER) + 1U) 17 | 18 | /* Compute a*2^32 + b (modulo order). */ 19 | #define SCALAR_HORNER(a, b) (((uint64_t)(a) * SCALAR_2P32 + (b)) % EXHAUSTIVE_TEST_ORDER) 20 | 21 | /* Evaluates to the provided 256-bit constant reduced modulo order. */ 22 | #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER((d7), (d6)), (d5)), (d4)), (d3)), (d2)), (d1)), (d0)) 23 | 24 | #endif /* SECP256K1_SCALAR_REPR_H */ 25 | -------------------------------------------------------------------------------- /src/scratch.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2017 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCRATCH_H 8 | #define SECP256K1_SCRATCH_H 9 | 10 | /* The typedef is used internally; the struct name is used in the public API 11 | * (where it is exposed as a different typedef) */ 12 | typedef struct secp256k1_scratch_space_struct { 13 | /** guard against interpreting this object as other types */ 14 | unsigned char magic[8]; 15 | /** actual allocated data */ 16 | void *data; 17 | /** amount that has been allocated (i.e. `data + offset` is the next 18 | * available pointer) */ 19 | size_t alloc_size; 20 | /** maximum size available to allocate */ 21 | size_t max_size; 22 | } secp256k1_scratch; 23 | 24 | static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size); 25 | 26 | static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch); 27 | 28 | /** Returns an opaque object used to "checkpoint" a scratch space. Used 29 | * with `secp256k1_scratch_apply_checkpoint` to undo allocations. */ 30 | static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch); 31 | 32 | /** Applies a check point received from `secp256k1_scratch_checkpoint`, 33 | * undoing all allocations since that point. */ 34 | static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint); 35 | 36 | /** Returns the maximum allocation the scratch space will allow */ 37 | static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t n_objects); 38 | 39 | /** Returns a pointer into the most recently allocated frame, or NULL if there is insufficient available space */ 40 | static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t n); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/scratch_impl.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2017 Andrew Poelstra * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SCRATCH_IMPL_H 8 | #define SECP256K1_SCRATCH_IMPL_H 9 | 10 | #include "util.h" 11 | #include "scratch.h" 12 | 13 | static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) { 14 | const size_t base_alloc = ROUND_TO_ALIGN(sizeof(secp256k1_scratch)); 15 | void *alloc = checked_malloc(error_callback, base_alloc + size); 16 | secp256k1_scratch* ret = (secp256k1_scratch *)alloc; 17 | if (ret != NULL) { 18 | memset(ret, 0, sizeof(*ret)); 19 | memcpy(ret->magic, "scratch", 8); 20 | ret->data = (void *) ((char *) alloc + base_alloc); 21 | ret->max_size = size; 22 | } 23 | return ret; 24 | } 25 | 26 | static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) { 27 | if (scratch != NULL) { 28 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 29 | secp256k1_callback_call(error_callback, "invalid scratch space"); 30 | return; 31 | } 32 | VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */ 33 | memset(scratch->magic, 0, sizeof(scratch->magic)); 34 | free(scratch); 35 | } 36 | } 37 | 38 | static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch) { 39 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 40 | secp256k1_callback_call(error_callback, "invalid scratch space"); 41 | return 0; 42 | } 43 | return scratch->alloc_size; 44 | } 45 | 46 | static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint) { 47 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 48 | secp256k1_callback_call(error_callback, "invalid scratch space"); 49 | return; 50 | } 51 | if (checkpoint > scratch->alloc_size) { 52 | secp256k1_callback_call(error_callback, "invalid checkpoint"); 53 | return; 54 | } 55 | scratch->alloc_size = checkpoint; 56 | } 57 | 58 | static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t objects) { 59 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 60 | secp256k1_callback_call(error_callback, "invalid scratch space"); 61 | return 0; 62 | } 63 | /* Ensure that multiplication will not wrap around */ 64 | if (ALIGNMENT > 1 && objects > SIZE_MAX/(ALIGNMENT - 1)) { 65 | return 0; 66 | } 67 | if (scratch->max_size - scratch->alloc_size <= objects * (ALIGNMENT - 1)) { 68 | return 0; 69 | } 70 | return scratch->max_size - scratch->alloc_size - objects * (ALIGNMENT - 1); 71 | } 72 | 73 | static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t size) { 74 | void *ret; 75 | size_t rounded_size; 76 | 77 | rounded_size = ROUND_TO_ALIGN(size); 78 | /* Check that rounding did not wrap around */ 79 | if (rounded_size < size) { 80 | return NULL; 81 | } 82 | size = rounded_size; 83 | 84 | if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { 85 | secp256k1_callback_call(error_callback, "invalid scratch space"); 86 | return NULL; 87 | } 88 | 89 | if (size > scratch->max_size - scratch->alloc_size) { 90 | return NULL; 91 | } 92 | ret = (void *) ((char *) scratch->data + scratch->alloc_size); 93 | memset(ret, 0, size); 94 | scratch->alloc_size += size; 95 | 96 | return ret; 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/selftest.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2020 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_SELFTEST_H 8 | #define SECP256K1_SELFTEST_H 9 | 10 | #include "hash.h" 11 | 12 | #include 13 | 14 | static int secp256k1_selftest_sha256(void) { 15 | static const char *input63 = "For this sample, this 63-byte string will be used as input data"; 16 | static const unsigned char output32[32] = { 17 | 0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 18 | 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42, 19 | }; 20 | unsigned char out[32]; 21 | secp256k1_sha256 hasher; 22 | secp256k1_sha256_initialize(&hasher); 23 | secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); 24 | secp256k1_sha256_finalize(&hasher, out); 25 | return secp256k1_memcmp_var(out, output32, 32) == 0; 26 | } 27 | 28 | static int secp256k1_selftest_passes(void) { 29 | return secp256k1_selftest_sha256(); 30 | } 31 | 32 | #endif /* SECP256K1_SELFTEST_H */ 33 | -------------------------------------------------------------------------------- /src/testrand.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Copyright (c) 2013, 2014 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 | ***********************************************************************/ 6 | 7 | #ifndef SECP256K1_TESTRAND_H 8 | #define SECP256K1_TESTRAND_H 9 | 10 | #include "util.h" 11 | 12 | /* A non-cryptographic RNG used only for test infrastructure. */ 13 | 14 | /** Seed the pseudorandom number generator for testing. */ 15 | SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16); 16 | 17 | /** Generate a pseudorandom number in the range [0..2**32-1]. */ 18 | SECP256K1_INLINE static uint32_t secp256k1_testrand32(void); 19 | 20 | /** Generate a pseudorandom number in the range [0..2**64-1]. */ 21 | SECP256K1_INLINE static uint64_t secp256k1_testrand64(void); 22 | 23 | /** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or 24 | * more. */ 25 | SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits); 26 | 27 | /** Generate a pseudorandom number in the range [0..range-1]. */ 28 | static uint32_t secp256k1_testrand_int(uint32_t range); 29 | 30 | /** Generate a pseudorandom 32-byte array. */ 31 | static void secp256k1_testrand256(unsigned char *b32); 32 | 33 | /** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ 34 | static void secp256k1_testrand256_test(unsigned char *b32); 35 | 36 | /** Generate pseudorandom bytes with long sequences of zero and one bits. */ 37 | static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len); 38 | 39 | /** Generate a pseudorandom 64-bit integer in the range min..max, inclusive. */ 40 | static int64_t secp256k1_testrandi64(uint64_t min, uint64_t max); 41 | 42 | /** Flip a single random bit in a byte array */ 43 | static void secp256k1_testrand_flip(unsigned char *b, size_t len); 44 | 45 | /** Initialize the test RNG using (hex encoded) array up to 16 bytes, or randomly if hexseed is NULL. */ 46 | static void secp256k1_testrand_init(const char* hexseed); 47 | 48 | /** Print final test information. */ 49 | static void secp256k1_testrand_finish(void); 50 | 51 | #endif /* SECP256K1_TESTRAND_H */ 52 | -------------------------------------------------------------------------------- /src/testutil.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * Distributed under the MIT software license, see the accompanying * 3 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 4 | ***********************************************************************/ 5 | 6 | #ifndef SECP256K1_TESTUTIL_H 7 | #define SECP256K1_TESTUTIL_H 8 | 9 | #include "field.h" 10 | #include "testrand.h" 11 | #include "util.h" 12 | 13 | static void random_fe(secp256k1_fe *x) { 14 | unsigned char bin[32]; 15 | do { 16 | secp256k1_testrand256(bin); 17 | if (secp256k1_fe_set_b32_limit(x, bin)) { 18 | return; 19 | } 20 | } while(1); 21 | } 22 | 23 | static void random_fe_non_zero(secp256k1_fe *nz) { 24 | do { 25 | random_fe(nz); 26 | } while (secp256k1_fe_is_zero(nz)); 27 | } 28 | 29 | #endif /* SECP256K1_TESTUTIL_H */ 30 | -------------------------------------------------------------------------------- /tools/check-abi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | default_base_version="$(git describe --match "v*.*.*" --abbrev=0)" 6 | default_new_version="HEAD" 7 | 8 | display_help_and_exit() { 9 | echo "Usage: $0 [ []]" 10 | echo "" 11 | echo "Description: This script uses the ABI Compliance Checker tool to determine if the ABI" 12 | echo " of a new version of libsecp256k1 has changed in a backward-incompatible way." 13 | echo "" 14 | echo "Options:" 15 | echo " base_ver Specify the base version as a git commit-ish" 16 | echo " (default: most recent reachable tag matching \"v.*.*\", currently \"$default_base_version\")" 17 | echo " new_ver Specify the new version as a git commit-ish" 18 | echo " (default: $default_new_version)" 19 | echo " -h, --help Display this help message" 20 | exit 0 21 | } 22 | 23 | if [ "$#" -eq 0 ]; then 24 | base_version="$default_base_version" 25 | new_version="$default_new_version" 26 | elif [ "$#" -eq 1 ] && { [ "$1" = "-h" ] || [ "$1" = "--help" ]; }; then 27 | display_help_and_exit 28 | elif [ "$#" -eq 1 ] || [ "$#" -eq 2 ]; then 29 | base_version="$1" 30 | if [ "$#" -eq 2 ]; then 31 | new_version="$2" 32 | fi 33 | else 34 | echo "Invalid usage. See help:" 35 | echo "" 36 | display_help_and_exit 37 | fi 38 | 39 | checkout_and_build() { 40 | _orig_dir="$(pwd)" 41 | git worktree add --detach "$1" "$2" 42 | cd "$1" 43 | mkdir build && cd build 44 | cmake -S .. --preset dev-mode \ 45 | -DCMAKE_C_COMPILER=gcc -DCMAKE_BUILD_TYPE=None -DCMAKE_C_FLAGS="-g -Og -gdwarf-4" \ 46 | -DSECP256K1_BUILD_BENCHMARK=OFF \ 47 | -DSECP256K1_BUILD_TESTS=OFF \ 48 | -DSECP256K1_BUILD_EXHAUSTIVE_TESTS=OFF \ 49 | -DSECP256K1_BUILD_CTIME_TESTS=OFF \ 50 | -DSECP256K1_BUILD_EXAMPLES=OFF 51 | cmake --build . -j "$(nproc)" 52 | abi-dumper src/libsecp256k1.so -o ABI.dump -lver "$2" 53 | cd "$_orig_dir" 54 | } 55 | 56 | echo "Comparing $base_version (base version) to $new_version (new version)" 57 | echo 58 | 59 | base_source_dir="$(mktemp -d)" 60 | checkout_and_build "$base_source_dir" "$base_version" 61 | 62 | new_source_dir="$(mktemp -d)" 63 | checkout_and_build "$new_source_dir" "$new_version" 64 | 65 | abi-compliance-checker -lib libsecp256k1 -old "${base_source_dir}/build/ABI.dump" -new "${new_source_dir}/build/ABI.dump" 66 | git worktree remove "$base_source_dir" 67 | git worktree remove "$new_source_dir" 68 | -------------------------------------------------------------------------------- /tools/tests_wycheproof_generate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) 2023 Random "Randy" Lattice and Sean Andersen 3 | # Distributed under the MIT software license, see the accompanying 4 | # file COPYING or https://www.opensource.org/licenses/mit-license.php. 5 | ''' 6 | Generate a C file with ECDSA testvectors from the Wycheproof project. 7 | ''' 8 | 9 | import json 10 | import sys 11 | 12 | filename_input = sys.argv[1] 13 | 14 | with open(filename_input) as f: 15 | doc = json.load(f) 16 | 17 | num_groups = len(doc['testGroups']) 18 | 19 | def to_c_array(x): 20 | if x == "": 21 | return "" 22 | s = ',0x'.join(a+b for a,b in zip(x[::2], x[1::2])) 23 | return "0x" + s 24 | 25 | 26 | num_vectors = 0 27 | offset_msg_running, offset_pk_running, offset_sig = 0, 0, 0 28 | out = "" 29 | messages = "" 30 | signatures = "" 31 | public_keys = "" 32 | cache_msgs = {} 33 | cache_public_keys = {} 34 | 35 | for i in range(num_groups): 36 | group = doc['testGroups'][i] 37 | num_tests = len(group['tests']) 38 | public_key = group['publicKey'] 39 | for j in range(num_tests): 40 | test_vector = group['tests'][j] 41 | # // 2 to convert hex to byte length 42 | sig_size = len(test_vector['sig']) // 2 43 | msg_size = len(test_vector['msg']) // 2 44 | 45 | if test_vector['result'] == "invalid": 46 | expected_verify = 0 47 | elif test_vector['result'] == "valid": 48 | expected_verify = 1 49 | else: 50 | raise ValueError("invalid result field") 51 | 52 | if num_vectors != 0 and sig_size != 0: 53 | signatures += ",\n " 54 | 55 | new_msg = False 56 | msg = to_c_array(test_vector['msg']) 57 | msg_offset = offset_msg_running 58 | # check for repeated msg 59 | if msg not in cache_msgs: 60 | if num_vectors != 0 and msg_size != 0: 61 | messages += ",\n " 62 | cache_msgs[msg] = offset_msg_running 63 | messages += msg 64 | new_msg = True 65 | else: 66 | msg_offset = cache_msgs[msg] 67 | 68 | new_pk = False 69 | pk = to_c_array(public_key['uncompressed']) 70 | pk_offset = offset_pk_running 71 | # check for repeated pk 72 | if pk not in cache_public_keys: 73 | if num_vectors != 0: 74 | public_keys += ",\n " 75 | cache_public_keys[pk] = offset_pk_running 76 | public_keys += pk 77 | new_pk = True 78 | else: 79 | pk_offset = cache_public_keys[pk] 80 | 81 | signatures += to_c_array(test_vector['sig']) 82 | 83 | out += " /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n" 84 | out += f" {{{pk_offset}, {msg_offset}, {msg_size}, {offset_sig}, {sig_size}, {expected_verify} }},\n" 85 | if new_msg: 86 | offset_msg_running += msg_size 87 | if new_pk: 88 | offset_pk_running += 65 89 | offset_sig += sig_size 90 | num_vectors += 1 91 | 92 | struct_definition = """ 93 | typedef struct { 94 | size_t pk_offset; 95 | size_t msg_offset; 96 | size_t msg_len; 97 | size_t sig_offset; 98 | size_t sig_len; 99 | int expected_verify; 100 | } wycheproof_ecdsa_testvector; 101 | """ 102 | 103 | 104 | print("/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */") 105 | print(f"#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})") 106 | 107 | print(struct_definition) 108 | 109 | print("static const unsigned char wycheproof_ecdsa_messages[] = { " + messages + "};\n") 110 | print("static const unsigned char wycheproof_ecdsa_public_keys[] = { " + public_keys + "};\n") 111 | print("static const unsigned char wycheproof_ecdsa_signatures[] = { " + signatures + "};\n") 112 | 113 | print("static const wycheproof_ecdsa_testvector testvectors[SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS] = {") 114 | print(out) 115 | print("};") 116 | --------------------------------------------------------------------------------