Repository: paritytech/libsecp256k1 Branch: master Commit: f992b80dedc1 Files: 39 Total size: 440.1 KB Directory structure: gitextract_oew3p_ij/ ├── .arcconfig ├── .editorconfig ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ ├── audit.yml │ ├── check-style.yml │ ├── clippy.yml │ ├── prepare_artifacts.sh │ ├── rust-windows.yml │ ├── rust.yml │ └── sccache.sh ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── benches/ │ ├── public_key.rs │ ├── sign.rs │ └── signature.rs ├── build.rs ├── core/ │ ├── Cargo.toml │ └── src/ │ ├── der.rs │ ├── ecdh.rs │ ├── ecdsa.rs │ ├── ecmult.rs │ ├── error.rs │ ├── field.rs │ ├── group.rs │ ├── lib.rs │ └── scalar.rs ├── gen/ │ ├── ecmult/ │ │ ├── Cargo.toml │ │ └── src/ │ │ └── lib.rs │ └── genmult/ │ ├── Cargo.toml │ └── src/ │ └── lib.rs ├── res/ │ └── ecdsa_secp256k1_sha256_test.json ├── rustfmt.toml ├── src/ │ └── lib.rs └── tests/ ├── serde.rs ├── verify.rs └── wycheproof.rs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .arcconfig ================================================ { "phabricator.uri" : "https://source.that.world/" } ================================================ FILE: .editorconfig ================================================ root = true [*] indent_style=space indent_size=4 tab_width=4 end_of_line=lf charset=utf-8 trim_trailing_whitespace=true max_line_length=80 insert_final_newline=true ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: cargo directory: "/" labels: [] schedule: interval: "daily" rebase-strategy: disabled open-pull-requests-limit: 2 - package-ecosystem: github-actions directory: "/" labels: [] schedule: interval: "daily" rebase-strategy: disabled open-pull-requests-limit: 2 ================================================ FILE: .github/workflows/audit.yml ================================================ name: Security audit on: pull_request: paths: Cargo.lock schedule: - cron: '0 0 * * *' jobs: security_audit: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Checkout sources uses: actions/checkout@v3.1.0 with: fetch-depth: 50 - name: Run cargo audit uses: actions-rs/audit-check@v1.2.0 with: token: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/check-style.yml ================================================ name: Check style on: pull_request: push: branches: - master - stable tags: - v* paths-ignore: - 'README.md' jobs: check-style: name: Check style runs-on: ubuntu-latest env: RUST_BACKTRACE: full steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Checkout sources & submodules uses: actions/checkout@v3.1.0 with: fetch-depth: 5 submodules: recursive - name: Install toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: stable components: clippy, rustfmt override: true - name: Checking style uses: actions-rs/cargo@v1.0.3 with: command: fmt toolchain: stable args: --all -- --check ================================================ FILE: .github/workflows/clippy.yml ================================================ name: Check clippy on: pull_request: push: branches: - master - stable tags: - v* paths-ignore: - 'README.md' jobs: check-clippy: name: Check clippy runs-on: ubuntu-latest env: RUST_BACKTRACE: full steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Checkout sources & submodules uses: actions/checkout@v3.1.0 with: fetch-depth: 5 submodules: recursive - name: Install toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: stable components: clippy, rustfmt override: true - name: Checking clippy uses: actions-rs/cargo@v1.0.3 with: command: clippy toolchain: stable args: --all - name: Checking clippy uses: actions-rs/cargo@v1.0.3 with: command: clippy toolchain: stable args: --all --no-default-features --features std,hmac,lazy-static-context ================================================ FILE: .github/workflows/prepare_artifacts.sh ================================================ #!/bin/bash set -e # fail on any error set -u # treat unset variables as error # ARGUMENT $1 CARGO_TARGET #Set additional dir path if [ "${1}" == "" ]; then dir="" else dir=".." fi mkdir -p ./artifacts/ cd ./target/$1/release/ ls -a echo "_____ Find binary files in target _____" find . -maxdepth 1 -type f ! -size 0 -exec grep -IL . "{}" \; | cut -c 3- echo "_____ Move binaries to artifacts folder _____" for binary in $(find . -maxdepth 1 -type f ! -size 0 -exec grep -IL . "{}" \; | cut -c 3- ) do mv -v $binary ../$dir/../artifacts/$binary done cd ../$dir/.. echo "_____ Clean target dir _____" find ./target/$1/{debug,release} -maxdepth 1 -type f -delete; rm -f ./target/.rustc_info.json; rm -rf ./target/$1/{debug,release}/{deps,.fingerprint}/ ================================================ FILE: .github/workflows/rust-windows.yml ================================================ # almost a copy of .github/workflows/rust.yml made in https://github.com/paritytech/libsecp256k1/pull/84 # windows causes some troubles with sudo sccache and # caching within GHA https://github.com/Swatinem/rust-cache/issues/31 name: Check, Test and Build on Windows on: pull_request: push: branches: - master - stable tags: - v* paths-ignore: - 'README.md' jobs: check: name: Check strategy: matrix: platform: - windows-latest toolchain: - stable - nightly compiler: - clang - gcc runs-on: ${{ matrix.platform }} env: RUST_BACKTRACE: full steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Install sudo for windows #https://github.com/actions/virtual-environments/issues/572 if: matrix.platform == 'windows-latest' run: choco install sudo - name: Install LLVM for Windows if: matrix.platform == 'windows-latest' && matrix.compiler == 'clang' run: | choco install llvm echo "CC=clang-cl.exe --enable-64-bit" >> "$GITHUB_ENV" echo "CXX=clang-cl.exe --enable-64-bit" >> "$GITHUB_ENV" refreshenv - name: Checkout sources & submodules uses: actions/checkout@v3.1.0 with: fetch-depth: 5 submodules: recursive - name: Install toolchain id: toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} components: clippy, rustfmt override: true - name: Set cache_hash ENV and prepare cache dir run: | echo "cache_hash=${{ runner.os }}-${{ steps.toolchain.outputs.rustc_hash }}-${{ matrix.compiler }}-${{ hashFiles('**/Cargo.toml') }}" >> "$GITHUB_ENV" mkdir -p $HOME/sccache sudo chmod -R a+w $HOME/.cargo shell: bash - name: Cache cargo registry uses: actions/cache@v3.0.11 with: path: $HOME/.cargo/registry key: cargo-registry-${{ env['cache_hash'] }} - name: Cache cargo index uses: actions/cache@v3.0.11 with: path: $HOME/.cargo/git key: cargo-git-${{ env['cache_hash'] }} - name: Cache cargo build uses: actions/cache@v3.0.11 with: path: target key: cargo-target-${{ env['cache_hash'] }} - name: Checking ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: check toolchain: ${{ matrix.toolchain }} args: --all --verbose test: name: Test needs: [check] strategy: matrix: platform: - windows-latest toolchain: - stable - nightly compiler: - clang - gcc runs-on: ${{ matrix.platform }} env: RUST_BACKTRACE: full steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Set default compiler if: matrix.compiler == 'clang' && matrix.platform != 'windows-latest' run: | echo "CC=clang" >> "$GITHUB_ENV" echo "CXX=clang++" >> "$GITHUB_ENV" - name: Install sudo for windows #https://github.com/actions/virtual-environments/issues/572 if: matrix.platform == 'windows-latest' run: choco install sudo - name: Install LLVM for Windows if: matrix.platform == 'windows-latest' && matrix.compiler == 'clang' run: | choco install llvm echo "CC=clang-cl.exe --enable-64-bit" >> "$GITHUB_ENV" echo "CXX=clang-cl.exe --enable-64-bit" >> "$GITHUB_ENV" refreshenv - name: Checkout sources & submodules uses: actions/checkout@v3.1.0 with: fetch-depth: 5 submodules: recursive - name: Install toolchain id: toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} components: clippy, rustfmt override: true - name: Set cache_hash ENV and prepare cache dir run: | echo "cache_hash=${{ runner.os }}-${{ steps.toolchain.outputs.rustc_hash }}-${{ matrix.compiler }}-${{ hashFiles('**/Cargo.toml') }}" >> "$GITHUB_ENV" mkdir -p $HOME/sccache sudo chmod -R a+w $HOME/.cargo shell: bash - name: Cache cargo registry uses: actions/cache@v3.0.11 with: path: $HOME/.cargo/registry key: cargo-registry-${{ env['cache_hash'] }} - name: Cache cargo index uses: actions/cache@v3.0.11 with: path: $HOME/.cargo/git key: cargo-git-${{ env['cache_hash'] }} - name: Cache cargo build uses: actions/cache@v3.0.11 with: path: target key: cargo-target-${{ env['cache_hash'] }} - name: Testing ${{ matrix.platform }}-${{ matrix.toolchain }} (debug build) uses: actions-rs/cargo@v1.0.3 with: command: test toolchain: ${{ matrix.toolchain }} args: --all --verbose - name: Testing ${{ matrix.platform }}-${{ matrix.toolchain }} (release build) uses: actions-rs/cargo@v1.0.3 with: command: test toolchain: ${{ matrix.toolchain }} args: --all --release --verbose build: name: Build needs: [check,test] strategy: matrix: platform: - windows-latest toolchain: - stable - nightly compiler: - clang - gcc runs-on: ${{ matrix.platform }} env: RUST_BACKTRACE: full # NOTE: Enables the aes-ni instructions for RustCrypto dependency. # Strip binaries # If you change this please remember to also update .cargo/config RUSTFLAGS: "-C target-feature=+aes,+sse2,+ssse3 -C link-arg=-s" steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Set default compiler if: matrix.compiler == 'clang' && matrix.platform != 'windows-latest' run: | echo "CC=clang" >> "$GITHUB_ENV" echo "CXX=clang++" >> "$GITHUB_ENV" - name: Install sudo for windows #https://github.com/actions/virtual-environments/issues/572 if: matrix.platform == 'windows-latest' run: choco install sudo - name: Install LLVM for Windows if: matrix.platform == 'windows-latest' && matrix.compiler == 'clang' run: | choco install llvm echo "CC=clang-cl.exe --enable-64-bit" >> "$GITHUB_ENV" echo "CXX=clang-cl.exe --enable-64-bit" >> "$GITHUB_ENV" refreshenv - name: Checkout sources & submodules uses: actions/checkout@v3.1.0 with: fetch-depth: 5 submodules: recursive - name: Install toolchain id: toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} components: clippy, rustfmt override: true - name: Set cache_hash ENV and prepare cache dir run: | echo "cache_hash=${{ runner.os }}-${{ steps.toolchain.outputs.rustc_hash }}-${{ matrix.compiler }}-${{ hashFiles('**/Cargo.toml') }}" >> "$GITHUB_ENV" mkdir -p $HOME/sccache sudo chmod -R a+w $HOME/.cargo shell: bash - name: Cache cargo registry uses: actions/cache@v3.0.11 with: path: $HOME/.cargo/registry key: cargo-registry-${{ env['cache_hash'] }} - name: Cache cargo index uses: actions/cache@v3.0.11 with: path: $HOME/.cargo/git key: cargo-git-${{ env['cache_hash'] }} - name: Cache cargo build uses: actions/cache@v3.0.11 with: path: target key: cargo-target-${{ env['cache_hash'] }} - name: Building ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --all --verbose --release - name: Building `no default` ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --verbose --no-default-features - name: Building `hmac` ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --verbose --no-default-features --features hmac - name: Building `static-context` ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --verbose --no-default-features --features static-context - name: Building `lazy-static-context` ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --verbose --no-default-features --features lazy-static-context - name: Prepare artifacts run: .github/workflows/prepare_artifacts.sh "" shell: bash - name: Upload artifacts uses: actions/upload-artifact@v3.1.0 with: name: ${{ matrix.platform }}.${{ matrix.toolchain }}.${{ matrix.compiler }}.zip path: artifacts/ ================================================ FILE: .github/workflows/rust.yml ================================================ name: Check, Test and Build Suite on: pull_request: push: branches: - master - stable tags: - v* paths-ignore: - 'README.md' jobs: check: name: Check strategy: matrix: platform: - ubuntu-latest - macos-latest toolchain: - stable - nightly compiler: - clang - gcc runs-on: ${{ matrix.platform }} env: RUST_BACKTRACE: full steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Set default compiler if: matrix.compiler == 'clang' run: | echo "CC=clang" >> "$GITHUB_ENV" echo "CXX=clang++" >> "$GITHUB_ENV" - name: Checkout sources & submodules uses: actions/checkout@v3.1.0 with: fetch-depth: 5 submodules: recursive - name: Install toolchain id: toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} components: clippy, rustfmt override: true - uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1 - name: Cache sccache uses: actions/cache@v3.0.11 with: path: "$HOME/sccache" key: sccache-${{ env['cache_hash'] }} - name: Install & start sccache for ${{ matrix.platform }} shell: bash run: .github/workflows/sccache.sh ${{ runner.os}} - name: Sccache statistics run: sccache --show-stats # here comes different part - name: Checking ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: check toolchain: ${{ matrix.toolchain }} args: --all --verbose - name: Stop sccache if: always() run: sccache --stop-server test: name: Test needs: [check] strategy: matrix: platform: - ubuntu-latest - macos-latest toolchain: - stable - nightly compiler: - clang - gcc runs-on: ${{ matrix.platform }} env: RUST_BACKTRACE: full steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Set default compiler if: matrix.compiler == 'clang' run: | echo "CC=clang" >> "$GITHUB_ENV" echo "CXX=clang++" >> "$GITHUB_ENV" - name: Checkout sources & submodules uses: actions/checkout@v3.1.0 with: fetch-depth: 5 submodules: recursive - name: Install toolchain id: toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} components: clippy, rustfmt override: true - uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1 - name: Cache sccache uses: actions/cache@v3.0.11 with: path: "$HOME/sccache" key: sccache-${{ env['cache_hash'] }} - name: Install & start sccache for ${{ matrix.platform }} shell: bash run: .github/workflows/sccache.sh ${{ runner.os}} - name: Sccache statistics run: sccache --show-stats # here comes different part - name: Testing ${{ matrix.platform }}-${{ matrix.toolchain }} (debug build) uses: actions-rs/cargo@v1.0.3 with: command: test toolchain: ${{ matrix.toolchain }} args: --all --verbose - name: Testing ${{ matrix.platform }}-${{ matrix.toolchain }} (release build) uses: actions-rs/cargo@v1.0.3 with: command: test toolchain: ${{ matrix.toolchain }} args: --all --release --verbose - name: Stop sccache if: always() run: sccache --stop-server build: name: Build needs: [check,test] strategy: matrix: platform: - ubuntu-latest - macos-latest toolchain: - stable - nightly compiler: - clang - gcc runs-on: ${{ matrix.platform }} env: RUST_BACKTRACE: full # NOTE: Enables the aes-ni instructions for RustCrypto dependency. # Strip binaries # If you change this please remember to also update .cargo/config RUSTFLAGS: "-C target-feature=+aes,+sse2,+ssse3 -C link-arg=-s" steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # 0.11.0 - name: Set default compiler if: matrix.compiler == 'clang' run: | echo "CC=clang" >> "$GITHUB_ENV" echo "CXX=clang++" >> "$GITHUB_ENV" - name: Checkout sources & submodules uses: actions/checkout@v3.1.0 with: fetch-depth: 5 submodules: recursive - name: Install toolchain id: toolchain uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} components: clippy, rustfmt override: true - uses: Swatinem/rust-cache@22c9328bcba27aa81a32b1bef27c7e3c78052531 # v2.0.1 - name: Cache sccache uses: actions/cache@v3.0.11 with: path: "$HOME/sccache" key: sccache-${{ env['cache_hash'] }} - name: Install & start sccache for ${{ matrix.platform }} shell: bash run: .github/workflows/sccache.sh ${{ runner.os}} - name: Sccache statistics run: sccache --show-stats # here comes different part - name: Building ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --all --verbose --release - name: Building `no default` ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --verbose --no-default-features - name: Building `hmac` ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --verbose --no-default-features --features hmac - name: Building `static-context` ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --verbose --no-default-features --features static-context - name: Building `lazy-static-context` ${{ matrix.platform }}-${{ matrix.toolchain }} uses: actions-rs/cargo@v1.0.3 with: command: build toolchain: ${{ matrix.toolchain }} args: --verbose --no-default-features --features lazy-static-context - name: Stop sccache if: always() run: sccache --stop-server - name: Prepare artifacts run: .github/workflows/prepare_artifacts.sh "" shell: bash - name: Upload artifacts uses: actions/upload-artifact@v3.1.0 with: name: ${{ matrix.platform }}.${{ matrix.toolchain }}.${{ matrix.compiler }}.zip path: artifacts/ ================================================ FILE: .github/workflows/sccache.sh ================================================ #!/bin/bash set -ex export SCCACHE_CACHE_SIZE="1G" export SCCACHE_IDLE_TIMEOUT=0 export SCCACHE_DIR="$HOME/sccache" OS=$1 VERSION="0.2.13" echo "Current OS: $OS" case $OS in "macOS") PLATFORM="x86_64-apple-darwin" ;; "Linux") PLATFORM="x86_64-unknown-linux-musl" ;; "Windows") PLATFORM="x86_64-pc-windows-msvc" VERSION="0.2.14" ;; esac echo "Target arch: " $PLATFORM BASENAME="sccache-$VERSION-$PLATFORM" URL="https://github.com/mozilla/sccache/releases/download/$VERSION/$BASENAME.tar.gz" echo "Download sccache from " "$URL" curl -LO "$URL" tar -xzvf "$BASENAME.tar.gz" ls $BASENAME/ echo "$(pwd)/$BASENAME" >> "$GITHUB_PATH" echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV" ./$BASENAME/sccache --start-server ================================================ FILE: .gitignore ================================================ /target/ **/*.rs.bk Cargo.lock *.swp /.idea /shell.nix ================================================ FILE: CHANGELOG.md ================================================ # Changelog The format is based on [Keep a Changelog]. [Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ ## [0.5.0] - 2021-05-18 - Add standard non-overflowing signature parsing `Signature::parse_standard`. The previous behavior `Signature::parse` is considered non-standard and renamed to `Signature::parse_overflowing`. Unless you have a specific need, you should switch to use the new `Signature::parse_standard` function. (PR #67) ## [0.3.5] - 2020-02-06 - Implement `std::error::Error` and `Display` for `Error`. (PR #29) - Fix the PartialEq impl of Field. (PR #30) - Add `LowerHex` implementation for `SecretKey` and `Scalar`. (PR #32) - Put signing behind feature flag. (PR #33) ================================================ FILE: Cargo.toml ================================================ [package] name = "libsecp256k1" description = "Pure Rust secp256k1 implementation." license = "Apache-2.0" version = "0.7.2" authors = ["Wei Tang "] repository = "https://github.com/paritytech/libsecp256k1" keywords = ["crypto", "ECDSA", "secp256k1", "bitcoin", "no_std"] edition = "2018" resolver = "2" [dependencies] libsecp256k1-core = { version = "0.3.0", path = "core", default-features = false } arrayref = "0.3" rand = { version = "0.8", default-features = false } digest = "0.9" base64 = { version = "0.22", default-features = false } hmac-drbg = { version = "0.3", optional = true } sha2 = { version = "0.9", optional = true, default-features = false } typenum = { version = "1.12", optional = true } serde = { version = "1.0.104", features = ["derive"], default-features = false } lazy_static = { version = "1.4.0", optional = true } [dev-dependencies] secp256k1-test = { package = "secp256k1", version = "0.20.3", features = ["rand-std", "recovery"] } clear_on_drop = "0.2" serde_json = "1.0" hex = "0.4" hex-literal = "0.3.3" bincode = "1.3.3" [build-dependencies] libsecp256k1-gen-ecmult = { version = "0.3.0", path = "gen/ecmult" } libsecp256k1-gen-genmult = { version = "0.3.0", path = "gen/genmult" } [features] default = ["std", "hmac", "static-context"] std = ["libsecp256k1-core/std", "sha2/std", "rand/std", "serde/std", "base64/std"] hmac = ["hmac-drbg", "sha2", "typenum"] static-context = [] lazy-static-context = ["static-context", "lazy_static", "std"] [workspace] members = [ "./gen/ecmult", "./gen/genmult", ] ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ _Please note that this repository is no longer maintained. You can use [k256](https://crates.io/crates/k256) instead._ # SECP256K1 implementation in pure Rust * [Cargo](https://crates.io/crates/libsecp256k1) * [Documentation](https://docs.rs/libsecp256k1) SECP256K1 implementation with `no_std` support. Currently we have implementation for: * Convert a private key to a public key. * Sign messages. * Signature verification. * Public key recovery from signed messages. * Shared secrets. ## Feature flags * `std`: If disabled, works in `no_std` environment. Enabled by default. * `hmac`: Add certain features that requires the HMAC-DRBG. This includes signing. Enabled by default. * `static-context`: To speed up computation, the library uses a pre-computed table context for many `ecmult` operations. This feature flag puts the context directly as static variables. If disabled, the context must be created from heap manually. Increases binary size, enabled by default. * `lazy-static-context`: Instead of storing the pre-computed table context as static variables, store it as a variable that dynamically allocates the context in heap via `lazy_static`. It overwrites `static-context`. Impact bootstrap performance and only available in `std`, disabled by default. ## Development workflow ### Branch This repository uses `develop` branch for development. Changes are periodically merged to `master` branch. ### Pull request All changes (except new releases) are handled through pull requests. Please open your PR against `develop` branch. ### Versioning `libsecp256k1` follows [Semantic Versioning](https://semver.org/). An unreleased crate in the repository will have the `-dev` suffix in the end, and we do rolling releases. When you make a pull request against this repository, please also update the affected crates' versions, using the following rules. Note that the rules should be applied recursively -- if a change modifies any upper crate's dependency (even just the `Cargo.toml` file), then the upper crate will also need to apply those rules. Additionally, if your change is notable, then you should also modify the corresponding `CHANGELOG.md` file, in the "Unreleased" section. If the affected crate already has `-dev` suffix: * If your change is a patch, then you do not have to update any versions. * If your change introduces a new feature, please check if the local version already had its minor version bumped, if not, bump it. * If your change modifies the current interface, please check if the local version already had its major version bumped, if not, bump it. If the affected crate does not yet have `-dev` suffix: * If your change is a patch, then bump the patch version, and add `-dev` suffix. * If your change introduces a new feature, then bump the minor version, and add `-dev` suffix. * If your change modifies the current interface, then bump the major version, and add `-dev` suffix. If your pull request introduces a new crate, please set its version to `1.0.0-dev`. ================================================ FILE: benches/public_key.rs ================================================ #![feature(test)] extern crate test; use libsecp256k1::PublicKey; use secp256k1_test::{rand::thread_rng, Secp256k1}; use test::Bencher; #[bench] fn bench_public_key_parse(b: &mut Bencher) { let secp256k1 = Secp256k1::new(); let (_, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()); let pubkey_arr = secp_pubkey.serialize_uncompressed(); assert!(pubkey_arr.len() == 65); let mut pubkey_a = [0u8; 65]; pubkey_a[0..65].copy_from_slice(&pubkey_arr[0..65]); b.iter(|| { let _pubkey = PublicKey::parse(&pubkey_a).unwrap(); }); } #[bench] fn bench_public_key_serialize(b: &mut Bencher) { let secp256k1 = Secp256k1::new(); let (_, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()); let pubkey_arr = secp_pubkey.serialize_uncompressed(); assert!(pubkey_arr.len() == 65); let mut pubkey_a = [0u8; 65]; pubkey_a[0..65].copy_from_slice(&pubkey_arr[0..65]); let pubkey = PublicKey::parse(&pubkey_a).unwrap(); b.iter(|| { let _serialized = pubkey.serialize(); }); } #[bench] fn bench_public_key_serialize_compressed(b: &mut Bencher) { let secp256k1 = Secp256k1::new(); let (_, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()); let pubkey_arr = secp_pubkey.serialize_uncompressed(); assert!(pubkey_arr.len() == 65); let mut pubkey_a = [0u8; 65]; pubkey_a[0..65].copy_from_slice(&pubkey_arr[0..65]); let pubkey = PublicKey::parse(&pubkey_a).unwrap(); b.iter(|| { let _serialized = pubkey.serialize_compressed(); }); } ================================================ FILE: benches/sign.rs ================================================ #![feature(test)] extern crate test; use arrayref::array_ref; use libsecp256k1::{sign, Message, SecretKey}; use secp256k1_test::{rand::thread_rng, Secp256k1}; use test::Bencher; #[bench] fn bench_sign_message(b: &mut Bencher) { let secp256k1 = Secp256k1::new(); let message = Message::parse(&[5u8; 32]); let (secp_privkey, _) = secp256k1.generate_keypair(&mut thread_rng()); let seckey = SecretKey::parse(array_ref!(secp_privkey, 0, 32)).unwrap(); b.iter(|| { let _ = sign(&message, &seckey); }); } ================================================ FILE: benches/signature.rs ================================================ #![feature(test)] extern crate test; use libsecp256k1::Signature; use secp256k1_test::{rand::thread_rng, Message as SecpMessage, Secp256k1}; use test::Bencher; #[bench] fn bench_signature_parse(b: &mut Bencher) { let secp256k1 = Secp256k1::new(); let message_arr = [5u8; 32]; let (privkey, _) = secp256k1.generate_keypair(&mut thread_rng()); let message = SecpMessage::from_slice(&message_arr).unwrap(); let signature = secp256k1.sign(&message, &privkey); let signature_arr = signature.serialize_compact(); assert!(signature_arr.len() == 64); let mut signature_a = [0u8; 64]; signature_a.copy_from_slice(&signature_arr[0..64]); b.iter(|| { let _signature = Signature::parse_standard_slice(&signature_a); }); } #[bench] fn bench_signature_serialize(b: &mut Bencher) { let secp256k1 = Secp256k1::new(); let message_arr = [5u8; 32]; let (privkey, _) = secp256k1.generate_keypair(&mut thread_rng()); let message = SecpMessage::from_slice(&message_arr).unwrap(); let signature = secp256k1.sign(&message, &privkey); let signature_arr = signature.serialize_compact(); assert!(signature_arr.len() == 64); let mut signature_a = [0u8; 64]; signature_a.copy_from_slice(&signature_arr[0..64]); let signature = Signature::parse_standard_slice(&signature_a).expect("parsed signature"); b.iter(|| { let _serialized = signature.serialize(); }); } ================================================ FILE: build.rs ================================================ use std::{env, fs::File, io::Write, path::Path}; fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); let const_path = Path::new(&out_dir).join("const.rs"); let mut const_file = File::create(&const_path).expect("Create const.rs file failed"); libsecp256k1_gen_ecmult::generate_to(&mut const_file).expect("Write const.rs file failed"); const_file.flush().expect("Flush const.rs file failed"); let gen_path = Path::new(&out_dir).join("const_gen.rs"); let mut gen_file = File::create(&gen_path).expect("Create const_gen.rs file failed"); libsecp256k1_gen_genmult::generate_to(&mut gen_file).expect("Write const_gen.rs file failed"); gen_file.flush().expect("Flush const_gen.rs file failed"); } ================================================ FILE: core/Cargo.toml ================================================ [package] name = "libsecp256k1-core" description = "Core functions for pure Rust secp256k1 implementation." license = "Apache-2.0" version = "0.3.0" authors = ["Wei Tang "] repository = "https://github.com/paritytech/libsecp256k1" keywords = ["crypto", "ECDSA", "secp256k1", "bitcoin", "no_std"] edition = "2018" [dependencies] subtle = { version = "2.2", default-features = false } crunchy = "0.2" digest = "0.9" [features] default = ["std"] std = ["subtle/std"] ================================================ FILE: core/src/der.rs ================================================ use core::{ convert::{AsMut, AsRef}, mem, }; use crate::{error::Error, scalar::Scalar}; pub struct SignatureArray([u8; 6 + 33 + 33], usize); impl SignatureArray { pub fn new(size: usize) -> Self { SignatureArray([0u8; 6 + 33 + 33], size) } pub fn len(&self) -> usize { self.1 } pub fn is_empty(&self) -> bool { self.len() == 0 } } impl AsRef<[u8]> for SignatureArray { fn as_ref(&self) -> &[u8] { &self.0[..self.1] } } impl AsMut<[u8]> for SignatureArray { fn as_mut(&mut self) -> &mut [u8] { &mut self.0[..self.1] } } pub struct Decoder<'a>(&'a [u8], usize); impl<'a> Decoder<'a> { pub fn new(arr: &'a [u8]) -> Self { Decoder(arr, 0) } pub fn remaining_len(&self) -> usize { self.0.len() - self.1 } pub fn read(&mut self) -> Result { if self.1 >= self.0.len() { Err(Error::InvalidSignature) } else { let v = self.0[self.1]; self.1 += 1; Ok(v) } } pub fn peek(&self, forward: usize) -> Result { if self.1 + forward >= self.0.len() { Err(Error::InvalidSignature) } else { let v = self.0[self.1 + forward]; Ok(v) } } pub fn peek_slice(&self, len: usize) -> Result<&[u8], Error> { if (len == 0 && self.1 >= self.0.len()) || self.1 + len > self.0.len() { Err(Error::InvalidSignature) } else { let v = &self.0[self.1..(self.1 + len)]; Ok(v) } } pub fn skip(&mut self, len: usize) -> Result<(), Error> { if (len == 0 && self.1 >= self.0.len()) || self.1 + len > self.0.len() { Err(Error::InvalidSignature) } else { self.1 += len; Ok(()) } } pub fn read_constructed_sequence(&mut self) -> Result<(), Error> { let v = self.read()?; if v == 0x30 { Ok(()) } else { Err(Error::InvalidSignature) } } pub fn read_len(&mut self) -> Result { let b1 = self.read()?; if b1 == 0xff { return Err(Error::InvalidSignature); } // Short form if b1 & 0x80 == 0 { return Ok(b1 as usize); } // Infinite length is not allowed if b1 == 0x80 { return Err(Error::InvalidSignature); } let mut lenleft = (b1 & 0x7f) as usize; if lenleft > self.remaining_len() { return Err(Error::InvalidSignature); } if self.peek(0)? == 0 { // Not the shortest possible length encoding return Err(Error::InvalidSignature); } if lenleft > mem::size_of::() { return Err(Error::InvalidSignature); } let mut ret = 0; while lenleft > 0 { ret = (ret << 8) | (self.read()? as usize); if ret + lenleft > self.remaining_len() { return Err(Error::InvalidSignature); } lenleft -= 1; } if ret < 128 { // Not the shortest possible length encoding return Err(Error::InvalidSignature); } Ok(ret) } pub fn read_integer(&mut self) -> Result { if self.read()? != 0x02 { return Err(Error::InvalidSignature); } let mut rlen = self.read_len()?; if rlen == 0 || rlen > self.remaining_len() { return Err(Error::InvalidSignature); } if self.peek(0)? == 0x00 && rlen > 1 && (self.peek(1)? & 0x80) == 0x00 { return Err(Error::InvalidSignature); } if self.peek(0)? == 0xff && rlen > 1 && (self.peek(1)? & 0x80) == 0x00 { return Err(Error::InvalidSignature); } let mut overflow = false; if self.peek(0)? & 0x80 == 0x80 { overflow |= true; } // Skip leading zero bytes while rlen > 0 && self.peek(0)? == 0 { rlen -= 1; self.read()?; } if rlen > 32 { overflow |= true; } let mut int = Scalar::default(); if !overflow { let mut b32 = [0u8; 32]; b32[32 - rlen..].copy_from_slice(self.peek_slice(rlen)?); self.skip(rlen)?; overflow |= bool::from(int.set_b32(&b32)); } if overflow { int = Scalar::default(); } Ok(int) } pub fn read_seq_len_lax(&mut self) -> Result { let mut len = self.read()?; if len & 0x80 != 0x00 { len -= 0x80; if len as usize > self.remaining_len() { return Err(Error::InvalidSignature); } self.skip(len as usize)?; } Ok(len as usize) } pub fn read_len_lax(&mut self) -> Result { let mut ret = 0usize; let mut len = self.read()?; if len & 0x80 != 0x00 { len -= 0x80; if len as usize > self.remaining_len() { return Err(Error::InvalidSignature); } while len > 0 && self.peek(0)? == 0 { self.skip(1)?; len -= 1; } if (len as usize) >= mem::size_of::() { return Err(Error::InvalidSignature); } while len > 0 { ret = (ret << 8) + (self.read()? as usize); len -= 1; } } else { ret = len as usize; } if ret > self.remaining_len() { return Err(Error::InvalidSignature); } Ok(ret) } pub fn read_integer_lax(&mut self) -> Result { // Integer tag byte. if self.read()? != 0x02 { return Err(Error::InvalidSignature); } let mut len = self.read_len_lax()?; // Ignore leading zeroes. while len > 0 && self.peek(0)? == 0 { len -= 1; self.skip(1)?; } let mut overflow = false; // Copy value if len > 32 { overflow |= true; } let mut int = Scalar::default(); if !overflow { let mut b32 = [0u8; 32]; b32[32 - len..].copy_from_slice(&self.peek_slice(len)?); self.skip(len)?; overflow |= bool::from(int.set_b32(&b32)); } if overflow { int = Scalar::default(); } Ok(int) } } ================================================ FILE: core/src/ecdh.rs ================================================ use crate::{ ecmult::ECMultContext, group::{Affine, Jacobian}, scalar::Scalar, }; use digest::{generic_array::GenericArray, Digest}; impl ECMultContext { pub fn ecdh_raw( &self, point: &Affine, scalar: &Scalar, ) -> Option> { let mut digest: D = Default::default(); let mut pt = *point; let s = *scalar; if s.is_zero() { return None; } let mut res = Jacobian::default(); self.ecmult_const(&mut res, &pt, &s); pt.set_gej(&res); pt.x.normalize(); pt.y.normalize(); let x = pt.x.b32(); let y = 0x02 | (if pt.y.is_odd() { 1 } else { 0 }); digest.update(&[y]); digest.update(&x); Some(digest.finalize_reset()) } } ================================================ FILE: core/src/ecdsa.rs ================================================ use crate::{ ecmult::{ECMultContext, ECMultGenContext}, field::Field, group::{Affine, Jacobian}, scalar::Scalar, Error, }; const P_MINUS_ORDER: Field = Field::new(0, 0, 0, 1, 0x45512319, 0x50B75FC4, 0x402DA172, 0x2FC9BAEE); const ORDER_AS_FE: Field = Field::new( 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xBAAEDCE6, 0xAF48A03B, 0xBFD25E8C, 0xD0364141, ); impl ECMultContext { pub fn verify_raw( &self, sigr: &Scalar, sigs: &Scalar, pubkey: &Affine, message: &Scalar, ) -> bool { let c; let (sn, u1, u2): (Scalar, Scalar, Scalar); if sigr.is_zero() || sigs.is_zero() { return false; } sn = sigs.inv_var(); u1 = &sn * message; u2 = &sn * sigr; let mut pubkeyj: Jacobian = Jacobian::default(); pubkeyj.set_ge(pubkey); let mut pr: Jacobian = Jacobian::default(); self.ecmult(&mut pr, &pubkeyj, &u2, &u1); if pr.is_infinity() { return false; } c = sigr.b32(); let mut xr: Field = Default::default(); let _ = xr.set_b32(&c); if pr.eq_x_var(&xr) { return true; } if xr >= P_MINUS_ORDER { return false; } xr += ORDER_AS_FE; if pr.eq_x_var(&xr) { return true; } false } pub fn recover_raw( &self, sigr: &Scalar, sigs: &Scalar, rec_id: u8, message: &Scalar, ) -> Result { debug_assert!(rec_id < 4); if sigr.is_zero() || sigs.is_zero() { return Err(Error::InvalidSignature); } let brx = sigr.b32(); let mut fx = Field::default(); let overflow = fx.set_b32(&brx); debug_assert!(overflow); if rec_id & 2 > 0 { if fx >= P_MINUS_ORDER { return Err(Error::InvalidSignature); } fx += ORDER_AS_FE; } let mut x = Affine::default(); if !x.set_xo_var(&fx, rec_id & 1 > 0) { return Err(Error::InvalidSignature); } let mut xj = Jacobian::default(); xj.set_ge(&x); let rn = sigr.inv(); let mut u1 = &rn * message; u1 = -u1; let u2 = &rn * sigs; let mut qj = Jacobian::default(); self.ecmult(&mut qj, &xj, &u2, &u1); let mut pubkey = Affine::default(); pubkey.set_gej_var(&qj); if pubkey.is_infinity() { Err(Error::InvalidSignature) } else { Ok(pubkey) } } } impl ECMultGenContext { pub fn sign_raw( &self, seckey: &Scalar, message: &Scalar, nonce: &Scalar, ) -> Result<(Scalar, Scalar, u8), Error> { let mut rp = Jacobian::default(); self.ecmult_gen(&mut rp, nonce); let mut r = Affine::default(); r.set_gej(&rp); r.x.normalize(); r.y.normalize(); let b = r.x.b32(); let mut sigr = Scalar::default(); let overflow = bool::from(sigr.set_b32(&b)); debug_assert!(!sigr.is_zero()); debug_assert!(!overflow); let mut recid = (if overflow { 2 } else { 0 }) | (if r.y.is_odd() { 1 } else { 0 }); let mut n = &sigr * seckey; n += message; let mut sigs = nonce.inv(); sigs *= &n; n.clear(); rp.clear(); r.clear(); if sigs.is_zero() { return Err(Error::InvalidMessage); } if sigs.is_high() { sigs = -sigs; recid ^= 1; } Ok((sigr, sigs, recid)) } } ================================================ FILE: core/src/ecmult.rs ================================================ use crate::{ field::Field, group::{globalz_set_table_gej, set_table_gej_var, Affine, AffineStorage, Jacobian, AFFINE_G}, scalar::Scalar, }; use alloc::{ alloc::{alloc, Layout}, boxed::Box, vec, vec::Vec, }; use subtle::Choice; pub const WINDOW_A: usize = 5; pub const WINDOW_G: usize = 16; pub const ECMULT_TABLE_SIZE_A: usize = 1 << (WINDOW_A - 2); pub const ECMULT_TABLE_SIZE_G: usize = 1 << (WINDOW_G - 2); pub const WNAF_BITS: usize = 256; fn odd_multiples_table_storage_var(pre: &mut [AffineStorage], a: &Jacobian) { let mut prej: Vec = Vec::with_capacity(pre.len()); for _ in 0..pre.len() { prej.push(Jacobian::default()); } let mut prea: Vec = Vec::with_capacity(pre.len()); for _ in 0..pre.len() { prea.push(Affine::default()); } let mut zr: Vec = Vec::with_capacity(pre.len()); for _ in 0..pre.len() { zr.push(Field::default()); } odd_multiples_table(&mut prej, &mut zr, a); set_table_gej_var(&mut prea, &prej, &zr); for i in 0..pre.len() { pre[i] = prea[i].into(); } } /// Context for accelerating the computation of a*P + b*G. pub struct ECMultContext { pre_g: [AffineStorage; ECMULT_TABLE_SIZE_G], } impl ECMultContext { /// Create a new `ECMultContext` from raw values. /// /// # Safety /// The function is unsafe because incorrect value of `pre_g` can lead to /// crypto logic failure. You most likely do not want to use this function, /// but `ECMultContext::new_boxed`. pub const unsafe fn new_from_raw(pre_g: [AffineStorage; ECMULT_TABLE_SIZE_G]) -> Self { Self { pre_g } } /// Inspect raw values of `ECMultContext`. pub fn inspect_raw(&self) -> &[AffineStorage; ECMULT_TABLE_SIZE_G] { &self.pre_g } /// Generate a new `ECMultContext` on the heap. Note that this function is expensive. pub fn new_boxed() -> Box { // This unsafe block allocates a new, unitialized `ECMultContext` and // then fills in the value. This is to avoid allocating it on stack // because the struct is big. All values in `ECMultContext` are manually // initialized after allocation. let mut this = unsafe { let ptr = alloc(Layout::new::()) as *mut ECMultContext; let mut this = Box::from_raw(ptr); for i in 0..ECMULT_TABLE_SIZE_G { this.pre_g[i] = AffineStorage::default(); } this }; let mut gj = Jacobian::default(); gj.set_ge(&AFFINE_G); odd_multiples_table_storage_var(&mut this.pre_g, &gj); this } } /// Set a batch of group elements equal to the inputs given in jacobian /// coordinates. Not constant time. pub fn set_all_gej_var(a: &[Jacobian]) -> Vec { let mut az: Vec = Vec::with_capacity(a.len()); for point in a { if !point.is_infinity() { az.push(point.z); } } let azi: Vec = inv_all_var(&az); let mut ret = vec![Affine::default(); a.len()]; let mut count = 0; for i in 0..a.len() { ret[i].infinity = a[i].infinity; if !a[i].is_infinity() { ret[i].set_gej_zinv(&a[i], &azi[count]); count += 1; } } ret } /// Calculate the (modular) inverses of a batch of field /// elements. Requires the inputs' magnitudes to be at most 8. The /// output magnitudes are 1 (but not guaranteed to be /// normalized). pub fn inv_all_var(fields: &[Field]) -> Vec { if fields.is_empty() { return Vec::new(); } let mut ret = Vec::with_capacity(fields.len()); ret.push(fields[0]); for i in 1..fields.len() { ret.push(Field::default()); ret[i] = ret[i - 1] * fields[i]; } let mut u = ret[fields.len() - 1].inv_var(); for i in (1..fields.len()).rev() { let j = i; let i = i - 1; ret[j] = ret[i] * u; u *= fields[j]; } ret[0] = u; ret } const GEN_BLIND: Scalar = Scalar([ 2217680822, 850875797, 1046150361, 1330484644, 4015777837, 2466086288, 2052467175, 2084507480, ]); const GEN_INITIAL: Jacobian = Jacobian { x: Field::new_raw( 586608, 43357028, 207667908, 262670128, 142222828, 38529388, 267186148, 45417712, 115291924, 13447464, ), y: Field::new_raw( 12696548, 208302564, 112025180, 191752716, 143238548, 145482948, 228906000, 69755164, 243572800, 210897016, ), z: Field::new_raw( 3685368, 75404844, 20246216, 5748944, 73206666, 107661790, 110806176, 73488774, 5707384, 104448710, ), infinity: false, }; /// Context for accelerating the computation of a*G. pub struct ECMultGenContext { prec: [[AffineStorage; 16]; 64], blind: Scalar, initial: Jacobian, } impl ECMultGenContext { /// Create a new `ECMultGenContext` from raw values. /// /// # Safety /// The function is unsafe because incorrect value of `pre_g` can lead to /// crypto logic failure. You most likely do not want to use this function, /// but `ECMultGenContext::new_boxed`. pub const unsafe fn new_from_raw(prec: [[AffineStorage; 16]; 64]) -> Self { Self { prec, blind: GEN_BLIND, initial: GEN_INITIAL, } } /// Inspect `ECMultGenContext` values. pub fn inspect_raw(&self) -> &[[AffineStorage; 16]; 64] { &self.prec } /// Generate a new `ECMultGenContext` on the heap. Note that this function is expensive. pub fn new_boxed() -> Box { // This unsafe block allocates a new, unitialized `ECMultGenContext` and // then fills in the value. This is to avoid allocating it on stack // because the struct is big. All values in `ECMultGenContext` are // manually initialized after allocation. let mut this = unsafe { let ptr = alloc(Layout::new::()) as *mut ECMultGenContext; let mut this = Box::from_raw(ptr); for j in 0..64 { for i in 0..16 { this.prec[j][i] = AffineStorage::default(); } } this.blind = GEN_BLIND; this.initial = GEN_INITIAL; this }; let mut gj = Jacobian::default(); gj.set_ge(&AFFINE_G); // Construct a group element with no known corresponding scalar (nothing up my sleeve). let mut nums_32 = [0u8; 32]; debug_assert!(b"The scalar for this x is unknown".len() == 32); for (i, v) in b"The scalar for this x is unknown".iter().enumerate() { nums_32[i] = *v; } let mut nums_x = Field::default(); assert!(nums_x.set_b32(&nums_32)); let mut nums_ge = Affine::default(); assert!(nums_ge.set_xo_var(&nums_x, false)); let mut nums_gej = Jacobian::default(); nums_gej.set_ge(&nums_ge); nums_gej = nums_gej.add_ge_var(&AFFINE_G, None); // Compute prec. let mut precj: Vec = Vec::with_capacity(1024); for _ in 0..1024 { precj.push(Jacobian::default()); } let mut gbase = gj; let mut numsbase = nums_gej; for j in 0..64 { precj[j * 16] = numsbase; for i in 1..16 { precj[j * 16 + i] = precj[j * 16 + i - 1].add_var(&gbase, None); } for _ in 0..4 { gbase = gbase.double_var(None); } numsbase = numsbase.double_var(None); if j == 62 { numsbase = numsbase.neg(); numsbase = numsbase.add_var(&nums_gej, None); } } let prec = set_all_gej_var(&precj); for j in 0..64 { for i in 0..16 { let pg: AffineStorage = prec[j * 16 + i].into(); this.prec[j][i] = pg; } } this } } pub fn odd_multiples_table(prej: &mut [Jacobian], zr: &mut [Field], a: &Jacobian) { debug_assert!(prej.len() == zr.len()); debug_assert!(!prej.is_empty()); debug_assert!(!a.is_infinity()); let d = a.double_var(None); let d_ge = Affine { x: d.x, y: d.y, infinity: false, }; let mut a_ge = Affine::default(); a_ge.set_gej_zinv(a, &d.z); prej[0].x = a_ge.x; prej[0].y = a_ge.y; prej[0].z = a.z; prej[0].infinity = false; zr[0] = d.z; for i in 1..prej.len() { prej[i] = prej[i - 1].add_ge_var(&d_ge, Some(&mut zr[i])); } let l = prej.last().unwrap().z * d.z; prej.last_mut().unwrap().z = l; } fn odd_multiples_table_globalz_windowa( pre: &mut [Affine; ECMULT_TABLE_SIZE_A], globalz: &mut Field, a: &Jacobian, ) { let mut prej: [Jacobian; ECMULT_TABLE_SIZE_A] = Default::default(); let mut zr: [Field; ECMULT_TABLE_SIZE_A] = Default::default(); odd_multiples_table(&mut prej, &mut zr, a); globalz_set_table_gej(pre, globalz, &prej, &zr); } fn table_get_ge(r: &mut Affine, pre: &[Affine], n: i32, w: usize) { debug_assert!(n & 1 == 1); debug_assert!(n >= -((1 << (w - 1)) - 1)); debug_assert!(n <= ((1 << (w - 1)) - 1)); if n > 0 { *r = pre[((n - 1) / 2) as usize]; } else { *r = pre[((-n - 1) / 2) as usize].neg(); } } fn table_get_ge_const(r: &mut Affine, pre: &[Affine], n: i32, w: usize) { let abs_n = n * (if n > 0 { 1 } else { 0 } * 2 - 1); let idx_n = abs_n / 2; debug_assert!(n & 1 == 1); debug_assert!(n >= -((1 << (w - 1)) - 1)); debug_assert!(n <= ((1 << (w - 1)) - 1)); for m in 0..pre.len() { let flag = m == idx_n as usize; r.x.cmov(&pre[m].x, flag); r.y.cmov(&pre[m].y, flag); } r.infinity = false; let neg_y = r.y.neg(1); r.y.cmov(&neg_y, n != abs_n); } fn table_get_ge_storage(r: &mut Affine, pre: &[AffineStorage], n: i32, w: usize) { debug_assert!(n & 1 == 1); debug_assert!(n >= -((1 << (w - 1)) - 1)); debug_assert!(n <= ((1 << (w - 1)) - 1)); if n > 0 { *r = pre[((n - 1) / 2) as usize].into(); } else { *r = pre[((-n - 1) / 2) as usize].into(); *r = r.neg(); } } pub fn ecmult_wnaf(wnaf: &mut [i32], a: &Scalar, w: usize) -> i32 { let mut s = *a; let mut last_set_bit: i32 = -1; let mut bit = 0; let mut sign = 1; let mut carry = 0; debug_assert!(wnaf.len() <= 256); debug_assert!(w >= 2 && w <= 31); for i in 0..wnaf.len() { wnaf[i] = 0; } if s.bits(255, 1) > 0 { s = -s; sign = -1; } while bit < wnaf.len() { let mut now; let mut word; if s.bits(bit, 1) == carry as u32 { bit += 1; continue; } now = w; if now > wnaf.len() - bit { now = wnaf.len() - bit; } word = (s.bits_var(bit, now) as i32) + carry; carry = (word >> (w - 1)) & 1; word -= carry << w; wnaf[bit] = sign * word; last_set_bit = bit as i32; bit += now; } debug_assert!(carry == 0); debug_assert!({ let mut t = true; while bit < 256 { t = t && (s.bits(bit, 1) == 0); bit += 1; } t }); last_set_bit + 1 } pub fn ecmult_wnaf_const(wnaf: &mut [i32], a: &Scalar, w: usize) -> i32 { let mut s = *a; let mut word = 0; /* Note that we cannot handle even numbers by negating them to be * odd, as is done in other implementations, since if our scalars * were specified to have width < 256 for performance reasons, * their negations would have width 256 and we'd lose any * performance benefit. Instead, we use a technique from Section * 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for * even) or 2 (for odd) to the number we are encoding, returning a * skew value indicating this, and having the caller compensate * after doing the multiplication. */ /* Negative numbers will be negated to keep their bit * representation below the maximum width */ let flip = s.is_high(); /* We add 1 to even numbers, 2 to odd ones, noting that negation * flips parity */ let bit = flip ^ !s.is_even(); /* We add 1 to even numbers, 2 to odd ones, noting that negation * flips parity */ let neg_s = -s; let not_neg_one = !neg_s.is_one(); s.cadd_bit(if bit { 1 } else { 0 }, not_neg_one); /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so * caller expects that we added two to it and flipped it. In fact * for -1 these operations are identical. We only flipped, but * since skewing is required (in the sense that the skew must be 1 * or 2, never zero) and flipping is not, we need to change our * flags to claim that we only skewed. */ let mut global_sign = if flip { -1 } else { 1 }; s.cond_neg_assign(Choice::from(flip as u8)); global_sign *= if not_neg_one { 1 } else { 0 } * 2 - 1; let skew = 1 << (if bit { 1 } else { 0 }); let mut u_last: i32 = s.shr_int(w) as i32; let mut u: i32 = 0; while word * w < WNAF_BITS { u = s.shr_int(w) as i32; let even = (u & 1) == 0; let sign = 2 * (if u_last > 0 { 1 } else { 0 }) - 1; u += sign * if even { 1 } else { 0 }; u_last -= sign * if even { 1 } else { 0 } * (1 << w); wnaf[word] = (u_last as i32 * global_sign as i32) as i32; word += 1; u_last = u; } wnaf[word] = u * global_sign as i32; debug_assert!(s.is_zero()); let wnaf_size = (WNAF_BITS + w - 1) / w; debug_assert!(word == wnaf_size); skew } impl ECMultContext { pub fn ecmult(&self, r: &mut Jacobian, a: &Jacobian, na: &Scalar, ng: &Scalar) { let mut tmpa = Affine::default(); let mut pre_a: [Affine; ECMULT_TABLE_SIZE_A] = Default::default(); let mut z = Field::default(); let mut wnaf_na = [0i32; 256]; let mut wnaf_ng = [0i32; 256]; let bits_na = ecmult_wnaf(&mut wnaf_na, na, WINDOW_A); let mut bits = bits_na; odd_multiples_table_globalz_windowa(&mut pre_a, &mut z, a); let bits_ng = ecmult_wnaf(&mut wnaf_ng, &ng, WINDOW_G); if bits_ng > bits { bits = bits_ng; } r.set_infinity(); for i in (0..bits).rev() { let mut n; *r = r.double_var(None); n = wnaf_na[i as usize]; if i < bits_na && n != 0 { table_get_ge(&mut tmpa, &pre_a, n, WINDOW_A); *r = r.add_ge_var(&tmpa, None); } n = wnaf_ng[i as usize]; if i < bits_ng && n != 0 { table_get_ge_storage(&mut tmpa, &self.pre_g, n, WINDOW_G); *r = r.add_zinv_var(&tmpa, &z); } } if !r.is_infinity() { r.z *= &z; } } pub fn ecmult_const(&self, r: &mut Jacobian, a: &Affine, scalar: &Scalar) { const WNAF_SIZE: usize = (WNAF_BITS + (WINDOW_A - 1) - 1) / (WINDOW_A - 1); let mut tmpa = Affine::default(); let mut pre_a: [Affine; ECMULT_TABLE_SIZE_A] = Default::default(); let mut z = Field::default(); let mut wnaf_1 = [0i32; 1 + WNAF_SIZE]; let sc = *scalar; let skew_1 = ecmult_wnaf_const(&mut wnaf_1, &sc, WINDOW_A - 1); /* Calculate odd multiples of a. All multiples are brought to * the same Z 'denominator', which is stored in Z. Due to * secp256k1' isomorphism we can do all operations pretending * that the Z coordinate was 1, use affine addition formulae, * and correct the Z coordinate of the result once at the end. */ r.set_ge(a); odd_multiples_table_globalz_windowa(&mut pre_a, &mut z, r); for i in 0..ECMULT_TABLE_SIZE_A { pre_a[i].y.normalize_weak(); } /* first loop iteration (separated out so we can directly set * r, rather than having it start at infinity, get doubled * several times, then have its new value added to it) */ let i = wnaf_1[WNAF_SIZE]; debug_assert!(i != 0); table_get_ge_const(&mut tmpa, &pre_a, i, WINDOW_A); r.set_ge(&tmpa); /* remaining loop iterations */ for i in (0..WNAF_SIZE).rev() { for _ in 0..(WINDOW_A - 1) { let r2 = *r; r.double_nonzero_in_place(&r2, None); } let n = wnaf_1[i]; table_get_ge_const(&mut tmpa, &pre_a, n, WINDOW_A); debug_assert!(n != 0); *r = r.add_ge(&tmpa); } r.z *= &z; /* Correct for wNAF skew */ let mut correction = *a; let mut correction_1_stor: AffineStorage; let a2_stor: AffineStorage; let mut tmpj = Jacobian::default(); tmpj.set_ge(&correction); tmpj = tmpj.double_var(None); correction.set_gej(&tmpj); correction_1_stor = (*a).into(); a2_stor = correction.into(); /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ correction_1_stor.cmov(&a2_stor, skew_1 == 2); /* Apply the correction */ correction = correction_1_stor.into(); correction = correction.neg(); *r = r.add_ge(&correction) } } impl ECMultGenContext { pub fn ecmult_gen(&self, r: &mut Jacobian, gn: &Scalar) { let mut adds = AffineStorage::default(); *r = self.initial; let mut gnb = gn + &self.blind; let mut add = Affine::default(); add.infinity = false; for j in 0..64 { let mut bits = gnb.bits(j * 4, 4); for i in 0..16 { adds.cmov(&self.prec[j][i], i as u32 == bits); } add = adds.into(); *r = r.add_ge(&add); #[allow(unused_assignments)] { bits = 0; } } add.clear(); gnb.clear(); } } ================================================ FILE: core/src/error.rs ================================================ #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum Error { InvalidSignature, InvalidPublicKey, InvalidSecretKey, InvalidRecoveryId, InvalidMessage, InvalidInputLength, TweakOutOfRange, InvalidAffine, } #[cfg(feature = "std")] impl std::error::Error for Error {} impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Error::InvalidSignature => write!(f, "Invalid signature"), Error::InvalidPublicKey => write!(f, "Invalid public key"), Error::InvalidSecretKey => write!(f, "Invalid secret key"), Error::InvalidRecoveryId => write!(f, "Invalid recovery ID"), Error::InvalidMessage => write!(f, "Invalid message"), Error::InvalidInputLength => write!(f, "Invalid input length"), Error::TweakOutOfRange => write!(f, "Tweak out of range"), Error::InvalidAffine => write!(f, "Invalid Affine"), } } } ================================================ FILE: core/src/field.rs ================================================ use core::{ cmp::Ordering, ops::{Add, AddAssign, Mul, MulAssign}, }; macro_rules! debug_assert_bits { ($x: expr, $n: expr) => { debug_assert!($x >> $n == 0); }; } #[derive(Debug, Clone, Copy)] /// Field element for secp256k1. pub struct Field { /// Store representation of X. /// X = sum(i=0..9, n[i]*2^(i*26)) mod p /// where p = 2^256 - 0x1000003D1 /// /// The least signifiant byte is in the front. n: [u32; 10], magnitude: u32, normalized: bool, } impl Field { pub const fn new_raw( d9: u32, d8: u32, d7: u32, d6: u32, d5: u32, d4: u32, d3: u32, d2: u32, d1: u32, d0: u32, ) -> Self { Self { n: [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], magnitude: 1, normalized: false, } } pub const fn new( d7: u32, d6: u32, d5: u32, d4: u32, d3: u32, d2: u32, d1: u32, d0: u32, ) -> Self { Self { n: [ d0 & 0x3ffffff, (d0 >> 26) | ((d1 & 0xfffff) << 6), (d1 >> 20) | ((d2 & 0x3fff) << 12), (d2 >> 14) | ((d3 & 0xff) << 18), (d3 >> 8) | ((d4 & 0x3) << 24), (d4 >> 2) & 0x3ffffff, (d4 >> 28) | ((d5 & 0x3fffff) << 4), (d5 >> 22) | ((d6 & 0xffff) << 10), (d6 >> 16) | ((d7 & 0x3ff) << 16), (d7 >> 10), ], magnitude: 1, normalized: true, } } pub fn from_int(a: u32) -> Field { let mut f = Field::default(); f.set_int(a); f } fn verify(&self) -> bool { let m = if self.normalized { 1 } else { 2 } * self.magnitude; let mut r = true; r = r && (self.n[0] <= 0x3ffffff * m); r = r && (self.n[1] <= 0x3ffffff * m); r = r && (self.n[2] <= 0x3ffffff * m); r = r && (self.n[3] <= 0x3ffffff * m); r = r && (self.n[4] <= 0x3ffffff * m); r = r && (self.n[5] <= 0x3ffffff * m); r = r && (self.n[6] <= 0x3ffffff * m); r = r && (self.n[7] <= 0x3ffffff * m); r = r && (self.n[8] <= 0x3ffffff * m); r = r && (self.n[9] <= 0x03fffff * m); r = r && (self.magnitude <= 32); if self.normalized { r = r && self.magnitude <= 1; if r && (self.n[9] == 0x03fffff) { let mid = self.n[8] & self.n[7] & self.n[6] & self.n[5] & self.n[4] & self.n[3] & self.n[2]; if mid == 0x3ffffff { r = r && ((self.n[1] + 0x40 + ((self.n[0] + 0x3d1) >> 26)) <= 0x3ffffff) } } } r } /// Normalize a field element. pub fn normalize(&mut self) { let mut t0 = self.n[0]; let mut t1 = self.n[1]; let mut t2 = self.n[2]; let mut t3 = self.n[3]; let mut t4 = self.n[4]; let mut t5 = self.n[5]; let mut t6 = self.n[6]; let mut t7 = self.n[7]; let mut t8 = self.n[8]; let mut t9 = self.n[9]; let mut m: u32; let mut x = t9 >> 22; t9 &= 0x03fffff; t0 += x * 0x3d1; t1 += x << 6; t1 += t0 >> 26; t0 &= 0x3ffffff; t2 += t1 >> 26; t1 &= 0x3ffffff; t3 += t2 >> 26; t2 &= 0x3ffffff; m = t2; t4 += t3 >> 26; t3 &= 0x3ffffff; m &= t3; t5 += t4 >> 26; t4 &= 0x3ffffff; m &= t4; t6 += t5 >> 26; t5 &= 0x3ffffff; m &= t5; t7 += t6 >> 26; t6 &= 0x3ffffff; m &= t6; t8 += t7 >> 26; t7 &= 0x3ffffff; m &= t7; t9 += t8 >> 26; t8 &= 0x3ffffff; m &= t8; debug_assert!(t9 >> 23 == 0); x = (t9 >> 22) | (if t9 == 0x03fffff { 1 } else { 0 } & if m == 0x3ffffff { 1 } else { 0 } & (if (t1 + 0x40 + ((t0 + 0x3d1) >> 26)) > 0x3ffffff { 1 } else { 0 })); t0 += x * 0x3d1; t1 += x << 6; t1 += t0 >> 26; t0 &= 0x3ffffff; t2 += t1 >> 26; t1 &= 0x3ffffff; t3 += t2 >> 26; t2 &= 0x3ffffff; t4 += t3 >> 26; t3 &= 0x3ffffff; t5 += t4 >> 26; t4 &= 0x3ffffff; t6 += t5 >> 26; t5 &= 0x3ffffff; t7 += t6 >> 26; t6 &= 0x3ffffff; t8 += t7 >> 26; t7 &= 0x3ffffff; t9 += t8 >> 26; t8 &= 0x3ffffff; debug_assert!(t9 >> 22 == x); t9 &= 0x03fffff; self.n = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9]; self.magnitude = 1; self.normalized = true; debug_assert!(self.verify()); } /// Weakly normalize a field element: reduce it magnitude to 1, /// but don't fully normalize. pub fn normalize_weak(&mut self) { let mut t0 = self.n[0]; let mut t1 = self.n[1]; let mut t2 = self.n[2]; let mut t3 = self.n[3]; let mut t4 = self.n[4]; let mut t5 = self.n[5]; let mut t6 = self.n[6]; let mut t7 = self.n[7]; let mut t8 = self.n[8]; let mut t9 = self.n[9]; let x = t9 >> 22; t9 &= 0x03fffff; t0 += x * 0x3d1; t1 += x << 6; t1 += t0 >> 26; t0 &= 0x3ffffff; t2 += t1 >> 26; t1 &= 0x3ffffff; t3 += t2 >> 26; t2 &= 0x3ffffff; t4 += t3 >> 26; t3 &= 0x3ffffff; t5 += t4 >> 26; t4 &= 0x3ffffff; t6 += t5 >> 26; t5 &= 0x3ffffff; t7 += t6 >> 26; t6 &= 0x3ffffff; t8 += t7 >> 26; t7 &= 0x3ffffff; t9 += t8 >> 26; t8 &= 0x3ffffff; debug_assert!(t9 >> 23 == 0); self.n = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9]; self.magnitude = 1; debug_assert!(self.verify()); } /// Normalize a field element, without constant-time guarantee. pub fn normalize_var(&mut self) { let mut t0 = self.n[0]; let mut t1 = self.n[1]; let mut t2 = self.n[2]; let mut t3 = self.n[3]; let mut t4 = self.n[4]; let mut t5 = self.n[5]; let mut t6 = self.n[6]; let mut t7 = self.n[7]; let mut t8 = self.n[8]; let mut t9 = self.n[9]; let mut m: u32; let mut x = t9 >> 22; t9 &= 0x03fffff; t0 += x * 0x3d1; t1 += x << 6; t1 += t0 >> 26; t0 &= 0x3ffffff; t2 += t1 >> 26; t1 &= 0x3ffffff; t3 += t2 >> 26; t2 &= 0x3ffffff; m = t2; t4 += t3 >> 26; t3 &= 0x3ffffff; m &= t3; t5 += t4 >> 26; t4 &= 0x3ffffff; m &= t4; t6 += t5 >> 26; t5 &= 0x3ffffff; m &= t5; t7 += t6 >> 26; t6 &= 0x3ffffff; m &= t6; t8 += t7 >> 26; t7 &= 0x3ffffff; m &= t7; t9 += t8 >> 26; t8 &= 0x3ffffff; m &= t8; debug_assert!(t9 >> 23 == 0); x = (t9 >> 22) | (if t9 == 0x03fffff { 1 } else { 0 } & if m == 0x3ffffff { 1 } else { 0 } & (if (t1 + 0x40 + ((t0 + 0x3d1) >> 26)) > 0x3ffffff { 1 } else { 0 })); if x > 0 { t0 += 0x3d1; t1 += x << 6; t1 += t0 >> 26; t0 &= 0x3ffffff; t2 += t1 >> 26; t1 &= 0x3ffffff; t3 += t2 >> 26; t2 &= 0x3ffffff; t4 += t3 >> 26; t3 &= 0x3ffffff; t5 += t4 >> 26; t4 &= 0x3ffffff; t6 += t5 >> 26; t5 &= 0x3ffffff; t7 += t6 >> 26; t6 &= 0x3ffffff; t8 += t7 >> 26; t7 &= 0x3ffffff; t9 += t8 >> 26; t8 &= 0x3ffffff; debug_assert!(t9 >> 22 == x); t9 &= 0x03fffff; } self.n = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9]; self.magnitude = 1; self.normalized = true; debug_assert!(self.verify()); } /// Verify whether a field element represents zero i.e. would /// normalize to a zero value. The field implementation may /// optionally normalize the input, but this should not be relied /// upon. pub fn normalizes_to_zero(&self) -> bool { let mut t0 = self.n[0]; let mut t1 = self.n[1]; let mut t2 = self.n[2]; let mut t3 = self.n[3]; let mut t4 = self.n[4]; let mut t5 = self.n[5]; let mut t6 = self.n[6]; let mut t7 = self.n[7]; let mut t8 = self.n[8]; let mut t9 = self.n[9]; let mut z0: u32; let mut z1: u32; let x = t9 >> 22; t9 &= 0x03fffff; t0 += x * 0x3d1; t1 += x << 6; t1 += t0 >> 26; t0 &= 0x3ffffff; z0 = t0; z1 = t0 ^ 0x3d0; t2 += t1 >> 26; t1 &= 0x3ffffff; z0 |= t1; z1 &= t1 ^ 0x40; t3 += t2 >> 26; t2 &= 0x3ffffff; z0 |= t2; z1 &= t2; t4 += t3 >> 26; t3 &= 0x3ffffff; z0 |= t3; z1 &= t3; t5 += t4 >> 26; t4 &= 0x3ffffff; z0 |= t4; z1 &= t4; t6 += t5 >> 26; t5 &= 0x3ffffff; z0 |= t5; z1 &= t5; t7 += t6 >> 26; t6 &= 0x3ffffff; z0 |= t6; z1 &= t6; t8 += t7 >> 26; t7 &= 0x3ffffff; z0 |= t7; z1 &= t7; t9 += t8 >> 26; t8 &= 0x3ffffff; z0 |= t8; z1 &= t8; z0 |= t9; z1 &= t9 ^ 0x3c00000; debug_assert!(t9 >> 23 == 0); z0 == 0 || z1 == 0x3ffffff } /// Verify whether a field element represents zero i.e. would /// normalize to a zero value. The field implementation may /// optionally normalize the input, but this should not be relied /// upon. pub fn normalizes_to_zero_var(&self) -> bool { let mut t0: u32; let mut t1: u32; let mut t2: u32; let mut t3: u32; let mut t4: u32; let mut t5: u32; let mut t6: u32; let mut t7: u32; let mut t8: u32; let mut t9: u32; let mut z0: u32; let mut z1: u32; let x: u32; t0 = self.n[0]; t9 = self.n[9]; x = t9 >> 22; t0 += x * 0x3d1; z0 = t0 & 0x3ffffff; z1 = z0 ^ 0x3d0; if z0 != 0 && z1 != 0x3ffffff { return false; } t1 = self.n[1]; t2 = self.n[2]; t3 = self.n[3]; t4 = self.n[4]; t5 = self.n[5]; t6 = self.n[6]; t7 = self.n[7]; t8 = self.n[8]; t9 &= 0x03fffff; t1 += x << 6; t1 += t0 >> 26; t2 += t1 >> 26; t1 &= 0x3ffffff; z0 |= t1; z1 &= t1 ^ 0x40; t3 += t2 >> 26; t2 &= 0x3ffffff; z0 |= t2; z1 &= t2; t4 += t3 >> 26; t3 &= 0x3ffffff; z0 |= t3; z1 &= t3; t5 += t4 >> 26; t4 &= 0x3ffffff; z0 |= t4; z1 &= t4; t6 += t5 >> 26; t5 &= 0x3ffffff; z0 |= t5; z1 &= t5; t7 += t6 >> 26; t6 &= 0x3ffffff; z0 |= t6; z1 &= t6; t8 += t7 >> 26; t7 &= 0x3ffffff; z0 |= t7; z1 &= t7; t9 += t8 >> 26; t8 &= 0x3ffffff; z0 |= t8; z1 &= t8; z0 |= t9; z1 &= t9 ^ 0x3c00000; debug_assert!(t9 >> 23 == 0); z0 == 0 || z1 == 0x3ffffff } /// Set a field element equal to a small integer. Resulting field /// element is normalized. pub fn set_int(&mut self, a: u32) { self.n = [a, 0, 0, 0, 0, 0, 0, 0, 0, 0]; self.magnitude = 1; self.normalized = true; debug_assert!(self.verify()); } /// Verify whether a field element is zero. Requires the input to /// be normalized. pub fn is_zero(&self) -> bool { debug_assert!(self.normalized); debug_assert!(self.verify()); (self.n[0] | self.n[1] | self.n[2] | self.n[3] | self.n[4] | self.n[5] | self.n[6] | self.n[7] | self.n[8] | self.n[9]) == 0 } /// Check the "oddness" of a field element. Requires the input to /// be normalized. pub fn is_odd(&self) -> bool { debug_assert!(self.normalized); debug_assert!(self.verify()); self.n[0] & 1 != 0 } /// Sets a field element equal to zero, initializing all fields. pub fn clear(&mut self) { self.magnitude = 0; self.normalized = true; self.n = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; } /// Set a field element equal to 32-byte big endian value. If /// successful, the resulting field element is normalized. #[must_use] pub fn set_b32(&mut self, a: &[u8; 32]) -> bool { self.n[0] = (a[31] as u32) | ((a[30] as u32) << 8) | ((a[29] as u32) << 16) | (((a[28] & 0x3) as u32) << 24); self.n[1] = (((a[28] >> 2) & 0x3f) as u32) | ((a[27] as u32) << 6) | ((a[26] as u32) << 14) | (((a[25] & 0xf) as u32) << 22); self.n[2] = (((a[25] >> 4) & 0xf) as u32) | ((a[24] as u32) << 4) | ((a[23] as u32) << 12) | (((a[22] as u32) & 0x3f) << 20); self.n[3] = (((a[22] >> 6) & 0x3) as u32) | ((a[21] as u32) << 2) | ((a[20] as u32) << 10) | ((a[19] as u32) << 18); self.n[4] = (a[18] as u32) | ((a[17] as u32) << 8) | ((a[16] as u32) << 16) | (((a[15] & 0x3) as u32) << 24); self.n[5] = (((a[15] >> 2) & 0x3f) as u32) | ((a[14] as u32) << 6) | ((a[13] as u32) << 14) | (((a[12] as u32) & 0xf) << 22); self.n[6] = (((a[12] >> 4) & 0xf) as u32) | ((a[11] as u32) << 4) | ((a[10] as u32) << 12) | (((a[9] & 0x3f) as u32) << 20); self.n[7] = (((a[9] >> 6) & 0x3) as u32) | ((a[8] as u32) << 2) | ((a[7] as u32) << 10) | ((a[6] as u32) << 18); self.n[8] = (a[5] as u32) | ((a[4] as u32) << 8) | ((a[3] as u32) << 16) | (((a[2] & 0x3) as u32) << 24); self.n[9] = (((a[2] >> 2) & 0x3f) as u32) | ((a[1] as u32) << 6) | ((a[0] as u32) << 14); if self.n[9] == 0x03fffff && (self.n[8] & self.n[7] & self.n[6] & self.n[5] & self.n[4] & self.n[3] & self.n[2]) == 0x3ffffff && (self.n[1] + 0x40 + ((self.n[0] + 0x3d1) >> 26)) > 0x3ffffff { return false; } self.magnitude = 1; self.normalized = true; debug_assert!(self.verify()); true } pub fn fill_b32(&self, r: &mut [u8; 32]) { debug_assert!(self.normalized); debug_assert!(self.verify()); r[0] = ((self.n[9] >> 14) & 0xff) as u8; r[1] = ((self.n[9] >> 6) & 0xff) as u8; r[2] = (((self.n[9] & 0x3f) << 2) | ((self.n[8] >> 24) & 0x3)) as u8; r[3] = ((self.n[8] >> 16) & 0xff) as u8; r[4] = ((self.n[8] >> 8) & 0xff) as u8; r[5] = (self.n[8] & 0xff) as u8; r[6] = ((self.n[7] >> 18) & 0xff) as u8; r[7] = ((self.n[7] >> 10) & 0xff) as u8; r[8] = ((self.n[7] >> 2) & 0xff) as u8; r[9] = (((self.n[7] & 0x3) << 6) | ((self.n[6] >> 20) & 0x3f)) as u8; r[10] = ((self.n[6] >> 12) & 0xff) as u8; r[11] = ((self.n[6] >> 4) & 0xff) as u8; r[12] = (((self.n[6] & 0xf) << 4) | ((self.n[5] >> 22) & 0xf)) as u8; r[13] = ((self.n[5] >> 14) & 0xff) as u8; r[14] = ((self.n[5] >> 6) & 0xff) as u8; r[15] = (((self.n[5] & 0x3f) << 2) | ((self.n[4] >> 24) & 0x3)) as u8; r[16] = ((self.n[4] >> 16) & 0xff) as u8; r[17] = ((self.n[4] >> 8) & 0xff) as u8; r[18] = (self.n[4] & 0xff) as u8; r[19] = ((self.n[3] >> 18) & 0xff) as u8; r[20] = ((self.n[3] >> 10) & 0xff) as u8; r[21] = ((self.n[3] >> 2) & 0xff) as u8; r[22] = (((self.n[3] & 0x3) << 6) | ((self.n[2] >> 20) & 0x3f)) as u8; r[23] = ((self.n[2] >> 12) & 0xff) as u8; r[24] = ((self.n[2] >> 4) & 0xff) as u8; r[25] = (((self.n[2] & 0xf) << 4) | ((self.n[1] >> 22) & 0xf)) as u8; r[26] = ((self.n[1] >> 14) & 0xff) as u8; r[27] = ((self.n[1] >> 6) & 0xff) as u8; r[28] = (((self.n[1] & 0x3f) << 2) | ((self.n[0] >> 24) & 0x3)) as u8; r[29] = ((self.n[0] >> 16) & 0xff) as u8; r[30] = ((self.n[0] >> 8) & 0xff) as u8; r[31] = (self.n[0] & 0xff) as u8; } /// Convert a field element to a 32-byte big endian /// value. Requires the input to be normalized. pub fn b32(&self) -> [u8; 32] { let mut r = [0u8; 32]; self.fill_b32(&mut r); r } /// Set a field element equal to the additive inverse of /// another. Takes a maximum magnitude of the input as an /// argument. The magnitude of the output is one higher. pub fn neg_in_place(&mut self, other: &Field, m: u32) { debug_assert!(other.magnitude <= m); debug_assert!(other.verify()); self.n[0] = 0x3fffc2f * 2 * (m + 1) - other.n[0]; self.n[1] = 0x3ffffbf * 2 * (m + 1) - other.n[1]; self.n[2] = 0x3ffffff * 2 * (m + 1) - other.n[2]; self.n[3] = 0x3ffffff * 2 * (m + 1) - other.n[3]; self.n[4] = 0x3ffffff * 2 * (m + 1) - other.n[4]; self.n[5] = 0x3ffffff * 2 * (m + 1) - other.n[5]; self.n[6] = 0x3ffffff * 2 * (m + 1) - other.n[6]; self.n[7] = 0x3ffffff * 2 * (m + 1) - other.n[7]; self.n[8] = 0x3ffffff * 2 * (m + 1) - other.n[8]; self.n[9] = 0x03fffff * 2 * (m + 1) - other.n[9]; self.magnitude = m + 1; self.normalized = false; debug_assert!(self.verify()); } /// Compute the additive inverse of this element. Takes the maximum /// expected magnitude of this element as an argument. pub fn neg(&self, m: u32) -> Field { let mut ret = Field::default(); ret.neg_in_place(self, m); ret } /// Multiplies the passed field element with a small integer /// constant. Multiplies the magnitude by that small integer. pub fn mul_int(&mut self, a: u32) { self.n[0] *= a; self.n[1] *= a; self.n[2] *= a; self.n[3] *= a; self.n[4] *= a; self.n[5] *= a; self.n[6] *= a; self.n[7] *= a; self.n[8] *= a; self.n[9] *= a; self.magnitude *= a; self.normalized = false; debug_assert!(self.verify()); } /// Compare two field elements. Requires both inputs to be /// normalized. pub fn cmp_var(&self, other: &Field) -> Ordering { // Variable time compare implementation. debug_assert!(self.normalized); debug_assert!(other.normalized); debug_assert!(self.verify()); debug_assert!(other.verify()); for i in (0..10).rev() { if self.n[i] > other.n[i] { return Ordering::Greater; } if self.n[i] < other.n[i] { return Ordering::Less; } } Ordering::Equal } pub fn eq_var(&self, other: &Field) -> bool { let mut na = self.neg(1); na += other; na.normalizes_to_zero_var() } fn mul_inner(&mut self, a: &Field, b: &Field) { const M: u64 = 0x3ffffff; const R0: u64 = 0x3d10; const R1: u64 = 0x400; let (mut c, mut d): (u64, u64); let (v0, v1, v2, v3, v4, v5, v6, v7, v8): (u64, u64, u64, u64, u64, u64, u64, u64, u64); let (t9, t1, t0, t2, t3, t4, t5, t6, t7): (u32, u32, u32, u32, u32, u32, u32, u32, u32); debug_assert_bits!(a.n[0], 30); debug_assert_bits!(a.n[1], 30); debug_assert_bits!(a.n[2], 30); debug_assert_bits!(a.n[3], 30); debug_assert_bits!(a.n[4], 30); debug_assert_bits!(a.n[5], 30); debug_assert_bits!(a.n[6], 30); debug_assert_bits!(a.n[7], 30); debug_assert_bits!(a.n[8], 30); debug_assert_bits!(a.n[9], 26); debug_assert_bits!(b.n[0], 30); debug_assert_bits!(b.n[1], 30); debug_assert_bits!(b.n[2], 30); debug_assert_bits!(b.n[3], 30); debug_assert_bits!(b.n[4], 30); debug_assert_bits!(b.n[5], 30); debug_assert_bits!(b.n[6], 30); debug_assert_bits!(b.n[7], 30); debug_assert_bits!(b.n[8], 30); debug_assert_bits!(b.n[9], 26); // [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. // px is a shorthand for sum(a[i]*b[x-i], i=0..x). // Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. d = ((a.n[0] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[0] as u64)); // debug_assert_bits!(d, 64); /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ t9 = (d & M) as u32; d >>= 26; debug_assert_bits!(t9, 26); debug_assert_bits!(d, 38); /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ c = (a.n[0] as u64) * (b.n[0] as u64); debug_assert_bits!(c, 60); /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ d = d .wrapping_add((a.n[1] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[1] as u64)); debug_assert_bits!(d, 63); /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ v0 = d & M; d >>= 26; c += v0 * R0; debug_assert_bits!(v0, 26); debug_assert_bits!(d, 37); debug_assert_bits!(c, 61); /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ t0 = (c & M) as u32; c >>= 26; c += v0 * R1; debug_assert_bits!(t0, 26); debug_assert_bits!(c, 37); /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ c = c .wrapping_add((a.n[0] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[0] as u64)); debug_assert_bits!(c, 62); /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ d = d .wrapping_add((a.n[2] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[2] as u64)); debug_assert_bits!(d, 63); /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ v1 = d & M; d >>= 26; c += v1 * R0; debug_assert_bits!(v1, 26); debug_assert_bits!(d, 37); debug_assert_bits!(c, 63); /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ t1 = (c & M) as u32; c >>= 26; c += v1 * R1; debug_assert_bits!(t1, 26); debug_assert_bits!(c, 38); /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ c = c .wrapping_add((a.n[0] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[0] as u64)); debug_assert_bits!(c, 62); /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ d = d .wrapping_add((a.n[3] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[3] as u64)); debug_assert_bits!(d, 63); /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ v2 = d & M; d >>= 26; c += v2 * R0; debug_assert_bits!(v2, 26); debug_assert_bits!(d, 37); debug_assert_bits!(c, 63); /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ t2 = (c & M) as u32; c >>= 26; c += v2 * R1; debug_assert_bits!(t2, 26); debug_assert_bits!(c, 38); /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ c = c .wrapping_add((a.n[0] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[0] as u64)); debug_assert_bits!(c, 63); /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ d = d .wrapping_add((a.n[4] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[4] as u64)); debug_assert_bits!(d, 63); /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ v3 = d & M; d >>= 26; c += v3 * R0; debug_assert_bits!(v3, 26); debug_assert_bits!(d, 37); // debug_assert_bits!(c, 64); /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ t3 = (c & M) as u32; c >>= 26; c += v3 * R1; debug_assert_bits!(t3, 26); debug_assert_bits!(c, 39); /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ c = c .wrapping_add((a.n[0] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[0] as u64)); debug_assert_bits!(c, 63); /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ d = d .wrapping_add((a.n[5] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[5] as u64)); debug_assert_bits!(d, 62); /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ v4 = d & M; d >>= 26; c += v4 * R0; debug_assert_bits!(v4, 26); debug_assert_bits!(d, 36); // debug_assert_bits!(c, 64); /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ t4 = (c & M) as u32; c >>= 26; c += v4 * R1; debug_assert_bits!(t4, 26); debug_assert_bits!(c, 39); /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ c = c .wrapping_add((a.n[0] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[0] as u64)); debug_assert_bits!(c, 63); /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ d = d .wrapping_add((a.n[6] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[6] as u64)); debug_assert_bits!(d, 62); /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ v5 = d & M; d >>= 26; c += v5 * R0; debug_assert_bits!(v5, 26); debug_assert_bits!(d, 36); // debug_assert_bits!(c, 64); /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ t5 = (c & M) as u32; c >>= 26; c += v5 * R1; debug_assert_bits!(t5, 26); debug_assert_bits!(c, 39); /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ c = c .wrapping_add((a.n[0] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[0] as u64)); debug_assert_bits!(c, 63); /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ d = d .wrapping_add((a.n[7] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[7] as u64)); debug_assert_bits!(d, 61); /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ v6 = d & M; d >>= 26; c += v6 * R0; debug_assert_bits!(v6, 26); debug_assert_bits!(d, 35); // debug_assert_bits!(c, 64); /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ t6 = (c & M) as u32; c >>= 26; c += v6 * R1; debug_assert_bits!(t6, 26); debug_assert_bits!(c, 39); /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ c = c .wrapping_add((a.n[0] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[0] as u64)); // debug_assert_bits!(c, 64); debug_assert!(c <= 0x8000007c00000007); /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ d = d .wrapping_add((a.n[8] as u64) * (b.n[9] as u64)) .wrapping_add((a.n[9] as u64) * (b.n[8] as u64)); debug_assert_bits!(d, 58); /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ v7 = d & M; d >>= 26; c += v7 * R0; debug_assert_bits!(v7, 26); debug_assert_bits!(d, 32); // debug_assert_bits!(c, 64); debug_assert!(c <= 0x800001703fffc2f7); /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ t7 = (c & M) as u32; c >>= 26; c += v7 * R1; debug_assert_bits!(t7, 26); debug_assert_bits!(c, 38); /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ c = c .wrapping_add((a.n[0] as u64) * (b.n[8] as u64)) .wrapping_add((a.n[1] as u64) * (b.n[7] as u64)) .wrapping_add((a.n[2] as u64) * (b.n[6] as u64)) .wrapping_add((a.n[3] as u64) * (b.n[5] as u64)) .wrapping_add((a.n[4] as u64) * (b.n[4] as u64)) .wrapping_add((a.n[5] as u64) * (b.n[3] as u64)) .wrapping_add((a.n[6] as u64) * (b.n[2] as u64)) .wrapping_add((a.n[7] as u64) * (b.n[1] as u64)) .wrapping_add((a.n[8] as u64) * (b.n[0] as u64)); // debug_assert_bits!(c, 64); debug_assert!(c <= 0x9000007b80000008); /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d = d.wrapping_add((a.n[9] as u64) * (b.n[9] as u64)); debug_assert_bits!(d, 57); /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ v8 = d & M; d >>= 26; c += v8 * R0; debug_assert_bits!(v8, 26); debug_assert_bits!(d, 31); // debug_assert_bits!(c, 64); debug_assert!(c <= 0x9000016fbfffc2f8); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[3] = t3; debug_assert_bits!(self.n[3], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[4] = t4; debug_assert_bits!(self.n[4], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[5] = t5; debug_assert_bits!(self.n[5], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[6] = t6; debug_assert_bits!(self.n[6], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[7] = t7; debug_assert_bits!(self.n[7], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[8] = (c & M) as u32; c >>= 26; c += v8 * R1; debug_assert_bits!(self.n[8], 26); debug_assert_bits!(c, 39); /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += d * R0 + t9 as u64; debug_assert_bits!(c, 45); /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[9] = (c & (M >> 4)) as u32; c >>= 22; c += d * (R1 << 4); debug_assert_bits!(self.n[9], 22); debug_assert_bits!(c, 46); /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d = c * (R0 >> 4) + t0 as u64; debug_assert_bits!(d, 56); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[0] = (d & M) as u32; d >>= 26; debug_assert_bits!(self.n[0], 26); debug_assert_bits!(d, 30); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += c * (R1 >> 4) + t1 as u64; debug_assert_bits!(d, 53); debug_assert!(d <= 0x10000003ffffbf); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[1] = (d & M) as u32; d >>= 26; debug_assert_bits!(self.n[1], 26); debug_assert_bits!(d, 27); debug_assert!(d <= 0x4000000); /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += t2 as u64; debug_assert_bits!(d, 27); /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[2] = d as u32; debug_assert_bits!(self.n[2], 27); /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } fn sqr_inner(&mut self, a: &Field) { const M: u64 = 0x3ffffff; const R0: u64 = 0x3d10; const R1: u64 = 0x400; let (mut c, mut d): (u64, u64); let (v0, v1, v2, v3, v4, v5, v6, v7, v8): (u64, u64, u64, u64, u64, u64, u64, u64, u64); let (t9, t0, t1, t2, t3, t4, t5, t6, t7): (u32, u32, u32, u32, u32, u32, u32, u32, u32); debug_assert_bits!(a.n[0], 30); debug_assert_bits!(a.n[1], 30); debug_assert_bits!(a.n[2], 30); debug_assert_bits!(a.n[3], 30); debug_assert_bits!(a.n[4], 30); debug_assert_bits!(a.n[5], 30); debug_assert_bits!(a.n[6], 30); debug_assert_bits!(a.n[7], 30); debug_assert_bits!(a.n[8], 30); debug_assert_bits!(a.n[9], 26); // [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. // px is a shorthand for sum(a.n[i]*a.n[x-i], i=0..x). // Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. d = (((a.n[0] * 2) as u64) * (a.n[9] as u64)) .wrapping_add(((a.n[1] * 2) as u64) * (a.n[8] as u64)) .wrapping_add(((a.n[2] * 2) as u64) * (a.n[7] as u64)) .wrapping_add(((a.n[3] * 2) as u64) * (a.n[6] as u64)) .wrapping_add(((a.n[4] * 2) as u64) * (a.n[5] as u64)); // debug_assert_bits!(d, 64); /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ t9 = (d & M) as u32; d >>= 26; debug_assert_bits!(t9, 26); debug_assert_bits!(d, 38); /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ c = (a.n[0] as u64) * (a.n[0] as u64); debug_assert_bits!(c, 60); /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ d = d .wrapping_add(((a.n[1] * 2) as u64) * (a.n[9] as u64)) .wrapping_add(((a.n[2] * 2) as u64) * (a.n[8] as u64)) .wrapping_add(((a.n[3] * 2) as u64) * (a.n[7] as u64)) .wrapping_add(((a.n[4] * 2) as u64) * (a.n[6] as u64)) .wrapping_add((a.n[5] as u64) * (a.n[5] as u64)); debug_assert_bits!(d, 63); /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ v0 = d & M; d >>= 26; c += v0 * R0; debug_assert_bits!(v0, 26); debug_assert_bits!(d, 37); debug_assert_bits!(c, 61); /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ t0 = (c & M) as u32; c >>= 26; c += v0 * R1; debug_assert_bits!(t0, 26); debug_assert_bits!(c, 37); /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ c = c.wrapping_add(((a.n[0] * 2) as u64) * (a.n[1] as u64)); debug_assert_bits!(c, 62); /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ d = d .wrapping_add(((a.n[2] * 2) as u64) * (a.n[9] as u64)) .wrapping_add(((a.n[3] * 2) as u64) * (a.n[8] as u64)) .wrapping_add(((a.n[4] * 2) as u64) * (a.n[7] as u64)) .wrapping_add(((a.n[5] * 2) as u64) * (a.n[6] as u64)); debug_assert_bits!(d, 63); /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ v1 = d & M; d >>= 26; c += v1 * R0; debug_assert_bits!(v1, 26); debug_assert_bits!(d, 37); debug_assert_bits!(c, 63); /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ t1 = (c & M) as u32; c >>= 26; c += v1 * R1; debug_assert_bits!(t1, 26); debug_assert_bits!(c, 38); /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ c = c .wrapping_add(((a.n[0] * 2) as u64) * (a.n[2] as u64)) .wrapping_add((a.n[1] as u64) * (a.n[1] as u64)); debug_assert_bits!(c, 62); /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ d = d .wrapping_add(((a.n[3] * 2) as u64) * (a.n[9] as u64)) .wrapping_add(((a.n[4] * 2) as u64) * (a.n[8] as u64)) .wrapping_add(((a.n[5] * 2) as u64) * (a.n[7] as u64)) .wrapping_add((a.n[6] as u64) * (a.n[6] as u64)); debug_assert_bits!(d, 63); /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ v2 = d & M; d >>= 26; c += v2 * R0; debug_assert_bits!(v2, 26); debug_assert_bits!(d, 37); debug_assert_bits!(c, 63); /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ t2 = (c & M) as u32; c >>= 26; c += v2 * R1; debug_assert_bits!(t2, 26); debug_assert_bits!(c, 38); /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ c = c .wrapping_add(((a.n[0] * 2) as u64) * (a.n[3] as u64)) .wrapping_add(((a.n[1] * 2) as u64) * (a.n[2] as u64)); debug_assert_bits!(c, 63); /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ d = d .wrapping_add(((a.n[4] * 2) as u64) * (a.n[9] as u64)) .wrapping_add(((a.n[5] * 2) as u64) * (a.n[8] as u64)) .wrapping_add(((a.n[6] * 2) as u64) * (a.n[7] as u64)); debug_assert_bits!(d, 63); /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ v3 = d & M; d >>= 26; c += v3 * R0; debug_assert_bits!(v3, 26); debug_assert_bits!(d, 37); // debug_assert_bits!(c, 64); /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ t3 = (c & M) as u32; c >>= 26; c += v3 * R1; debug_assert_bits!(t3, 26); debug_assert_bits!(c, 39); /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ c = c .wrapping_add(((a.n[0] * 2) as u64) * (a.n[4] as u64)) .wrapping_add(((a.n[1] * 2) as u64) * (a.n[3] as u64)) .wrapping_add((a.n[2] as u64) * (a.n[2] as u64)); debug_assert_bits!(c, 63); /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ d = d .wrapping_add(((a.n[5] * 2) as u64) * (a.n[9] as u64)) .wrapping_add(((a.n[6] * 2) as u64) * (a.n[8] as u64)) .wrapping_add((a.n[7] as u64) * (a.n[7] as u64)); debug_assert_bits!(d, 62); /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ v4 = d & M; d >>= 26; c += v4 * R0; debug_assert_bits!(v4, 26); debug_assert_bits!(d, 36); // debug_assert_bits!(c, 64); /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ t4 = (c & M) as u32; c >>= 26; c += v4 * R1; debug_assert_bits!(t4, 26); debug_assert_bits!(c, 39); /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ c = c .wrapping_add(((a.n[0] * 2) as u64) * (a.n[5] as u64)) .wrapping_add(((a.n[1] * 2) as u64) * (a.n[4] as u64)) .wrapping_add(((a.n[2] * 2) as u64) * (a.n[3] as u64)); debug_assert_bits!(c, 63); /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ d = d .wrapping_add(((a.n[6] * 2) as u64) * (a.n[9] as u64)) .wrapping_add(((a.n[7] * 2) as u64) * (a.n[8] as u64)); debug_assert_bits!(d, 62); /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ v5 = d & M; d >>= 26; c += v5 * R0; debug_assert_bits!(v5, 26); debug_assert_bits!(d, 36); // debug_assert_bits!(c, 64); /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ t5 = (c & M) as u32; c >>= 26; c += v5 * R1; debug_assert_bits!(t5, 26); debug_assert_bits!(c, 39); /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ c = c .wrapping_add(((a.n[0] * 2) as u64) * (a.n[6] as u64)) .wrapping_add(((a.n[1] * 2) as u64) * (a.n[5] as u64)) .wrapping_add(((a.n[2] * 2) as u64) * (a.n[4] as u64)) .wrapping_add((a.n[3] as u64) * (a.n[3] as u64)); debug_assert_bits!(c, 63); /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ d = d .wrapping_add(((a.n[7] * 2) as u64) * (a.n[9] as u64)) .wrapping_add((a.n[8] as u64) * (a.n[8] as u64)); debug_assert_bits!(d, 61); /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ v6 = d & M; d >>= 26; c += v6 * R0; debug_assert_bits!(v6, 26); debug_assert_bits!(d, 35); // debug_assert_bits!(c, 64); /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ t6 = (c & M) as u32; c >>= 26; c += v6 * R1; debug_assert_bits!(t6, 26); debug_assert_bits!(c, 39); /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ c = c .wrapping_add(((a.n[0] * 2) as u64) * (a.n[7] as u64)) .wrapping_add(((a.n[1] * 2) as u64) * (a.n[6] as u64)) .wrapping_add(((a.n[2] * 2) as u64) * (a.n[5] as u64)) .wrapping_add(((a.n[3] * 2) as u64) * (a.n[4] as u64)); // debug_assert_bits!(c, 64); debug_assert!(c <= 0x8000007C00000007); /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ d = d.wrapping_add(((a.n[8] * 2) as u64) * (a.n[9] as u64)); debug_assert_bits!(d, 58); /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ v7 = d & M; d >>= 26; c += v7 * R0; debug_assert_bits!(v7, 26); debug_assert_bits!(d, 32); /* debug_assert_bits!(c, 64); */ debug_assert!(c <= 0x800001703FFFC2F7); /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ t7 = (c & M) as u32; c >>= 26; c += v7 * R1; debug_assert_bits!(t7, 26); debug_assert_bits!(c, 38); /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ c = c .wrapping_add(((a.n[0] * 2) as u64) * (a.n[8] as u64)) .wrapping_add(((a.n[1] * 2) as u64) * (a.n[7] as u64)) .wrapping_add(((a.n[2] * 2) as u64) * (a.n[6] as u64)) .wrapping_add(((a.n[3] * 2) as u64) * (a.n[5] as u64)) .wrapping_add((a.n[4] as u64) * (a.n[4] as u64)); // debug_assert_bits!(c, 64); debug_assert!(c <= 0x9000007B80000008); /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d = d.wrapping_add((a.n[9] as u64) * (a.n[9] as u64)); debug_assert_bits!(d, 57); /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ v8 = d & M; d >>= 26; c += v8 * R0; debug_assert_bits!(v8, 26); debug_assert_bits!(d, 31); /* debug_assert_bits!(c, 64); */ debug_assert!(c <= 0x9000016FBFFFC2F8); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[3] = t3; debug_assert_bits!(self.n[3], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[4] = t4; debug_assert_bits!(self.n[4], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[5] = t5; debug_assert_bits!(self.n[5], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[6] = t6; debug_assert_bits!(self.n[6], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[7] = t7; debug_assert_bits!(self.n[7], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[8] = (c & M) as u32; c >>= 26; c += v8 * R1; debug_assert_bits!(self.n[8], 26); debug_assert_bits!(c, 39); /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += d * R0 + t9 as u64; debug_assert_bits!(c, 45); /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[9] = (c & (M >> 4)) as u32; c >>= 22; c += d * (R1 << 4); debug_assert_bits!(self.n[9], 22); debug_assert_bits!(c, 46); /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d = c * (R0 >> 4) + t0 as u64; debug_assert_bits!(d, 56); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[0] = (d & M) as u32; d >>= 26; debug_assert_bits!(self.n[0], 26); debug_assert_bits!(d, 30); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += c * (R1 >> 4) + t1 as u64; debug_assert_bits!(d, 53); debug_assert!(d <= 0x10000003FFFFBF); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[1] = (d & M) as u32; d >>= 26; debug_assert_bits!(self.n[1], 26); debug_assert_bits!(d, 27); debug_assert!(d <= 0x4000000); /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += t2 as u64; debug_assert_bits!(d, 27); /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ self.n[2] = d as u32; debug_assert_bits!(self.n[2], 27); /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } /// Sets a field element to be the product of two others. Requires /// the inputs' magnitudes to be at most 8. The output magnitude /// is 1 (but not guaranteed to be normalized). pub fn mul_in_place(&mut self, a: &Field, b: &Field) { debug_assert!(a.magnitude <= 8); debug_assert!(b.magnitude <= 8); debug_assert!(a.verify()); debug_assert!(b.verify()); self.mul_inner(a, b); self.magnitude = 1; self.normalized = false; debug_assert!(self.verify()); } /// Sets a field element to be the square of another. Requires the /// input's magnitude to be at most 8. The output magnitude is 1 /// (but not guaranteed to be normalized). pub fn sqr_in_place(&mut self, a: &Field) { debug_assert!(a.magnitude <= 8); debug_assert!(a.verify()); self.sqr_inner(a); self.magnitude = 1; self.normalized = false; debug_assert!(a.verify()); } pub fn sqr(&self) -> Field { let mut ret = Field::default(); ret.sqr_in_place(self); ret } /// If a has a square root, it is computed in r and 1 is /// returned. If a does not have a square root, the root of its /// negation is computed and 0 is returned. The input's magnitude /// can be at most 8. The output magnitude is 1 (but not /// guaranteed to be normalized). The result in r will always be a /// square itself. pub fn sqrt(&self) -> (Field, bool) { let mut x2 = self.sqr(); x2 *= self; let mut x3 = x2.sqr(); x3 *= self; let mut x6 = x3; for _ in 0..3 { x6 = x6.sqr(); } x6 *= &x3; let mut x9 = x6; for _ in 0..3 { x9 = x9.sqr(); } x9 *= &x3; let mut x11 = x9; for _ in 0..2 { x11 = x11.sqr(); } x11 *= &x2; let mut x22 = x11; for _ in 0..11 { x22 = x22.sqr(); } x22 *= &x11; let mut x44 = x22; for _ in 0..22 { x44 = x44.sqr(); } x44 *= &x22; let mut x88 = x44; for _ in 0..44 { x88 = x88.sqr(); } x88 *= &x44; let mut x176 = x88; for _ in 0..88 { x176 = x176.sqr(); } x176 *= &x88; let mut x220 = x176; for _ in 0..44 { x220 = x220.sqr(); } x220 *= &x44; let mut x223 = x220; for _ in 0..3 { x223 = x223.sqr(); } x223 *= &x3; let mut t1 = x223; for _ in 0..23 { t1 = t1.sqr(); } t1 *= &x22; for _ in 0..6 { t1 = t1.sqr(); } t1 *= &x2; t1 = t1.sqr(); let r = t1.sqr(); t1 = r.sqr(); (r, &t1 == self) } /// Sets a field element to be the (modular) inverse of /// another. Requires the input's magnitude to be at most 8. The /// output magnitude is 1 (but not guaranteed to be normalized). pub fn inv(&self) -> Field { let mut x2 = self.sqr(); x2 *= self; let mut x3 = x2.sqr(); x3 *= self; let mut x6 = x3; for _ in 0..3 { x6 = x6.sqr(); } x6 *= &x3; let mut x9 = x6; for _ in 0..3 { x9 = x9.sqr(); } x9 *= &x3; let mut x11 = x9; for _ in 0..2 { x11 = x11.sqr(); } x11 *= &x2; let mut x22 = x11; for _ in 0..11 { x22 = x22.sqr(); } x22 *= &x11; let mut x44 = x22; for _ in 0..22 { x44 = x44.sqr(); } x44 *= &x22; let mut x88 = x44; for _ in 0..44 { x88 = x88.sqr(); } x88 *= &x44; let mut x176 = x88; for _ in 0..88 { x176 = x176.sqr(); } x176 *= &x88; let mut x220 = x176; for _ in 0..44 { x220 = x220.sqr(); } x220 *= &x44; let mut x223 = x220; for _ in 0..3 { x223 = x223.sqr(); } x223 *= &x3; let mut t1 = x223; for _ in 0..23 { t1 = t1.sqr(); } t1 *= &x22; for _ in 0..5 { t1 = t1.sqr(); } t1 *= self; for _ in 0..3 { t1 = t1.sqr(); } t1 *= &x2; for _ in 0..2 { t1 = t1.sqr(); } self * &t1 } /// Potentially faster version of secp256k1_fe_inv, without /// constant-time guarantee. pub fn inv_var(&self) -> Field { self.inv() } /// Checks whether a field element is a quadratic residue. pub fn is_quad_var(&self) -> bool { let (_, ret) = self.sqrt(); ret } /// If flag is true, set *r equal to *a; otherwise leave /// it. Constant-time. pub fn cmov(&mut self, other: &Field, flag: bool) { self.n[0] = if flag { other.n[0] } else { self.n[0] }; self.n[1] = if flag { other.n[1] } else { self.n[1] }; self.n[2] = if flag { other.n[2] } else { self.n[2] }; self.n[3] = if flag { other.n[3] } else { self.n[3] }; self.n[4] = if flag { other.n[4] } else { self.n[4] }; self.n[5] = if flag { other.n[5] } else { self.n[5] }; self.n[6] = if flag { other.n[6] } else { self.n[6] }; self.n[7] = if flag { other.n[7] } else { self.n[7] }; self.n[8] = if flag { other.n[8] } else { self.n[8] }; self.n[9] = if flag { other.n[9] } else { self.n[9] }; self.magnitude = if flag { other.magnitude } else { self.magnitude }; self.normalized = if flag { other.normalized } else { self.normalized }; } } impl Default for Field { fn default() -> Field { Self { n: [0u32; 10], magnitude: 0, normalized: true, } } } impl Add for Field { type Output = Field; fn add(self, other: Field) -> Field { let mut ret = self; ret.add_assign(&other); ret } } impl<'a, 'b> Add<&'a Field> for &'b Field { type Output = Field; fn add(self, other: &'a Field) -> Field { let mut ret = *self; ret.add_assign(other); ret } } impl<'a> AddAssign<&'a Field> for Field { fn add_assign(&mut self, other: &'a Field) { self.n[0] += other.n[0]; self.n[1] += other.n[1]; self.n[2] += other.n[2]; self.n[3] += other.n[3]; self.n[4] += other.n[4]; self.n[5] += other.n[5]; self.n[6] += other.n[6]; self.n[7] += other.n[7]; self.n[8] += other.n[8]; self.n[9] += other.n[9]; self.magnitude += other.magnitude; self.normalized = false; debug_assert!(self.verify()); } } impl AddAssign for Field { fn add_assign(&mut self, other: Field) { self.add_assign(&other) } } impl Mul for Field { type Output = Field; fn mul(self, other: Field) -> Field { let mut ret = Field::default(); ret.mul_in_place(&self, &other); ret } } impl<'a, 'b> Mul<&'a Field> for &'b Field { type Output = Field; fn mul(self, other: &'a Field) -> Field { let mut ret = Field::default(); ret.mul_in_place(self, other); ret } } impl<'a> MulAssign<&'a Field> for Field { fn mul_assign(&mut self, other: &'a Field) { let mut ret = Field::default(); ret.mul_in_place(self, other); *self = ret; } } impl MulAssign for Field { fn mul_assign(&mut self, other: Field) { self.mul_assign(&other) } } impl PartialEq for Field { fn eq(&self, other: &Field) -> bool { let mut na = self.neg(self.magnitude); na += other; na.normalizes_to_zero() } } impl Eq for Field {} impl Ord for Field { fn cmp(&self, other: &Field) -> Ordering { self.cmp_var(other) } } impl PartialOrd for Field { fn partial_cmp(&self, other: &Field) -> Option { Some(self.cmp(other)) } } #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// Compact field element storage. pub struct FieldStorage(pub [u32; 8]); impl Default for FieldStorage { fn default() -> FieldStorage { FieldStorage([0; 8]) } } impl FieldStorage { pub const fn new( d7: u32, d6: u32, d5: u32, d4: u32, d3: u32, d2: u32, d1: u32, d0: u32, ) -> Self { Self([d0, d1, d2, d3, d4, d5, d6, d7]) } pub fn cmov(&mut self, other: &FieldStorage, flag: bool) { self.0[0] = if flag { other.0[0] } else { self.0[0] }; self.0[1] = if flag { other.0[1] } else { self.0[1] }; self.0[2] = if flag { other.0[2] } else { self.0[2] }; self.0[3] = if flag { other.0[3] } else { self.0[3] }; self.0[4] = if flag { other.0[4] } else { self.0[4] }; self.0[5] = if flag { other.0[5] } else { self.0[5] }; self.0[6] = if flag { other.0[6] } else { self.0[6] }; self.0[7] = if flag { other.0[7] } else { self.0[7] }; } } impl From for Field { fn from(a: FieldStorage) -> Field { let mut r = Field::default(); r.n[0] = a.0[0] & 0x3FFFFFF; r.n[1] = a.0[0] >> 26 | ((a.0[1] << 6) & 0x3FFFFFF); r.n[2] = a.0[1] >> 20 | ((a.0[2] << 12) & 0x3FFFFFF); r.n[3] = a.0[2] >> 14 | ((a.0[3] << 18) & 0x3FFFFFF); r.n[4] = a.0[3] >> 8 | ((a.0[4] << 24) & 0x3FFFFFF); r.n[5] = (a.0[4] >> 2) & 0x3FFFFFF; r.n[6] = a.0[4] >> 28 | ((a.0[5] << 4) & 0x3FFFFFF); r.n[7] = a.0[5] >> 22 | ((a.0[6] << 10) & 0x3FFFFFF); r.n[8] = a.0[6] >> 16 | ((a.0[7] << 16) & 0x3FFFFFF); r.n[9] = a.0[7] >> 10; r.magnitude = 1; r.normalized = true; r } } impl Into for Field { fn into(self) -> FieldStorage { debug_assert!(self.normalized); let mut r = FieldStorage::default(); r.0[0] = self.n[0] | self.n[1] << 26; r.0[1] = self.n[1] >> 6 | self.n[2] << 20; r.0[2] = self.n[2] >> 12 | self.n[3] << 14; r.0[3] = self.n[3] >> 18 | self.n[4] << 8; r.0[4] = self.n[4] >> 24 | self.n[5] << 2 | self.n[6] << 28; r.0[5] = self.n[6] >> 4 | self.n[7] << 22; r.0[6] = self.n[7] >> 10 | self.n[8] << 16; r.0[7] = self.n[8] >> 16 | self.n[9] << 10; r } } ================================================ FILE: core/src/group.rs ================================================ use crate::field::{Field, FieldStorage}; #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// A group element of the secp256k1 curve, in affine coordinates. pub struct Affine { pub x: Field, pub y: Field, pub infinity: bool, } #[derive(Debug, Clone, Copy)] /// A group element of the secp256k1 curve, in jacobian coordinates. pub struct Jacobian { pub x: Field, pub y: Field, pub z: Field, pub infinity: bool, } #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// Affine coordinate group element compact storage. pub struct AffineStorage { pub x: FieldStorage, pub y: FieldStorage, } impl Default for Affine { fn default() -> Affine { Affine { x: Field::default(), y: Field::default(), infinity: false, } } } impl Default for Jacobian { fn default() -> Jacobian { Jacobian { x: Field::default(), y: Field::default(), z: Field::default(), infinity: false, } } } impl Default for AffineStorage { fn default() -> AffineStorage { AffineStorage { x: FieldStorage::default(), y: FieldStorage::default(), } } } pub static AFFINE_INFINITY: Affine = Affine { x: Field::new(0, 0, 0, 0, 0, 0, 0, 0), y: Field::new(0, 0, 0, 0, 0, 0, 0, 0), infinity: true, }; pub static JACOBIAN_INFINITY: Jacobian = Jacobian { x: Field::new(0, 0, 0, 0, 0, 0, 0, 0), y: Field::new(0, 0, 0, 0, 0, 0, 0, 0), z: Field::new(0, 0, 0, 0, 0, 0, 0, 0), infinity: true, }; pub static AFFINE_G: Affine = Affine::new( Field::new( 0x79BE667E, 0xF9DCBBAC, 0x55A06295, 0xCE870B07, 0x029BFCDB, 0x2DCE28D9, 0x59F2815B, 0x16F81798, ), Field::new( 0x483ADA77, 0x26A3C465, 0x5DA4FBFC, 0x0E1108A8, 0xFD17B448, 0xA6855419, 0x9C47D08F, 0xFB10D4B8, ), ); pub const CURVE_B: u32 = 7; impl Affine { /// Create a new affine. pub const fn new(x: Field, y: Field) -> Self { Self { x, y, infinity: false, } } /// Set a group element equal to the point with given X and Y /// coordinates. pub fn set_xy(&mut self, x: &Field, y: &Field) { self.infinity = false; self.x = *x; self.y = *y; } /// Set a group element (affine) equal to the point with the given /// X coordinate and a Y coordinate that is a quadratic residue /// modulo p. The return value is true iff a coordinate with the /// given X coordinate exists. pub fn set_xquad(&mut self, x: &Field) -> bool { self.x = *x; let x2 = x.sqr(); let x3 = *x * x2; self.infinity = false; let mut c = Field::default(); c.set_int(CURVE_B); c += x3; let (v, ret) = c.sqrt(); self.y = v; ret } /// Set a group element (affine) equal to the point with the given /// X coordinate, and given oddness for Y. Return value indicates /// whether the result is valid. pub fn set_xo_var(&mut self, x: &Field, odd: bool) -> bool { if !self.set_xquad(x) { return false; } self.y.normalize_var(); if self.y.is_odd() != odd { self.y = self.y.neg(1); } true } /// Check whether a group element is the point at infinity. pub fn is_infinity(&self) -> bool { self.infinity } /// Check whether a group element is valid (i.e., on the curve). pub fn is_valid_var(&self) -> bool { if self.is_infinity() { return false; } let y2 = self.y.sqr(); let mut x3 = self.x.sqr(); x3 *= &self.x; let mut c = Field::default(); c.set_int(CURVE_B); x3 += &c; x3.normalize_weak(); y2.eq_var(&x3) } pub fn neg_in_place(&mut self, other: &Affine) { *self = *other; self.y.normalize_weak(); self.y = self.y.neg(1); } pub fn neg(&self) -> Affine { let mut ret = Affine::default(); ret.neg_in_place(self); ret } /// Set a group element equal to another which is given in /// jacobian coordinates. pub fn set_gej(&mut self, a: &Jacobian) { self.infinity = a.infinity; let mut a = *a; a.z = a.z.inv(); let z2 = a.z.sqr(); let z3 = a.z * z2; a.x *= z2; a.y *= z3; a.z.set_int(1); self.x = a.x; self.y = a.y; } pub fn from_gej(a: &Jacobian) -> Self { let mut ge = Self::default(); ge.set_gej(a); ge } pub fn set_gej_var(&mut self, a: &Jacobian) { let mut a = *a; self.infinity = a.infinity; if a.is_infinity() { return; } a.z = a.z.inv_var(); let z2 = a.z.sqr(); let z3 = a.z * z2; a.x *= &z2; a.y *= &z3; a.z.set_int(1); self.x = a.x; self.y = a.y; } pub fn set_gej_zinv(&mut self, a: &Jacobian, zi: &Field) { let zi2 = zi.sqr(); let zi3 = zi2 * *zi; self.x = a.x * zi2; self.y = a.y * zi3; self.infinity = a.infinity; } /// Clear a secp256k1_ge to prevent leaking sensitive information. pub fn clear(&mut self) { self.infinity = false; self.x.clear(); self.y.clear(); } } pub fn set_table_gej_var(r: &mut [Affine], a: &[Jacobian], zr: &[Field]) { debug_assert!(r.len() == a.len()); let mut i = r.len() - 1; let mut zi: Field; if !r.is_empty() { zi = a[i].z.inv(); r[i].set_gej_zinv(&a[i], &zi); while i > 0 { zi *= &zr[i]; i -= 1; r[i].set_gej_zinv(&a[i], &zi); } } } pub fn globalz_set_table_gej(r: &mut [Affine], globalz: &mut Field, a: &[Jacobian], zr: &[Field]) { debug_assert!(r.len() == a.len() && a.len() == zr.len()); let mut i = r.len() - 1; let mut zs: Field; if !r.is_empty() { r[i].x = a[i].x; r[i].y = a[i].y; *globalz = a[i].z; r[i].infinity = false; zs = zr[i]; while i > 0 { if i != r.len() - 1 { zs *= zr[i]; } i -= 1; r[i].set_gej_zinv(&a[i], &zs); } } } impl Jacobian { /// Create a new jacobian. pub const fn new(x: Field, y: Field) -> Self { Self { x, y, infinity: false, z: Field::new(0, 0, 0, 0, 0, 0, 0, 1), } } /// Set a group element (jacobian) equal to the point at infinity. pub fn set_infinity(&mut self) { self.infinity = true; self.x.clear(); self.y.clear(); self.z.clear(); } /// Set a group element (jacobian) equal to another which is given /// in affine coordinates. pub fn set_ge(&mut self, a: &Affine) { self.infinity = a.infinity; self.x = a.x; self.y = a.y; self.z.set_int(1); } pub fn from_ge(a: &Affine) -> Self { let mut gej = Self::default(); gej.set_ge(a); gej } /// Compare the X coordinate of a group element (jacobian). pub fn eq_x_var(&self, x: &Field) -> bool { debug_assert!(!self.is_infinity()); let mut r = self.z.sqr(); r *= x; let mut r2 = self.x; r2.normalize_weak(); r.eq_var(&r2) } /// Set r equal to the inverse of a (i.e., mirrored around the X /// axis). pub fn neg_in_place(&mut self, a: &Jacobian) { self.infinity = a.infinity; self.x = a.x; self.y = a.y; self.z = a.z; self.y.normalize_weak(); self.y = self.y.neg(1); } pub fn neg(&self) -> Jacobian { let mut ret = Jacobian::default(); ret.neg_in_place(self); ret } /// Check whether a group element is the point at infinity. pub fn is_infinity(&self) -> bool { self.infinity } /// Check whether a group element's y coordinate is a quadratic residue. pub fn has_quad_y_var(&self) -> bool { if self.infinity { return false; } let yz = self.y * self.z; yz.is_quad_var() } /// Set r equal to the double of a. If rzr is not-NULL, r->z = /// a->z * *rzr (where infinity means an implicit z = 0). a may /// not be zero. Constant time. pub fn double_nonzero_in_place(&mut self, a: &Jacobian, rzr: Option<&mut Field>) { debug_assert!(!self.is_infinity()); self.double_var_in_place(a, rzr); } /// Set r equal to the double of a. If rzr is not-NULL, r->z = /// a->z * *rzr (where infinity means an implicit z = 0). pub fn double_var_in_place(&mut self, a: &Jacobian, rzr: Option<&mut Field>) { self.infinity = a.infinity; if self.infinity { if let Some(rzr) = rzr { rzr.set_int(1); } return; } if let Some(rzr) = rzr { *rzr = a.y; rzr.normalize_weak(); rzr.mul_int(2); } self.z = a.z * a.y; self.z.mul_int(2); let mut t1 = a.x.sqr(); t1.mul_int(3); let mut t2 = t1.sqr(); let mut t3 = a.y.sqr(); t3.mul_int(2); let mut t4 = t3.sqr(); t4.mul_int(2); t3 *= &a.x; self.x = t3; self.x.mul_int(4); self.x = self.x.neg(4); self.x += &t2; t2 = t2.neg(1); t3.mul_int(6); t3 += &t2; self.y = t1 * t3; t2 = t4.neg(2); self.y += t2; } pub fn double_var(&self, rzr: Option<&mut Field>) -> Jacobian { let mut ret = Jacobian::default(); ret.double_var_in_place(&self, rzr); ret } /// Set r equal to the sum of a and b. If rzr is non-NULL, r->z = /// a->z * *rzr (a cannot be infinity in that case). pub fn add_var_in_place(&mut self, a: &Jacobian, b: &Jacobian, rzr: Option<&mut Field>) { if a.is_infinity() { debug_assert!(rzr.is_none()); *self = *b; return; } if b.is_infinity() { if let Some(rzr) = rzr { rzr.set_int(1); } *self = *a; return; } self.infinity = false; let z22 = b.z.sqr(); let z12 = a.z.sqr(); let u1 = a.x * z22; let u2 = b.x * z12; let mut s1 = a.y * z22; s1 *= b.z; let mut s2 = b.y * z12; s2 *= a.z; let mut h = u1.neg(1); h += u2; let mut i = s1.neg(1); i += s2; if h.normalizes_to_zero_var() { if i.normalizes_to_zero_var() { self.double_var_in_place(a, rzr); } else { if let Some(rzr) = rzr { rzr.set_int(0); } self.infinity = true; } return; } let i2 = i.sqr(); let h2 = h.sqr(); let mut h3 = h * h2; h *= b.z; if let Some(rzr) = rzr { *rzr = h; } self.z = a.z * h; let t = u1 * h2; self.x = t; self.x.mul_int(2); self.x += h3; self.x = self.x.neg(3); self.x += i2; self.y = self.x.neg(5); self.y += t; self.y *= i; h3 *= s1; h3 = h3.neg(1); self.y += h3; } pub fn add_var(&self, b: &Jacobian, rzr: Option<&mut Field>) -> Jacobian { let mut ret = Jacobian::default(); ret.add_var_in_place(self, b, rzr); ret } /// Set r equal to the sum of a and b (with b given in affine /// coordinates, and not infinity). pub fn add_ge_in_place(&mut self, a: &Jacobian, b: &Affine) { const FE1: Field = Field::new(0, 0, 0, 0, 0, 0, 0, 1); debug_assert!(!b.infinity); let zz = a.z.sqr(); let mut u1 = a.x; u1.normalize_weak(); let u2 = b.x * zz; let mut s1 = a.y; s1.normalize_weak(); let mut s2 = b.y * zz; s2 *= a.z; let mut t = u1; t += u2; let mut m = s1; m += s2; let mut rr = t.sqr(); let mut m_alt = u2.neg(1); let tt = u1 * m_alt; rr += tt; let degenerate = m.normalizes_to_zero() && rr.normalizes_to_zero(); let mut rr_alt = s1; rr_alt.mul_int(2); m_alt += u1; rr_alt.cmov(&rr, !degenerate); m_alt.cmov(&m, !degenerate); let mut n = m_alt.sqr(); let mut q = n * t; n = n.sqr(); n.cmov(&m, degenerate); t = rr_alt.sqr(); self.z = a.z * m_alt; let infinity = { let p = self.z.normalizes_to_zero(); let q = a.infinity; match (p, q) { (true, true) => false, (true, false) => true, (false, true) => false, (false, false) => false, } }; self.z.mul_int(2); q = q.neg(1); t += q; t.normalize_weak(); self.x = t; t.mul_int(2); t += q; t *= rr_alt; t += n; self.y = t.neg(3); self.y.normalize_weak(); self.x.mul_int(4); self.y.mul_int(4); self.x.cmov(&b.x, a.infinity); self.y.cmov(&b.y, a.infinity); self.z.cmov(&FE1, a.infinity); self.infinity = infinity; } pub fn add_ge(&self, b: &Affine) -> Jacobian { let mut ret = Jacobian::default(); ret.add_ge_in_place(self, b); ret } /// Set r equal to the sum of a and b (with b given in affine /// coordinates). This is more efficient than /// secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge /// but without constant-time guarantee, and b is allowed to be /// infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be /// infinity in that case). pub fn add_ge_var_in_place(&mut self, a: &Jacobian, b: &Affine, rzr: Option<&mut Field>) { if a.is_infinity() { debug_assert!(rzr.is_none()); self.set_ge(b); return; } if b.is_infinity() { if let Some(rzr) = rzr { rzr.set_int(1); } *self = *a; return; } self.infinity = false; let z12 = a.z.sqr(); let mut u1 = a.x; u1.normalize_weak(); let u2 = b.x * z12; let mut s1 = a.y; s1.normalize_weak(); let mut s2 = b.y * z12; s2 *= a.z; let mut h = u1.neg(1); h += u2; let mut i = s1.neg(1); i += s2; if h.normalizes_to_zero_var() { if i.normalizes_to_zero_var() { self.double_var_in_place(a, rzr); } else { if let Some(rzr) = rzr { rzr.set_int(0); } self.infinity = true; } return; } let i2 = i.sqr(); let h2 = h.sqr(); let mut h3 = h * h2; if let Some(rzr) = rzr { *rzr = h; } self.z = a.z * h; let t = u1 * h2; self.x = t; self.x.mul_int(2); self.x += h3; self.x = self.x.neg(3); self.x += i2; self.y = self.x.neg(5); self.y += t; self.y *= i; h3 *= s1; h3 = h3.neg(1); self.y += h3; } pub fn add_ge_var(&self, b: &Affine, rzr: Option<&mut Field>) -> Jacobian { let mut ret = Jacobian::default(); ret.add_ge_var_in_place(&self, b, rzr); ret } /// Set r equal to the sum of a and b (with the inverse of b's Z /// coordinate passed as bzinv). pub fn add_zinv_var_in_place(&mut self, a: &Jacobian, b: &Affine, bzinv: &Field) { if b.is_infinity() { *self = *a; return; } if a.is_infinity() { self.infinity = b.infinity; let bzinv2 = bzinv.sqr(); let bzinv3 = &bzinv2 * bzinv; self.x = b.x * bzinv2; self.y = b.y * bzinv3; self.z.set_int(1); return; } self.infinity = false; let az = a.z * *bzinv; let z12 = az.sqr(); let mut u1 = a.x; u1.normalize_weak(); let u2 = b.x * z12; let mut s1 = a.y; s1.normalize_weak(); let mut s2 = b.y * z12; s2 *= &az; let mut h = u1.neg(1); h += &u2; let mut i = s1.neg(1); i += &s2; if h.normalizes_to_zero_var() { if i.normalizes_to_zero_var() { self.double_var_in_place(a, None); } else { self.infinity = true; } return; } let i2 = i.sqr(); let h2 = h.sqr(); let mut h3 = h * h2; self.z = a.z; self.z *= h; let t = u1 * h2; self.x = t; self.x.mul_int(2); self.x += h3; self.x = self.x.neg(3); self.x += i2; self.y = self.x.neg(5); self.y += t; self.y *= i; h3 *= s1; h3 = h3.neg(1); self.y += h3; } pub fn add_zinv_var(&mut self, b: &Affine, bzinv: &Field) -> Jacobian { let mut ret = Jacobian::default(); ret.add_zinv_var_in_place(&self, b, bzinv); ret } /// Clear a secp256k1_gej to prevent leaking sensitive /// information. pub fn clear(&mut self) { self.infinity = false; self.x.clear(); self.y.clear(); self.z.clear(); } /// Rescale a jacobian point by b which must be /// non-zero. Constant-time. pub fn rescale(&mut self, s: &Field) { debug_assert!(!s.is_zero()); let zz = s.sqr(); self.x *= &zz; self.y *= &zz; self.y *= s; self.z *= s; } } impl From for Affine { fn from(a: AffineStorage) -> Affine { Affine::new(a.x.into(), a.y.into()) } } impl Into for Affine { fn into(mut self) -> AffineStorage { debug_assert!(!self.is_infinity()); self.x.normalize(); self.y.normalize(); AffineStorage::new(self.x.into(), self.y.into()) } } impl AffineStorage { /// Create a new affine storage. pub const fn new(x: FieldStorage, y: FieldStorage) -> Self { Self { x, y } } /// If flag is true, set *r equal to *a; otherwise leave /// it. Constant-time. pub fn cmov(&mut self, a: &AffineStorage, flag: bool) { self.x.cmov(&a.x, flag); self.y.cmov(&a.y, flag); } } ================================================ FILE: core/src/lib.rs ================================================ //! Core libraries for libsecp256k1. #![allow( clippy::cast_ptr_alignment, clippy::identity_op, clippy::many_single_char_names, clippy::needless_range_loop, clippy::suspicious_op_assign_impl, clippy::too_many_arguments, clippy::type_complexity )] #![deny( unused_import_braces, unused_imports, unused_comparisons, unused_must_use, unused_variables, non_shorthand_field_patterns, unreachable_code, unused_parens )] #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; #[macro_use] mod field; #[macro_use] mod group; mod der; mod ecdh; mod ecdsa; mod ecmult; mod error; mod scalar; pub use crate::error::Error; /// Curve related structs. pub mod curve { pub use crate::{ field::{Field, FieldStorage}, group::{Affine, AffineStorage, Jacobian, AFFINE_G, CURVE_B}, scalar::Scalar, }; pub use crate::ecmult::{ECMultContext, ECMultGenContext}; } /// Utilities to manipulate the secp256k1 curve parameters. pub mod util { pub const TAG_PUBKEY_EVEN: u8 = 0x02; pub const TAG_PUBKEY_ODD: u8 = 0x03; pub const TAG_PUBKEY_FULL: u8 = 0x04; pub const TAG_PUBKEY_HYBRID_EVEN: u8 = 0x06; pub const TAG_PUBKEY_HYBRID_ODD: u8 = 0x07; pub const MESSAGE_SIZE: usize = 32; pub const SECRET_KEY_SIZE: usize = 32; pub const RAW_PUBLIC_KEY_SIZE: usize = 64; pub const FULL_PUBLIC_KEY_SIZE: usize = 65; pub const COMPRESSED_PUBLIC_KEY_SIZE: usize = 33; pub const SIGNATURE_SIZE: usize = 64; pub const DER_MAX_SIGNATURE_SIZE: usize = 72; pub use crate::{ ecmult::{ odd_multiples_table, ECMULT_TABLE_SIZE_A, ECMULT_TABLE_SIZE_G, WINDOW_A, WINDOW_G, }, group::{globalz_set_table_gej, set_table_gej_var, AFFINE_INFINITY, JACOBIAN_INFINITY}, }; pub use crate::der::{Decoder, SignatureArray}; } ================================================ FILE: core/src/scalar.rs ================================================ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg}; use crunchy::unroll; use subtle::Choice; const SECP256K1_N: [u32; 8] = [ 0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, ]; const SECP256K1_N_C_0: u32 = !SECP256K1_N[0] + 1; const SECP256K1_N_C_1: u32 = !SECP256K1_N[1]; const SECP256K1_N_C_2: u32 = !SECP256K1_N[2]; const SECP256K1_N_C_3: u32 = !SECP256K1_N[3]; const SECP256K1_N_C_4: u32 = 1; const SECP256K1_N_H_0: u32 = 0x681B20A0; const SECP256K1_N_H_1: u32 = 0xDFE92F46; const SECP256K1_N_H_2: u32 = 0x57A4501D; const SECP256K1_N_H_3: u32 = 0x5D576E73; const SECP256K1_N_H_4: u32 = 0xFFFFFFFF; const SECP256K1_N_H_5: u32 = 0xFFFFFFFF; const SECP256K1_N_H_6: u32 = 0xFFFFFFFF; const SECP256K1_N_H_7: u32 = 0x7FFFFFFF; #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// A 256-bit scalar value. pub struct Scalar(pub [u32; 8]); impl Scalar { /// Clear a scalar to prevent the leak of sensitive data. pub fn clear(&mut self) { unsafe { core::ptr::write_volatile(&mut self.0, [0u32; 8]); } } /// Set a scalar to an unsigned integer. pub fn set_int(&mut self, v: u32) { self.0 = [v, 0, 0, 0, 0, 0, 0, 0]; } /// Create a scalar from an unsigned integer. pub fn from_int(v: u32) -> Self { let mut scalar = Self::default(); scalar.set_int(v); scalar } /// Access bits from a scalar. All requested bits must belong to /// the same 32-bit limb. pub fn bits(&self, offset: usize, count: usize) -> u32 { debug_assert!((offset + count - 1) >> 5 == offset >> 5); (self.0[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1) } /// Access bits from a scalar. Not constant time. pub fn bits_var(&self, offset: usize, count: usize) -> u32 { debug_assert!(count < 32); debug_assert!(offset + count <= 256); if (offset + count - 1) >> 5 == offset >> 5 { self.bits(offset, count) } else { debug_assert!((offset >> 5) + 1 < 8); ((self.0[offset >> 5] >> (offset & 0x1f)) | (self.0[(offset >> 5) + 1] << (32 - (offset & 0x1f)))) & ((1 << count) - 1) } } #[must_use] fn check_overflow(&self) -> Choice { let mut yes: Choice = 0.into(); let mut no: Choice = 0.into(); no |= Choice::from((self.0[7] < SECP256K1_N[7]) as u8); /* No need for a > check. */ no |= Choice::from((self.0[6] < SECP256K1_N[6]) as u8); /* No need for a > check. */ no |= Choice::from((self.0[5] < SECP256K1_N[5]) as u8); /* No need for a > check. */ no |= Choice::from((self.0[4] < SECP256K1_N[4]) as u8); yes |= Choice::from((self.0[4] > SECP256K1_N[4]) as u8) & !no; no |= Choice::from((self.0[3] < SECP256K1_N[3]) as u8) & !yes; yes |= Choice::from((self.0[3] > SECP256K1_N[3]) as u8) & !no; no |= Choice::from((self.0[2] < SECP256K1_N[2]) as u8) & !yes; yes |= Choice::from((self.0[2] > SECP256K1_N[2]) as u8) & !no; no |= Choice::from((self.0[1] < SECP256K1_N[1]) as u8) & !yes; yes |= Choice::from((self.0[1] > SECP256K1_N[1]) as u8) & !no; yes |= Choice::from((self.0[0] >= SECP256K1_N[0]) as u8) & !no; yes } fn reduce(&mut self, overflow: Choice) { let o = overflow.unwrap_u8() as u64; let mut t: u64; t = (self.0[0] as u64) + o * (SECP256K1_N_C_0 as u64); self.0[0] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[1] as u64) + o * (SECP256K1_N_C_1 as u64); self.0[1] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[2] as u64) + o * (SECP256K1_N_C_2 as u64); self.0[2] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[3] as u64) + o * (SECP256K1_N_C_3 as u64); self.0[3] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[4] as u64) + o * (SECP256K1_N_C_4 as u64); self.0[4] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += self.0[5] as u64; self.0[5] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += self.0[6] as u64; self.0[6] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += self.0[7] as u64; self.0[7] = (t & 0xFFFFFFFF) as u32; } /// Conditionally add a power of two to a scalar. The result is /// not allowed to overflow. pub fn cadd_bit(&mut self, mut bit: usize, flag: bool) { let mut t: u64; debug_assert!(bit < 256); bit += if flag { 0 } else { usize::max_value() } & 0x100; t = (self.0[0] as u64) + ((if (bit >> 5) == 0 { 1 } else { 0 }) << (bit & 0x1F)); self.0[0] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[1] as u64) + ((if (bit >> 5) == 1 { 1 } else { 0 }) << (bit & 0x1F)); self.0[1] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[2] as u64) + ((if (bit >> 5) == 2 { 1 } else { 0 }) << (bit & 0x1F)); self.0[2] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[3] as u64) + ((if (bit >> 5) == 3 { 1 } else { 0 }) << (bit & 0x1F)); self.0[3] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[4] as u64) + ((if (bit >> 5) == 4 { 1 } else { 0 }) << (bit & 0x1F)); self.0[4] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[5] as u64) + ((if (bit >> 5) == 5 { 1 } else { 0 }) << (bit & 0x1F)); self.0[5] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[6] as u64) + ((if (bit >> 5) == 6 { 1 } else { 0 }) << (bit & 0x1F)); self.0[6] = (t & 0xFFFFFFFF) as u32; t >>= 32; t += (self.0[7] as u64) + ((if (bit >> 5) == 7 { 1 } else { 0 }) << (bit & 0x1F)); self.0[7] = (t & 0xFFFFFFFF) as u32; debug_assert!((t >> 32) == 0); debug_assert!(!bool::from(self.check_overflow())); } /// Set a scalar from a big endian byte array, return whether it overflowed. #[must_use] pub fn set_b32(&mut self, b32: &[u8; 32]) -> Choice { self.0[0] = (b32[31] as u32) | ((b32[30] as u32) << 8) | ((b32[29] as u32) << 16) | ((b32[28] as u32) << 24); self.0[1] = (b32[27] as u32) | ((b32[26] as u32) << 8) | ((b32[25] as u32) << 16) | ((b32[24] as u32) << 24); self.0[2] = (b32[23] as u32) | ((b32[22] as u32) << 8) | ((b32[21] as u32) << 16) | ((b32[20] as u32) << 24); self.0[3] = (b32[19] as u32) | ((b32[18] as u32) << 8) | ((b32[17] as u32) << 16) | ((b32[16] as u32) << 24); self.0[4] = (b32[15] as u32) | ((b32[14] as u32) << 8) | ((b32[13] as u32) << 16) | ((b32[12] as u32) << 24); self.0[5] = (b32[11] as u32) | ((b32[10] as u32) << 8) | ((b32[9] as u32) << 16) | ((b32[8] as u32) << 24); self.0[6] = (b32[7] as u32) | ((b32[6] as u32) << 8) | ((b32[5] as u32) << 16) | ((b32[4] as u32) << 24); self.0[7] = (b32[3] as u32) | ((b32[2] as u32) << 8) | ((b32[1] as u32) << 16) | ((b32[0] as u32) << 24); let overflow = self.check_overflow(); self.reduce(overflow); overflow } /// Convert a scalar to a byte array. pub fn b32(&self) -> [u8; 32] { let mut bin = [0u8; 32]; self.fill_b32(&mut bin); bin } /// Convert a scalar to a byte array. pub fn fill_b32(&self, bin: &mut [u8; 32]) { bin[0] = (self.0[7] >> 24) as u8; bin[1] = (self.0[7] >> 16) as u8; bin[2] = (self.0[7] >> 8) as u8; bin[3] = (self.0[7]) as u8; bin[4] = (self.0[6] >> 24) as u8; bin[5] = (self.0[6] >> 16) as u8; bin[6] = (self.0[6] >> 8) as u8; bin[7] = (self.0[6]) as u8; bin[8] = (self.0[5] >> 24) as u8; bin[9] = (self.0[5] >> 16) as u8; bin[10] = (self.0[5] >> 8) as u8; bin[11] = (self.0[5]) as u8; bin[12] = (self.0[4] >> 24) as u8; bin[13] = (self.0[4] >> 16) as u8; bin[14] = (self.0[4] >> 8) as u8; bin[15] = (self.0[4]) as u8; bin[16] = (self.0[3] >> 24) as u8; bin[17] = (self.0[3] >> 16) as u8; bin[18] = (self.0[3] >> 8) as u8; bin[19] = (self.0[3]) as u8; bin[20] = (self.0[2] >> 24) as u8; bin[21] = (self.0[2] >> 16) as u8; bin[22] = (self.0[2] >> 8) as u8; bin[23] = (self.0[2]) as u8; bin[24] = (self.0[1] >> 24) as u8; bin[25] = (self.0[1] >> 16) as u8; bin[26] = (self.0[1] >> 8) as u8; bin[27] = (self.0[1]) as u8; bin[28] = (self.0[0] >> 24) as u8; bin[29] = (self.0[0] >> 16) as u8; bin[30] = (self.0[0] >> 8) as u8; bin[31] = (self.0[0]) as u8; } /// Check whether a scalar equals zero. pub fn is_zero(&self) -> bool { (self.0[0] | self.0[1] | self.0[2] | self.0[3] | self.0[4] | self.0[5] | self.0[6] | self.0[7]) == 0 } /// Check whether a scalar equals one. pub fn is_one(&self) -> bool { ((self.0[0] ^ 1) | self.0[1] | self.0[2] | self.0[3] | self.0[4] | self.0[5] | self.0[6] | self.0[7]) == 0 } /// Check whether a scalar is higher than the group order divided /// by 2. pub fn is_high(&self) -> bool { let mut yes: Choice = 0.into(); let mut no: Choice = 0.into(); no |= Choice::from((self.0[7] < SECP256K1_N_H_7) as u8); yes |= Choice::from((self.0[7] > SECP256K1_N_H_7) as u8) & !no; no |= Choice::from((self.0[6] < SECP256K1_N_H_6) as u8) & !yes; /* No need for a > check. */ no |= Choice::from((self.0[5] < SECP256K1_N_H_5) as u8) & !yes; /* No need for a > check. */ no |= Choice::from((self.0[4] < SECP256K1_N_H_4) as u8) & !yes; /* No need for a > check. */ no |= Choice::from((self.0[3] < SECP256K1_N_H_3) as u8) & !yes; yes |= Choice::from((self.0[3] > SECP256K1_N_H_3) as u8) & !no; no |= Choice::from((self.0[2] < SECP256K1_N_H_2) as u8) & !yes; yes |= Choice::from((self.0[2] > SECP256K1_N_H_2) as u8) & !no; no |= Choice::from((self.0[1] < SECP256K1_N_H_1) as u8) & !yes; yes |= Choice::from((self.0[1] > SECP256K1_N_H_1) as u8) & !no; yes |= Choice::from((self.0[0] >= SECP256K1_N_H_0) as u8) & !no; yes.into() } /// Conditionally negate a number, in constant time. pub fn cond_neg_assign(&mut self, flag: Choice) { let mask = u32::max_value() * flag.unwrap_u8() as u32; let nonzero = 0xFFFFFFFFu64 * !self.is_zero() as u64; let mut t = 1u64 * flag.unwrap_u8() as u64; unroll! { for i in 0..8 { t += (self.0[i] ^ mask) as u64 + (SECP256K1_N[i] & mask) as u64; self.0[i] = (t & nonzero) as u32; t >>= 32; } } let _ = t; } } macro_rules! define_ops { ($c0: ident, $c1: ident, $c2: ident) => { #[allow(unused_macros)] macro_rules! muladd { ($a: expr, $b: expr) => { let a = $a; let b = $b; let t = (a as u64) * (b as u64); let mut th = (t >> 32) as u32; let tl = t as u32; $c0 = $c0.wrapping_add(tl); th = th.wrapping_add(if $c0 < tl { 1 } else { 0 }); $c1 = $c1.wrapping_add(th); $c2 = $c2.wrapping_add(if $c1 < th { 1 } else { 0 }); debug_assert!($c1 >= th || $c2 != 0); }; } #[allow(unused_macros)] macro_rules! muladd_fast { ($a: expr, $b: expr) => { let a = $a; let b = $b; let t = (a as u64) * (b as u64); let mut th = (t >> 32) as u32; let tl = t as u32; $c0 = $c0.wrapping_add(tl); th = th.wrapping_add(if $c0 < tl { 1 } else { 0 }); $c1 = $c1.wrapping_add(th); debug_assert!($c1 >= th); }; } #[allow(unused_macros)] macro_rules! muladd2 { ($a: expr, $b: expr) => { let a = $a; let b = $b; let t = (a as u64) * (b as u64); let th = (t >> 32) as u32; let tl = t as u32; let mut th2 = th.wrapping_add(th); $c2 = $c2.wrapping_add(if th2 < th { 1 } else { 0 }); debug_assert!(th2 >= th || $c2 != 0); let tl2 = tl.wrapping_add(tl); th2 = th2.wrapping_add(if tl2 < tl { 1 } else { 0 }); $c0 = $c0.wrapping_add(tl2); th2 = th2.wrapping_add(if $c0 < tl2 { 1 } else { 0 }); $c2 = $c2.wrapping_add(if $c0 < tl2 && th2 == 0 { 1 } else { 0 }); debug_assert!($c0 >= tl2 || th2 != 0 || $c2 != 0); $c1 = $c1.wrapping_add(th2); $c2 = $c2.wrapping_add(if $c1 < th2 { 1 } else { 0 }); debug_assert!($c1 >= th2 || $c2 != 0); }; } #[allow(unused_macros)] macro_rules! sumadd { ($a: expr) => { let a = $a; $c0 = $c0.wrapping_add(a); let over = if $c0 < a { 1 } else { 0 }; $c1 = $c1.wrapping_add(over); $c2 = $c2.wrapping_add(if $c1 < over { 1 } else { 0 }); }; } #[allow(unused_macros)] macro_rules! sumadd_fast { ($a: expr) => { let a = $a; $c0 = $c0.wrapping_add(a); $c1 = $c1.wrapping_add(if $c0 < a { 1 } else { 0 }); debug_assert!($c1 != 0 || $c0 >= a); debug_assert!($c2 == 0); }; } #[allow(unused_macros)] macro_rules! extract { () => {{ #[allow(unused_assignments)] { let n = $c0; $c0 = $c1; $c1 = $c2; $c2 = 0; n } }}; } #[allow(unused_macros)] macro_rules! extract_fast { () => {{ #[allow(unused_assignments)] { let n = $c0; $c0 = $c1; $c1 = 0; debug_assert!($c2 == 0); n } }}; } }; } impl Scalar { fn reduce_512(&mut self, l: &[u32; 16]) { let (mut c0, mut c1, mut c2): (u32, u32, u32); define_ops!(c0, c1, c2); let mut c: u64; let (n0, n1, n2, n3, n4, n5, n6, n7) = (l[8], l[9], l[10], l[11], l[12], l[13], l[14], l[15]); let (m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12): ( u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, ); let (p0, p1, p2, p3, p4, p5, p6, p7, p8): (u32, u32, u32, u32, u32, u32, u32, u32, u32); c0 = l[0]; c1 = 0; c2 = 0; muladd_fast!(n0, SECP256K1_N_C_0); m0 = extract_fast!(); sumadd_fast!(l[1]); muladd!(n1, SECP256K1_N_C_0); muladd!(n0, SECP256K1_N_C_1); m1 = extract!(); sumadd!(l[2]); muladd!(n2, SECP256K1_N_C_0); muladd!(n1, SECP256K1_N_C_1); muladd!(n0, SECP256K1_N_C_2); m2 = extract!(); sumadd!(l[3]); muladd!(n3, SECP256K1_N_C_0); muladd!(n2, SECP256K1_N_C_1); muladd!(n1, SECP256K1_N_C_2); muladd!(n0, SECP256K1_N_C_3); m3 = extract!(); sumadd!(l[4]); muladd!(n4, SECP256K1_N_C_0); muladd!(n3, SECP256K1_N_C_1); muladd!(n2, SECP256K1_N_C_2); muladd!(n1, SECP256K1_N_C_3); sumadd!(n0); m4 = extract!(); sumadd!(l[5]); muladd!(n5, SECP256K1_N_C_0); muladd!(n4, SECP256K1_N_C_1); muladd!(n3, SECP256K1_N_C_2); muladd!(n2, SECP256K1_N_C_3); sumadd!(n1); m5 = extract!(); sumadd!(l[6]); muladd!(n6, SECP256K1_N_C_0); muladd!(n5, SECP256K1_N_C_1); muladd!(n4, SECP256K1_N_C_2); muladd!(n3, SECP256K1_N_C_3); sumadd!(n2); m6 = extract!(); sumadd!(l[7]); muladd!(n7, SECP256K1_N_C_0); muladd!(n6, SECP256K1_N_C_1); muladd!(n5, SECP256K1_N_C_2); muladd!(n4, SECP256K1_N_C_3); sumadd!(n3); m7 = extract!(); muladd!(n7, SECP256K1_N_C_1); muladd!(n6, SECP256K1_N_C_2); muladd!(n5, SECP256K1_N_C_3); sumadd!(n4); m8 = extract!(); muladd!(n7, SECP256K1_N_C_2); muladd!(n6, SECP256K1_N_C_3); sumadd!(n5); m9 = extract!(); muladd!(n7, SECP256K1_N_C_3); sumadd!(n6); m10 = extract!(); sumadd_fast!(n7); m11 = extract_fast!(); debug_assert!(c0 <= 1); m12 = c0; /* Reduce 385 bits into 258. */ /* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */ c0 = m0; c1 = 0; c2 = 0; muladd_fast!(m8, SECP256K1_N_C_0); p0 = extract_fast!(); sumadd_fast!(m1); muladd!(m9, SECP256K1_N_C_0); muladd!(m8, SECP256K1_N_C_1); p1 = extract!(); sumadd!(m2); muladd!(m10, SECP256K1_N_C_0); muladd!(m9, SECP256K1_N_C_1); muladd!(m8, SECP256K1_N_C_2); p2 = extract!(); sumadd!(m3); muladd!(m11, SECP256K1_N_C_0); muladd!(m10, SECP256K1_N_C_1); muladd!(m9, SECP256K1_N_C_2); muladd!(m8, SECP256K1_N_C_3); p3 = extract!(); sumadd!(m4); muladd!(m12, SECP256K1_N_C_0); muladd!(m11, SECP256K1_N_C_1); muladd!(m10, SECP256K1_N_C_2); muladd!(m9, SECP256K1_N_C_3); sumadd!(m8); p4 = extract!(); sumadd!(m5); muladd!(m12, SECP256K1_N_C_1); muladd!(m11, SECP256K1_N_C_2); muladd!(m10, SECP256K1_N_C_3); sumadd!(m9); p5 = extract!(); sumadd!(m6); muladd!(m12, SECP256K1_N_C_2); muladd!(m11, SECP256K1_N_C_3); sumadd!(m10); p6 = extract!(); sumadd_fast!(m7); muladd_fast!(m12, SECP256K1_N_C_3); sumadd_fast!(m11); p7 = extract_fast!(); p8 = c0 + m12; debug_assert!(p8 <= 2); /* Reduce 258 bits into 256. */ /* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */ c = p0 as u64 + SECP256K1_N_C_0 as u64 * p8 as u64; self.0[0] = (c & 0xFFFFFFFF) as u32; c >>= 32; c += p1 as u64 + SECP256K1_N_C_1 as u64 * p8 as u64; self.0[1] = (c & 0xFFFFFFFF) as u32; c >>= 32; c += p2 as u64 + SECP256K1_N_C_2 as u64 * p8 as u64; self.0[2] = (c & 0xFFFFFFFF) as u32; c >>= 32; c += p3 as u64 + SECP256K1_N_C_3 as u64 * p8 as u64; self.0[3] = (c & 0xFFFFFFFF) as u32; c >>= 32; c += p4 as u64 + p8 as u64; self.0[4] = (c & 0xFFFFFFFF) as u32; c >>= 32; c += p5 as u64; self.0[5] = (c & 0xFFFFFFFF) as u32; c >>= 32; c += p6 as u64; self.0[6] = (c & 0xFFFFFFFF) as u32; c >>= 32; c += p7 as u64; self.0[7] = (c & 0xFFFFFFFF) as u32; c >>= 32; let overflow = self.check_overflow(); self.reduce(Choice::from(c as u8) | overflow); } fn mul_512(&self, b: &Scalar, l: &mut [u32; 16]) { let (mut c0, mut c1, mut c2): (u32, u32, u32) = (0, 0, 0); define_ops!(c0, c1, c2); /* l[0..15] = a[0..7] * b[0..7]. */ muladd_fast!(self.0[0], b.0[0]); l[0] = extract_fast!(); muladd!(self.0[0], b.0[1]); muladd!(self.0[1], b.0[0]); l[1] = extract!(); muladd!(self.0[0], b.0[2]); muladd!(self.0[1], b.0[1]); muladd!(self.0[2], b.0[0]); l[2] = extract!(); muladd!(self.0[0], b.0[3]); muladd!(self.0[1], b.0[2]); muladd!(self.0[2], b.0[1]); muladd!(self.0[3], b.0[0]); l[3] = extract!(); muladd!(self.0[0], b.0[4]); muladd!(self.0[1], b.0[3]); muladd!(self.0[2], b.0[2]); muladd!(self.0[3], b.0[1]); muladd!(self.0[4], b.0[0]); l[4] = extract!(); muladd!(self.0[0], b.0[5]); muladd!(self.0[1], b.0[4]); muladd!(self.0[2], b.0[3]); muladd!(self.0[3], b.0[2]); muladd!(self.0[4], b.0[1]); muladd!(self.0[5], b.0[0]); l[5] = extract!(); muladd!(self.0[0], b.0[6]); muladd!(self.0[1], b.0[5]); muladd!(self.0[2], b.0[4]); muladd!(self.0[3], b.0[3]); muladd!(self.0[4], b.0[2]); muladd!(self.0[5], b.0[1]); muladd!(self.0[6], b.0[0]); l[6] = extract!(); muladd!(self.0[0], b.0[7]); muladd!(self.0[1], b.0[6]); muladd!(self.0[2], b.0[5]); muladd!(self.0[3], b.0[4]); muladd!(self.0[4], b.0[3]); muladd!(self.0[5], b.0[2]); muladd!(self.0[6], b.0[1]); muladd!(self.0[7], b.0[0]); l[7] = extract!(); muladd!(self.0[1], b.0[7]); muladd!(self.0[2], b.0[6]); muladd!(self.0[3], b.0[5]); muladd!(self.0[4], b.0[4]); muladd!(self.0[5], b.0[3]); muladd!(self.0[6], b.0[2]); muladd!(self.0[7], b.0[1]); l[8] = extract!(); muladd!(self.0[2], b.0[7]); muladd!(self.0[3], b.0[6]); muladd!(self.0[4], b.0[5]); muladd!(self.0[5], b.0[4]); muladd!(self.0[6], b.0[3]); muladd!(self.0[7], b.0[2]); l[9] = extract!(); muladd!(self.0[3], b.0[7]); muladd!(self.0[4], b.0[6]); muladd!(self.0[5], b.0[5]); muladd!(self.0[6], b.0[4]); muladd!(self.0[7], b.0[3]); l[10] = extract!(); muladd!(self.0[4], b.0[7]); muladd!(self.0[5], b.0[6]); muladd!(self.0[6], b.0[5]); muladd!(self.0[7], b.0[4]); l[11] = extract!(); muladd!(self.0[5], b.0[7]); muladd!(self.0[6], b.0[6]); muladd!(self.0[7], b.0[5]); l[12] = extract!(); muladd!(self.0[6], b.0[7]); muladd!(self.0[7], b.0[6]); l[13] = extract!(); muladd_fast!(self.0[7], b.0[7]); l[14] = extract_fast!(); debug_assert!(c1 == 0); l[15] = c0; } fn sqr_512(&self, l: &mut [u32; 16]) { let (mut c0, mut c1, mut c2): (u32, u32, u32) = (0, 0, 0); define_ops!(c0, c1, c2); /* l[0..15] = a[0..7]^2. */ muladd_fast!(self.0[0], self.0[0]); l[0] = extract_fast!(); muladd2!(self.0[0], self.0[1]); l[1] = extract!(); muladd2!(self.0[0], self.0[2]); muladd!(self.0[1], self.0[1]); l[2] = extract!(); muladd2!(self.0[0], self.0[3]); muladd2!(self.0[1], self.0[2]); l[3] = extract!(); muladd2!(self.0[0], self.0[4]); muladd2!(self.0[1], self.0[3]); muladd!(self.0[2], self.0[2]); l[4] = extract!(); muladd2!(self.0[0], self.0[5]); muladd2!(self.0[1], self.0[4]); muladd2!(self.0[2], self.0[3]); l[5] = extract!(); muladd2!(self.0[0], self.0[6]); muladd2!(self.0[1], self.0[5]); muladd2!(self.0[2], self.0[4]); muladd!(self.0[3], self.0[3]); l[6] = extract!(); muladd2!(self.0[0], self.0[7]); muladd2!(self.0[1], self.0[6]); muladd2!(self.0[2], self.0[5]); muladd2!(self.0[3], self.0[4]); l[7] = extract!(); muladd2!(self.0[1], self.0[7]); muladd2!(self.0[2], self.0[6]); muladd2!(self.0[3], self.0[5]); muladd!(self.0[4], self.0[4]); l[8] = extract!(); muladd2!(self.0[2], self.0[7]); muladd2!(self.0[3], self.0[6]); muladd2!(self.0[4], self.0[5]); l[9] = extract!(); muladd2!(self.0[3], self.0[7]); muladd2!(self.0[4], self.0[6]); muladd!(self.0[5], self.0[5]); l[10] = extract!(); muladd2!(self.0[4], self.0[7]); muladd2!(self.0[5], self.0[6]); l[11] = extract!(); muladd2!(self.0[5], self.0[7]); muladd!(self.0[6], self.0[6]); l[12] = extract!(); muladd2!(self.0[6], self.0[7]); l[13] = extract!(); muladd_fast!(self.0[7], self.0[7]); l[14] = extract_fast!(); debug_assert!(c1 == 0); l[15] = c0; } pub fn mul_in_place(&mut self, a: &Scalar, b: &Scalar) { let mut l = [0u32; 16]; a.mul_512(b, &mut l); self.reduce_512(&l); } /// Shift a scalar right by some amount strictly between 0 and 16, /// returning the low bits that were shifted off. pub fn shr_int(&mut self, n: usize) -> u32 { let ret: u32; debug_assert!(n > 0); debug_assert!(n < 16); ret = self.0[0] & ((1 << n) - 1); self.0[0] = (self.0[0] >> n) + (self.0[1] << (32 - n)); self.0[1] = (self.0[1] >> n) + (self.0[2] << (32 - n)); self.0[2] = (self.0[2] >> n) + (self.0[3] << (32 - n)); self.0[3] = (self.0[3] >> n) + (self.0[4] << (32 - n)); self.0[4] = (self.0[4] >> n) + (self.0[5] << (32 - n)); self.0[5] = (self.0[5] >> n) + (self.0[6] << (32 - n)); self.0[6] = (self.0[6] >> n) + (self.0[7] << (32 - n)); self.0[7] >>= n; ret } pub fn sqr_in_place(&mut self, a: &Scalar) { let mut l = [0u32; 16]; a.sqr_512(&mut l); self.reduce_512(&l); } pub fn sqr(&self) -> Scalar { let mut ret = Scalar::default(); ret.sqr_in_place(self); ret } pub fn inv_in_place(&mut self, x: &Scalar) { let u2 = x.sqr(); let x2 = u2 * *x; let u5 = u2 * x2; let x3 = u5 * u2; let u9 = x3 * u2; let u11 = u9 * u2; let u13 = u11 * u2; let mut x6 = u13.sqr(); x6 = x6.sqr(); x6 *= &u11; let mut x8 = x6.sqr(); x8 = x8.sqr(); x8 *= &x2; let mut x14 = x8.sqr(); for _ in 0..5 { x14 = x14.sqr(); } x14 *= &x6; let mut x28 = x14.sqr(); for _ in 0..13 { x28 = x28.sqr(); } x28 *= &x14; let mut x56 = x28.sqr(); for _ in 0..27 { x56 = x56.sqr(); } x56 *= &x28; let mut x112 = x56.sqr(); for _ in 0..55 { x112 = x112.sqr(); } x112 *= &x56; let mut x126 = x112.sqr(); for _ in 0..13 { x126 = x126.sqr(); } x126 *= &x14; let mut t = x126; for _ in 0..3 { t = t.sqr(); } t *= &u5; for _ in 0..4 { t = t.sqr(); } t *= &x3; for _ in 0..4 { t = t.sqr(); } t *= &u5; for _ in 0..5 { t = t.sqr(); } t *= &u11; for _ in 0..4 { t = t.sqr(); } t *= &u11; for _ in 0..4 { t = t.sqr(); } t *= &x3; for _ in 0..5 { t = t.sqr(); } t *= &x3; for _ in 0..6 { t = t.sqr(); } t *= &u13; for _ in 0..4 { t = t.sqr(); } t *= &u5; for _ in 0..3 { t = t.sqr(); } t *= &x3; for _ in 0..5 { t = t.sqr(); } t *= &u9; for _ in 0..6 { t = t.sqr(); } t *= &u5; for _ in 0..10 { t = t.sqr(); } t *= &x3; for _ in 0..4 { t = t.sqr(); } t *= &x3; for _ in 0..9 { t = t.sqr(); } t *= &x8; for _ in 0..5 { t = t.sqr(); } t *= &u9; for _ in 0..6 { t = t.sqr(); } t *= &u11; for _ in 0..4 { t = t.sqr(); } t *= &u13; for _ in 0..5 { t = t.sqr(); } t *= &x2; for _ in 0..6 { t = t.sqr(); } t *= &u13; for _ in 0..10 { t = t.sqr(); } t *= &u13; for _ in 0..4 { t = t.sqr(); } t *= &u9; for _ in 0..6 { t = t.sqr(); } t *= x; for _ in 0..8 { t = t.sqr(); } *self = t * x6; } pub fn inv(&self) -> Scalar { let mut ret = Scalar::default(); ret.inv_in_place(self); ret } pub fn inv_var(&self) -> Scalar { self.inv() } pub fn is_even(&self) -> bool { self.0[0] & 1 == 0 } } impl Default for Scalar { fn default() -> Scalar { Scalar([0u32; 8]) } } impl Add for Scalar { type Output = Scalar; fn add(mut self, other: Scalar) -> Scalar { self.add_assign(&other); self } } impl<'a, 'b> Add<&'a Scalar> for &'b Scalar { type Output = Scalar; fn add(self, other: &'a Scalar) -> Scalar { let mut ret = *self; ret.add_assign(other); ret } } impl<'a> AddAssign<&'a Scalar> for Scalar { fn add_assign(&mut self, other: &'a Scalar) { let mut t = 0u64; unroll! { for i in 0..8 { t += (self.0[i] as u64) + (other.0[i] as u64); self.0[i] = (t & 0xFFFFFFFF) as u32; t >>= 32; } } let overflow = self.check_overflow(); self.reduce(Choice::from(t as u8) | overflow); } } impl AddAssign for Scalar { fn add_assign(&mut self, other: Scalar) { self.add_assign(&other) } } impl Mul for Scalar { type Output = Scalar; fn mul(self, other: Scalar) -> Scalar { let mut ret = Scalar::default(); ret.mul_in_place(&self, &other); ret } } impl<'a, 'b> Mul<&'a Scalar> for &'b Scalar { type Output = Scalar; fn mul(self, other: &'a Scalar) -> Scalar { let mut ret = Scalar::default(); ret.mul_in_place(self, other); ret } } impl<'a> MulAssign<&'a Scalar> for Scalar { fn mul_assign(&mut self, other: &'a Scalar) { let mut ret = Scalar::default(); ret.mul_in_place(self, other); *self = ret; } } impl MulAssign for Scalar { fn mul_assign(&mut self, other: Scalar) { self.mul_assign(&other) } } impl Neg for Scalar { type Output = Scalar; fn neg(mut self) -> Scalar { self.cond_neg_assign(1.into()); self } } impl<'a> Neg for &'a Scalar { type Output = Scalar; fn neg(self) -> Scalar { let value = *self; -value } } impl core::fmt::LowerHex for Scalar { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { for word in &self.0[..] { for byte in word.to_be_bytes().iter() { write!(f, "{:02x}", byte)?; } } Ok(()) } } ================================================ FILE: gen/ecmult/Cargo.toml ================================================ [package] name = "libsecp256k1-gen-ecmult" description = "Generator function of const_gen for libsecp256k1." license = "Apache-2.0" version = "0.3.0" authors = ["Wei Tang "] edition = "2018" repository = "https://github.com/paritytech/libsecp256k1" keywords = ["crypto", "ECDSA", "secp256k1", "bitcoin", "no_std"] [dependencies] libsecp256k1-core = { version = "0.3.0", path = "../../core" } ================================================ FILE: gen/ecmult/src/lib.rs ================================================ use libsecp256k1_core::curve::ECMultContext; use std::{ fs::File, io::{Error, Write}, }; pub fn generate_to(file: &mut File) -> Result<(), Error> { let context = ECMultContext::new_boxed(); let pre_g = context.inspect_raw().as_ref(); file.write_fmt(format_args!("["))?; for pg in pre_g { file.write_fmt( format_args!( " crate::curve::AffineStorage::new(crate::curve::FieldStorage::new({}, {}, {}, {}, {}, {}, {}, {}), crate::curve::FieldStorage::new({}, {}, {}, {}, {}, {}, {}, {})),", pg.x.0[7], pg.x.0[6], pg.x.0[5], pg.x.0[4], pg.x.0[3], pg.x.0[2], pg.x.0[1], pg.x.0[0], pg.y.0[7], pg.y.0[6], pg.y.0[5], pg.y.0[4], pg.y.0[3], pg.y.0[2], pg.y.0[1], pg.y.0[0] ) )?; } file.write_fmt(format_args!("]"))?; Ok(()) } ================================================ FILE: gen/genmult/Cargo.toml ================================================ [package] name = "libsecp256k1-gen-genmult" description = "Generator function of const for libsecp256k1." license = "Apache-2.0" version = "0.3.0" authors = ["Wei Tang "] edition = "2018" repository = "https://github.com/paritytech/libsecp256k1" keywords = ["crypto", "ECDSA", "secp256k1", "bitcoin", "no_std"] [dependencies] libsecp256k1-core = { version = "0.3.0", path = "../../core" } ================================================ FILE: gen/genmult/src/lib.rs ================================================ #![allow(clippy::needless_range_loop)] use libsecp256k1_core::curve::ECMultGenContext; use std::{ fs::File, io::{Error, Write}, }; pub fn generate_to(file: &mut File) -> Result<(), Error> { let context = ECMultGenContext::new_boxed(); let prec = context.inspect_raw().as_ref(); file.write_fmt(format_args!("["))?; for j in 0..64 { file.write_fmt(format_args!(" ["))?; for i in 0..16 { let pg = prec[j][i]; file.write_fmt(format_args!( " crate::curve::AffineStorage::new(crate::curve::FieldStorage::new({}, {}, {}, {}, {}, {}, {}, {}), crate::curve::FieldStorage::new({}, {}, {}, {}, {}, {}, {}, {})),", pg.x.0[7], pg.x.0[6], pg.x.0[5], pg.x.0[4], pg.x.0[3], pg.x.0[2], pg.x.0[1], pg.x.0[0], pg.y.0[7], pg.y.0[6], pg.y.0[5], pg.y.0[4], pg.y.0[3], pg.y.0[2], pg.y.0[1], pg.y.0[0] ))?; } file.write_fmt(format_args!(" ],"))?; } file.write_fmt(format_args!("]"))?; Ok(()) } ================================================ FILE: res/ecdsa_secp256k1_sha256_test.json ================================================ { "algorithm" : "ECDSA", "generatorVersion" : "0.8r12", "numberOfTests" : 380, "header" : [ "Test vectors of type EcdsaVerify are meant for the verification", "of ASN encoded ECDSA signatures." ], "notes" : { "BER" : "This is a signature with correct values for (r, s) but using some alternative BER encoding instead of DER encoding. Implementations should not accept such signatures to limit signature malleability.", "EdgeCase" : "Edge case values such as r=1 and s=0 can lead to forgeries if the ECDSA implementation does not check boundaries and computes s^(-1)==0.", "MissingZero" : "Some implementations of ECDSA and DSA incorrectly encode r and s by not including leading zeros in the ASN encoding of integers when necessary. Hence, some implementations (e.g. jdk) allow signatures with incorrect ASN encodings assuming that the signature is otherwise valid.", "PointDuplication" : "Some implementations of ECDSA do not handle duplication and points at infinity correctly. This is a test vector that has been specially crafted to check for such an omission." }, "schema" : "ecdsa_verify_schema.json", "testGroups" : [ { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", "wx" : "00b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6f", "wy" : "00f0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuDj/ROW8F3vyEYnQdmCC/J2EMiaIf8l2\nA3EQC37iCm/wyddb+6ezGmvKGXRJbutW3jVwcZVdg8Sxutqgshgy6Q==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 1, "comment" : "signature malleability", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022100900e75ad233fcc908509dbff5922647db37c21f4afd3203ae8dc4ae7794b0f87", "result" : "valid", "flags" : [] }, { "tcId" : 2, "comment" : "Legacy:ASN encoding of r misses leading 0", "msg" : "313233343030", "sig" : "30440220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "acceptable", "flags" : [ "MissingZero" ] }, { "tcId" : 3, "comment" : "valid", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "valid", "flags" : [] }, { "tcId" : 4, "comment" : "long form encoding of length of sequence", "msg" : "313233343030", "sig" : "308145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 5, "comment" : "length of sequence contains leading 0", "msg" : "313233343030", "sig" : "30820045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 6, "comment" : "wrong length of sequence", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 7, "comment" : "wrong length of sequence", "msg" : "313233343030", "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 8, "comment" : "uint32 overflow in length of sequence", "msg" : "313233343030", "sig" : "30850100000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 9, "comment" : "uint64 overflow in length of sequence", "msg" : "313233343030", "sig" : "3089010000000000000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 10, "comment" : "length of sequence = 2**31 - 1", "msg" : "313233343030", "sig" : "30847fffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 11, "comment" : "length of sequence = 2**32 - 1", "msg" : "313233343030", "sig" : "3084ffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 12, "comment" : "length of sequence = 2**40 - 1", "msg" : "313233343030", "sig" : "3085ffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 13, "comment" : "length of sequence = 2**64 - 1", "msg" : "313233343030", "sig" : "3088ffffffffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 14, "comment" : "incorrect length of sequence", "msg" : "313233343030", "sig" : "30ff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 15, "comment" : "indefinite length without termination", "msg" : "313233343030", "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 16, "comment" : "indefinite length without termination", "msg" : "313233343030", "sig" : "3045028000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 17, "comment" : "indefinite length without termination", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502806ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 18, "comment" : "removing sequence", "msg" : "313233343030", "sig" : "", "result" : "invalid", "flags" : [] }, { "tcId" : 19, "comment" : "lonely sequence tag", "msg" : "313233343030", "sig" : "30", "result" : "invalid", "flags" : [] }, { "tcId" : 20, "comment" : "appending 0's to sequence", "msg" : "313233343030", "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", "result" : "invalid", "flags" : [] }, { "tcId" : 21, "comment" : "prepending 0's to sequence", "msg" : "313233343030", "sig" : "30470000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 22, "comment" : "appending unused 0's to sequence", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", "result" : "invalid", "flags" : [] }, { "tcId" : 23, "comment" : "appending null value to sequence", "msg" : "313233343030", "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", "result" : "invalid", "flags" : [] }, { "tcId" : 24, "comment" : "including garbage", "msg" : "313233343030", "sig" : "304a4981773045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 25, "comment" : "including garbage", "msg" : "313233343030", "sig" : "304925003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 26, "comment" : "including garbage", "msg" : "313233343030", "sig" : "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", "result" : "invalid", "flags" : [] }, { "tcId" : 27, "comment" : "including garbage", "msg" : "313233343030", "sig" : "304a2226498177022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 28, "comment" : "including garbage", "msg" : "313233343030", "sig" : "304922252500022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 29, "comment" : "including garbage", "msg" : "313233343030", "sig" : "304d2223022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650004deadbeef02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 30, "comment" : "including garbage", "msg" : "313233343030", "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222549817702206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 31, "comment" : "including garbage", "msg" : "313233343030", "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652224250002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 32, "comment" : "including garbage", "msg" : "313233343030", "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", "result" : "invalid", "flags" : [] }, { "tcId" : 33, "comment" : "including undefined tags", "msg" : "313233343030", "sig" : "304daa00bb00cd003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 34, "comment" : "including undefined tags", "msg" : "313233343030", "sig" : "304baa02aabb3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 35, "comment" : "including undefined tags", "msg" : "313233343030", "sig" : "304d2229aa00bb00cd00022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 36, "comment" : "including undefined tags", "msg" : "313233343030", "sig" : "304b2227aa02aabb022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 37, "comment" : "including undefined tags", "msg" : "313233343030", "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652228aa00bb00cd0002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 38, "comment" : "including undefined tags", "msg" : "313233343030", "sig" : "304b022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652226aa02aabb02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 39, "comment" : "truncated length of sequence", "msg" : "313233343030", "sig" : "3081", "result" : "invalid", "flags" : [] }, { "tcId" : 40, "comment" : "using composition with indefinite length", "msg" : "313233343030", "sig" : "30803045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", "result" : "invalid", "flags" : [] }, { "tcId" : 41, "comment" : "using composition with indefinite length", "msg" : "313233343030", "sig" : "30492280022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 42, "comment" : "using composition with indefinite length", "msg" : "313233343030", "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", "result" : "invalid", "flags" : [] }, { "tcId" : 43, "comment" : "using composition with wrong tag", "msg" : "313233343030", "sig" : "30803145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", "result" : "invalid", "flags" : [] }, { "tcId" : 44, "comment" : "using composition with wrong tag", "msg" : "313233343030", "sig" : "30492280032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 45, "comment" : "using composition with wrong tag", "msg" : "313233343030", "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228003206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", "result" : "invalid", "flags" : [] }, { "tcId" : 46, "comment" : "Replacing sequence with NULL", "msg" : "313233343030", "sig" : "0500", "result" : "invalid", "flags" : [] }, { "tcId" : 47, "comment" : "changing tag value of sequence", "msg" : "313233343030", "sig" : "2e45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 48, "comment" : "changing tag value of sequence", "msg" : "313233343030", "sig" : "2f45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 49, "comment" : "changing tag value of sequence", "msg" : "313233343030", "sig" : "3145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 50, "comment" : "changing tag value of sequence", "msg" : "313233343030", "sig" : "3245022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 51, "comment" : "changing tag value of sequence", "msg" : "313233343030", "sig" : "ff45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 52, "comment" : "dropping value of sequence", "msg" : "313233343030", "sig" : "3000", "result" : "invalid", "flags" : [] }, { "tcId" : 53, "comment" : "using composition for sequence", "msg" : "313233343030", "sig" : "304930010230442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 54, "comment" : "truncated sequence", "msg" : "313233343030", "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", "result" : "invalid", "flags" : [] }, { "tcId" : 55, "comment" : "truncated sequence", "msg" : "313233343030", "sig" : "30442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 56, "comment" : "indefinite length", "msg" : "313233343030", "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 57, "comment" : "indefinite length with truncated delimiter", "msg" : "313233343030", "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba00", "result" : "invalid", "flags" : [] }, { "tcId" : 58, "comment" : "indefinite length with additional element", "msg" : "313233343030", "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba05000000", "result" : "invalid", "flags" : [] }, { "tcId" : 59, "comment" : "indefinite length with truncated element", "msg" : "313233343030", "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba060811220000", "result" : "invalid", "flags" : [] }, { "tcId" : 60, "comment" : "indefinite length with garbage", "msg" : "313233343030", "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000fe02beef", "result" : "invalid", "flags" : [] }, { "tcId" : 61, "comment" : "indefinite length with nonempty EOC", "msg" : "313233343030", "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0002beef", "result" : "invalid", "flags" : [] }, { "tcId" : 62, "comment" : "prepend empty sequence", "msg" : "313233343030", "sig" : "30473000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 63, "comment" : "append empty sequence", "msg" : "313233343030", "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba3000", "result" : "invalid", "flags" : [] }, { "tcId" : 64, "comment" : "append garbage with high tag number", "msg" : "313233343030", "sig" : "3048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31babf7f00", "result" : "invalid", "flags" : [] }, { "tcId" : 65, "comment" : "sequence of sequence", "msg" : "313233343030", "sig" : "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 66, "comment" : "truncated sequence: removed last 1 elements", "msg" : "313233343030", "sig" : "3023022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365", "result" : "invalid", "flags" : [] }, { "tcId" : 67, "comment" : "repeating element in sequence", "msg" : "313233343030", "sig" : "3067022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 68, "comment" : "long form encoding of length of integer", "msg" : "313233343030", "sig" : "304602812100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 69, "comment" : "long form encoding of length of integer", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 70, "comment" : "length of integer contains leading 0", "msg" : "313233343030", "sig" : "30470282002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 71, "comment" : "length of integer contains leading 0", "msg" : "313233343030", "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028200206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 72, "comment" : "wrong length of integer", "msg" : "313233343030", "sig" : "3045022200813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 73, "comment" : "wrong length of integer", "msg" : "313233343030", "sig" : "3045022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 74, "comment" : "wrong length of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502216ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 75, "comment" : "wrong length of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 76, "comment" : "uint32 overflow in length of integer", "msg" : "313233343030", "sig" : "304a0285010000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 77, "comment" : "uint32 overflow in length of integer", "msg" : "313233343030", "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028501000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 78, "comment" : "uint64 overflow in length of integer", "msg" : "313233343030", "sig" : "304e028901000000000000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 79, "comment" : "uint64 overflow in length of integer", "msg" : "313233343030", "sig" : "304e022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502890100000000000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 80, "comment" : "length of integer = 2**31 - 1", "msg" : "313233343030", "sig" : "304902847fffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 81, "comment" : "length of integer = 2**31 - 1", "msg" : "313233343030", "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502847fffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 82, "comment" : "length of integer = 2**32 - 1", "msg" : "313233343030", "sig" : "30490284ffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 83, "comment" : "length of integer = 2**32 - 1", "msg" : "313233343030", "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650284ffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 84, "comment" : "length of integer = 2**40 - 1", "msg" : "313233343030", "sig" : "304a0285ffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 85, "comment" : "length of integer = 2**40 - 1", "msg" : "313233343030", "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650285ffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 86, "comment" : "length of integer = 2**64 - 1", "msg" : "313233343030", "sig" : "304d0288ffffffffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 87, "comment" : "length of integer = 2**64 - 1", "msg" : "313233343030", "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650288ffffffffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 88, "comment" : "incorrect length of integer", "msg" : "313233343030", "sig" : "304502ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 89, "comment" : "incorrect length of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 90, "comment" : "removing integer", "msg" : "313233343030", "sig" : "302202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 91, "comment" : "lonely integer tag", "msg" : "313233343030", "sig" : "30230202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 92, "comment" : "lonely integer tag", "msg" : "313233343030", "sig" : "3024022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502", "result" : "invalid", "flags" : [] }, { "tcId" : 93, "comment" : "appending 0's to integer", "msg" : "313233343030", "sig" : "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 94, "comment" : "appending 0's to integer", "msg" : "313233343030", "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", "result" : "invalid", "flags" : [] }, { "tcId" : 95, "comment" : "prepending 0's to integer", "msg" : "313233343030", "sig" : "30470223000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 96, "comment" : "prepending 0's to integer", "msg" : "313233343030", "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022200006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [ "BER" ] }, { "tcId" : 97, "comment" : "appending unused 0's to integer", "msg" : "313233343030", "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 98, "comment" : "appending null value to integer", "msg" : "313233343030", "sig" : "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 99, "comment" : "appending null value to integer", "msg" : "313233343030", "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", "result" : "invalid", "flags" : [] }, { "tcId" : 100, "comment" : "truncated length of integer", "msg" : "313233343030", "sig" : "3024028102206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 101, "comment" : "truncated length of integer", "msg" : "313233343030", "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281", "result" : "invalid", "flags" : [] }, { "tcId" : 102, "comment" : "Replacing integer with NULL", "msg" : "313233343030", "sig" : "3024050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 103, "comment" : "Replacing integer with NULL", "msg" : "313233343030", "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650500", "result" : "invalid", "flags" : [] }, { "tcId" : 104, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 105, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045012100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 106, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 107, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045042100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 108, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045ff2100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 109, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236500206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 110, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236501206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 111, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236503206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 112, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236504206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 113, "comment" : "changing tag value of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365ff206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 114, "comment" : "dropping value of integer", "msg" : "313233343030", "sig" : "3024020002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 115, "comment" : "dropping value of integer", "msg" : "313233343030", "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650200", "result" : "invalid", "flags" : [] }, { "tcId" : 116, "comment" : "using composition for integer", "msg" : "313233343030", "sig" : "304922250201000220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 117, "comment" : "using composition for integer", "msg" : "313233343030", "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222402016f021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 118, "comment" : "modify first byte of integer", "msg" : "313233343030", "sig" : "3045022102813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 119, "comment" : "modify first byte of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206df18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 120, "comment" : "modify last byte of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323e502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 121, "comment" : "modify last byte of integer", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb313a", "result" : "invalid", "flags" : [] }, { "tcId" : 122, "comment" : "truncated integer", "msg" : "313233343030", "sig" : "3044022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832302206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 123, "comment" : "truncated integer", "msg" : "313233343030", "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", "result" : "invalid", "flags" : [] }, { "tcId" : 124, "comment" : "truncated integer", "msg" : "313233343030", "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 125, "comment" : "leading ff in integer", "msg" : "313233343030", "sig" : "30460222ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 126, "comment" : "leading ff in integer", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 127, "comment" : "replaced integer by infinity", "msg" : "313233343030", "sig" : "302509018002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 128, "comment" : "replaced integer by infinity", "msg" : "313233343030", "sig" : "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365090180", "result" : "invalid", "flags" : [] }, { "tcId" : 129, "comment" : "replacing integer with zero", "msg" : "313233343030", "sig" : "302502010002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 130, "comment" : "replacing integer with zero", "msg" : "313233343030", "sig" : "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365020100", "result" : "invalid", "flags" : [] }, { "tcId" : 131, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "3045022101813ef79ccefa9a56f7ba805f0e478583b90deabca4b05c4574e49b5899b964a602206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 132, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "30440220813ef79ccefa9a56f7ba805f0e47858643b030ef461f1bcdf53fde3ef94ce22402206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 133, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "30450221ff7ec10863310565a908457fa0f1b87a7b01a0f22a0a9843f64aedc334367cdc9b02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 134, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "304402207ec10863310565a908457fa0f1b87a79bc4fcf10b9e0e4320ac021c106b31ddc02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 135, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "30450221fe7ec10863310565a908457fa0f1b87a7c46f215435b4fa3ba8b1b64a766469b5a02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 136, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "3045022101813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 137, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "304402207ec10863310565a908457fa0f1b87a7b01a0f22a0a9843f64aedc334367cdc9b02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 138, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221016ff18a52dcc0336f7af62400a6dd9b7fc1e197d8aebe203c96c87232272172fb", "result" : "invalid", "flags" : [] }, { "tcId" : 139, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221ff6ff18a52dcc0336f7af62400a6dd9b824c83de0b502cdfc51723b51886b4f079", "result" : "invalid", "flags" : [] }, { "tcId" : 140, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650220900e75ad233fcc908509dbff5922647ef8cd450e008a7fff2909ec5aa914ce46", "result" : "invalid", "flags" : [] }, { "tcId" : 141, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221fe900e75ad233fcc908509dbff592264803e1e68275141dfc369378dcdd8de8d05", "result" : "invalid", "flags" : [] }, { "tcId" : 142, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221016ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", "result" : "invalid", "flags" : [] }, { "tcId" : 143, "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", "msg" : "313233343030", "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022100900e75ad233fcc908509dbff5922647ef8cd450e008a7fff2909ec5aa914ce46", "result" : "invalid", "flags" : [] }, { "tcId" : 144, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3006020100020100", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 145, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3006020100020101", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 146, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30060201000201ff", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 147, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 148, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 149, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 150, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 151, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 152, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3008020100090380fe01", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 153, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3006020100090142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 154, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3006020101020100", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 155, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3006020101020101", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 156, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30060201010201ff", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 157, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 158, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 159, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 160, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 161, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 162, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3008020101090380fe01", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 163, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3006020101090142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 164, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30060201ff020100", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 165, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30060201ff020101", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 166, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30060201ff0201ff", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 167, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 168, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 169, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 170, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 171, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 172, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30080201ff090380fe01", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 173, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "30060201ff090142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 174, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020100", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 175, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 176, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 177, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 178, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 179, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 180, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 181, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 182, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090380fe01", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 183, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 184, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020100", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 185, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020101", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 186, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641400201ff", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 187, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 188, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 189, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 190, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 191, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 192, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140090380fe01", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 193, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140090142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 194, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020100", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 195, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020101", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 196, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641420201ff", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 197, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 198, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 199, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 200, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 201, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 202, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142090380fe01", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 203, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142090142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 204, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020100", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 205, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020101", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 206, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0201ff", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 207, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 208, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 209, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 210, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 211, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 212, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090380fe01", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 213, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 214, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020100", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 215, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020101", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 216, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc300201ff", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 217, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 218, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 219, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 220, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 221, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 222, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30090380fe01", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 223, "comment" : "Signature with special case values for r and s", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30090142", "result" : "invalid", "flags" : [ "EdgeCase" ] }, { "tcId" : 224, "comment" : "Signature encoding contains wrong types.", "msg" : "313233343030", "sig" : "30060201010c0130", "result" : "invalid", "flags" : [] }, { "tcId" : 225, "comment" : "Signature encoding contains wrong types.", "msg" : "313233343030", "sig" : "30050201010c00", "result" : "invalid", "flags" : [] }, { "tcId" : 226, "comment" : "Signature encoding contains wrong types.", "msg" : "313233343030", "sig" : "30090c0225730c03732573", "result" : "invalid", "flags" : [] }, { "tcId" : 227, "comment" : "Signature encoding contains wrong types.", "msg" : "313233343030", "sig" : "30080201013003020100", "result" : "invalid", "flags" : [] }, { "tcId" : 228, "comment" : "Signature encoding contains wrong types.", "msg" : "313233343030", "sig" : "3003020101", "result" : "invalid", "flags" : [] }, { "tcId" : 229, "comment" : "Signature encoding contains wrong types.", "msg" : "313233343030", "sig" : "3006020101010100", "result" : "invalid", "flags" : [] }, { "tcId" : 230, "comment" : "Edge case for Shamir multiplication", "msg" : "3235353835", "sig" : "3045022100dd1b7d09a7bd8218961034a39a87fecf5314f00c4d25eb58a07ac85e85eab516022035138c401ef8d3493d65c9002fe62b43aee568731b744548358996d9cc427e06", "result" : "valid", "flags" : [] }, { "tcId" : 231, "comment" : "special case hash", "msg" : "343236343739373234", "sig" : "304502210095c29267d972a043d955224546222bba343fc1d4db0fec262a33ac61305696ae02206edfe96713aed56f8a28a6653f57e0b829712e5eddc67f34682b24f0676b2640", "result" : "valid", "flags" : [] }, { "tcId" : 232, "comment" : "special case hash", "msg" : "37313338363834383931", "sig" : "3045022028f94a894e92024699e345fe66971e3edcd050023386135ab3939d550898fb25022100cd69c1a42be05a6ee1270c821479251e134c21858d800bda6f4e98b37196238e", "result" : "valid", "flags" : [] }, { "tcId" : 233, "comment" : "special case hash", "msg" : "3130333539333331363638", "sig" : "3046022100be26b18f9549f89f411a9b52536b15aa270b84548d0e859a1952a27af1a77ac60221008f3e2b05632fc33715572af9124681113f2b84325b80154c044a544dc1a8fa12", "result" : "valid", "flags" : [] }, { "tcId" : 234, "comment" : "special case hash", "msg" : "33393439343031323135", "sig" : "3046022100b1a4b1478e65cc3eafdf225d1298b43f2da19e4bcff7eacc0a2e98cd4b74b114022100e8655ce1cfb33ebd30af8ce8e8ae4d6f7b50cd3e22af51bf69e0a2851760d52b", "result" : "valid", "flags" : [] }, { "tcId" : 235, "comment" : "special case hash", "msg" : "31333434323933303739", "sig" : "30440220325332021261f1bd18f2712aa1e2252da23796da8a4b1ff6ea18cafec7e171f2022040b4f5e287ee61fc3c804186982360891eaa35c75f05a43ecd48b35d984a6648", "result" : "valid", "flags" : [] }, { "tcId" : 236, "comment" : "special case hash", "msg" : "33373036323131373132", "sig" : "3046022100a23ad18d8fc66d81af0903890cbd453a554cb04cdc1a8ca7f7f78e5367ed88a0022100dc1c14d31e3fb158b73c764268c8b55579734a7e2a2c9b5ee5d9d0144ef652eb", "result" : "valid", "flags" : [] }, { "tcId" : 237, "comment" : "special case hash", "msg" : "333433363838373132", "sig" : "304502202bdea41cda63a2d14bf47353bd20880a690901de7cd6e3cc6d8ed5ba0cdb1091022100c31599433036064073835b1e3eba8335a650c8fd786f94fe235ad7d41dc94c7a", "result" : "valid", "flags" : [] }, { "tcId" : 238, "comment" : "special case hash", "msg" : "31333531353330333730", "sig" : "3046022100d7cd76ec01c1b1079eba9e2aa2a397243c4758c98a1ba0b7404a340b9b00ced6022100ca8affe1e626dd192174c2937b15bc48f77b5bdfe01f073a8aeaf7f24dc6c85b", "result" : "valid", "flags" : [] }, { "tcId" : 239, "comment" : "special case hash", "msg" : "36353533323033313236", "sig" : "3045022100a872c744d936db21a10c361dd5c9063355f84902219652f6fc56dc95a7139d960220400df7575d9756210e9ccc77162c6b593c7746cfb48ac263c42750b421ef4bb9", "result" : "valid", "flags" : [] }, { "tcId" : 240, "comment" : "special case hash", "msg" : "31353634333436363033", "sig" : "30460221009fa9afe07752da10b36d3afcd0fe44bfc40244d75203599cf8f5047fa3453854022100af1f583fec4040ae7e68c968d2bb4b494eec3a33edc7c0ccf95f7f75bc2569c7", "result" : "valid", "flags" : [] }, { "tcId" : 241, "comment" : "special case hash", "msg" : "34343239353339313137", "sig" : "3045022100885640384d0d910efb177b46be6c3dc5cac81f0b88c3190bb6b5f99c2641f2050220738ed9bff116306d9caa0f8fc608be243e0b567779d8dab03e8e19d553f1dc8e", "result" : "valid", "flags" : [] }, { "tcId" : 242, "comment" : "special case hash", "msg" : "3130393533323631333531", "sig" : "304502202d051f91c5a9d440c5676985710483bc4f1a6c611b10c95a2ff0363d90c2a45802210092206b19045a41a797cc2f3ac30de9518165e96d5b86341ecb3bcff231b3fd65", "result" : "valid", "flags" : [] }, { "tcId" : 243, "comment" : "special case hash", "msg" : "35393837333530303431", "sig" : "3045022100f3ac2523967482f53d508522712d583f4379cd824101ff635ea0935117baa54f022027f10812227397e02cea96fb0e680761636dab2b080d1fc5d11685cbe8500cfe", "result" : "valid", "flags" : [] }, { "tcId" : 244, "comment" : "special case hash", "msg" : "33343633303036383738", "sig" : "304602210096447cf68c3ab7266ed7447de3ac52fed7cc08cbdfea391c18a9b8ab370bc913022100f0a1878b2c53f16e70fe377a5e9c6e86f18ae480a22bb499f5b32e7109c07385", "result" : "valid", "flags" : [] }, { "tcId" : 245, "comment" : "special case hash", "msg" : "39383137333230323837", "sig" : "30450220530a0832b691da0b5619a0b11de6877f3c0971baaa68ed122758c29caaf46b7202210093761bb0a14ccf9f15b4b9ce73c6ec700bd015b8cb1cfac56837f4463f53074e", "result" : "valid", "flags" : [] }, { "tcId" : 246, "comment" : "special case hash", "msg" : "33323232303431303436", "sig" : "30460221009c54c25500bde0b92d72d6ec483dc2482f3654294ca74de796b681255ed58a77022100988bac394a90ad89ce360984c0c149dcbd2684bb64498ace90bcf6b6af1c170e", "result" : "valid", "flags" : [] }, { "tcId" : 247, "comment" : "special case hash", "msg" : "36363636333037313034", "sig" : "3045022100e7909d41439e2f6af29136c7348ca2641a2b070d5b64f91ea9da7070c7a2618b022042d782f132fa1d36c2c88ba27c3d678d80184a5d1eccac7501f0b47e3d205008", "result" : "valid", "flags" : [] }, { "tcId" : 248, "comment" : "special case hash", "msg" : "31303335393531383938", "sig" : "304502205924873209593135a4c3da7bb381227f8a4b6aa9f34fe5bb7f8fbc131a039ffe022100e0e44ee4bbe370155bf0bbdec265bf9fe31c0746faab446de62e3631eacd111f", "result" : "valid", "flags" : [] }, { "tcId" : 249, "comment" : "special case hash", "msg" : "31383436353937313935", "sig" : "3045022100eeb692c9b262969b231c38b5a7f60649e0c875cd64df88f33aa571fa3d29ab0e0220218b3a1eb06379c2c18cf51b06430786d1c64cd2d24c9b232b23e5bac7989acd", "result" : "valid", "flags" : [] }, { "tcId" : 250, "comment" : "special case hash", "msg" : "33313336303436313839", "sig" : "3045022100a40034177f36091c2b653684a0e3eb5d4bff18e4d09f664c2800e7cafda1daf802203a3ec29853704e52031c58927a800a968353adc3d973beba9172cbbeab4dd149", "result" : "valid", "flags" : [] }, { "tcId" : 251, "comment" : "special case hash", "msg" : "32363633373834323534", "sig" : "3046022100b5d795cc75cea5c434fa4185180cd6bd21223f3d5a86da6670d71d95680dadbf022100ab1b277ef5ffe134460835e3d1402461ba104cb50b16f397fdc7a9abfefef280", "result" : "valid", "flags" : [] }, { "tcId" : 252, "comment" : "special case hash", "msg" : "31363532313030353234", "sig" : "3044022007dc2478d43c1232a4595608c64426c35510051a631ae6a5a6eb1161e57e42e102204a59ea0fdb72d12165cea3bf1ca86ba97517bd188db3dbd21a5a157850021984", "result" : "valid", "flags" : [] }, { "tcId" : 253, "comment" : "special case hash", "msg" : "35373438303831363936", "sig" : "3046022100ddd20c4a05596ca868b558839fce9f6511ddd83d1ccb53f82e5269d559a01552022100a46e8cb8d626cf6c00ddedc3b5da7e613ac376445ee260743f06f79054c7d42a", "result" : "valid", "flags" : [] }, { "tcId" : 254, "comment" : "special case hash", "msg" : "36333433393133343638", "sig" : "30450221009cde6e0ede0a003f02fda0a01b59facfe5dec063318f279ce2de7a9b1062f7b702202886a5b8c679bdf8224c66f908fd6205492cb70b0068d46ae4f33a4149b12a52", "result" : "valid", "flags" : [] }, { "tcId" : 255, "comment" : "special case hash", "msg" : "31353431313033353938", "sig" : "3046022100c5771016d0dd6357143c89f684cd740423502554c0c59aa8c99584f1ff38f609022100ab4bfa0bb88ab99791b9b3ab9c4b02bd2a57ae8dde50b9064063fcf85315cfe5", "result" : "valid", "flags" : [] }, { "tcId" : 256, "comment" : "special case hash", "msg" : "3130343738353830313238", "sig" : "3045022100a24ebc0ec224bd67ae397cbe6fa37b3125adbd34891abe2d7c7356921916dfe6022034f6eb6374731bbbafc4924fb8b0bdcdda49456d724cdae6178d87014cb53d8c", "result" : "valid", "flags" : [] }, { "tcId" : 257, "comment" : "special case hash", "msg" : "3130353336323835353638", "sig" : "304502202557d64a7aee2e0931c012e4fea1cd3a2c334edae68cdeb7158caf21b68e5a2402210080f93244956ffdc568c77d12684f7f004fa92da7e60ae94a1b98c422e23eda34", "result" : "valid", "flags" : [] }, { "tcId" : 258, "comment" : "special case hash", "msg" : "393533393034313035", "sig" : "3046022100c4f2eccbb6a24350c8466450b9d61b207ee359e037b3dcedb42a3f2e6dd6aeb5022100cd9c394a65d0aa322e391eb76b2a1a687f8620a88adef3a01eb8e4fb05b6477a", "result" : "valid", "flags" : [] }, { "tcId" : 259, "comment" : "special case hash", "msg" : "393738383438303339", "sig" : "3046022100eff04781c9cbcd162d0a25a6e2ebcca43506c523385cb515d49ea38a1b12fcad022100ea5328ce6b36e56ab87acb0dcfea498bcec1bba86a065268f6eff3c41c4b0c9c", "result" : "valid", "flags" : [] }, { "tcId" : 260, "comment" : "special case hash", "msg" : "33363130363732343432", "sig" : "3046022100f58b4e3110a64bf1b5db97639ee0e5a9c8dfa49dc59b679891f520fdf0584c87022100d32701ae777511624c1f8abbf02b248b04e7a9eb27938f524f3e8828ba40164a", "result" : "valid", "flags" : [] }, { "tcId" : 261, "comment" : "special case hash", "msg" : "31303534323430373035", "sig" : "3045022100f8abecaa4f0c502de4bf5903d48417f786bf92e8ad72fec0bd7fcb7800c0bbe302204c7f9e231076a30b7ae36b0cebe69ccef1cd194f7cce93a5588fd6814f437c0e", "result" : "valid", "flags" : [] }, { "tcId" : 262, "comment" : "special case hash", "msg" : "35313734343438313937", "sig" : "304402205d5b38bd37ad498b2227a633268a8cca879a5c7c94a4e416bd0a614d09e606d2022012b8d664ea9991062ecbb834e58400e25c46007af84f6007d7f1685443269afe", "result" : "valid", "flags" : [] }, { "tcId" : 263, "comment" : "special case hash", "msg" : "31393637353631323531", "sig" : "304402200c1cd9fe4034f086a2b52d65b9d3834d72aebe7f33dfe8f976da82648177d8e3022013105782e3d0cfe85c2778dec1a848b27ac0ae071aa6da341a9553a946b41e59", "result" : "valid", "flags" : [] }, { "tcId" : 264, "comment" : "special case hash", "msg" : "33343437323533333433", "sig" : "3045022100ae7935fb96ff246b7b5d5662870d1ba587b03d6e1360baf47988b5c02ccc1a5b02205f00c323272083782d4a59f2dfd65e49de0693627016900ef7e61428056664b3", "result" : "valid", "flags" : [] }, { "tcId" : 265, "comment" : "special case hash", "msg" : "333638323634333138", "sig" : "3045022000a134b5c6ccbcefd4c882b945baeb4933444172795fa6796aae149067547098022100a991b9efa2db276feae1c115c140770901839d87e60e7ec45a2b81cf3b437be6", "result" : "valid", "flags" : [] }, { "tcId" : 266, "comment" : "special case hash", "msg" : "33323631313938363038", "sig" : "304502202e4721363ad3992c139e5a1c26395d2c2d777824aa24fde075e0d7381171309d0221008bf083b6bbe71ecff22baed087d5a77eaeaf726bf14ace2c03fd6e37ba6c26f2", "result" : "valid", "flags" : [] }, { "tcId" : 267, "comment" : "special case hash", "msg" : "39363738373831303934", "sig" : "304502206852e9d3cd9fe373c2d504877967d365ab1456707b6817a042864694e1960ccf022100f9b4d815ebd4cf77847b37952334d05b2045cb398d4c21ba207922a7a4714d84", "result" : "valid", "flags" : [] }, { "tcId" : 268, "comment" : "special case hash", "msg" : "34393538383233383233", "sig" : "30440220188a8c5648dc79eace158cf886c62b5468f05fd95f03a7635c5b4c31f09af4c5022036361a0b571a00c6cd5e686ccbfcfa703c4f97e48938346d0c103fdc76dc5867", "result" : "valid", "flags" : [] }, { "tcId" : 269, "comment" : "special case hash", "msg" : "383234363337383337", "sig" : "3045022100a74f1fb9a8263f62fc4416a5b7d584f4206f3996bb91f6fc8e73b9e92bad0e1302206815032e8c7d76c3ab06a86f33249ce9940148cb36d1f417c2e992e801afa3fa", "result" : "valid", "flags" : [] }, { "tcId" : 270, "comment" : "special case hash", "msg" : "3131303230383333373736", "sig" : "3045022007244865b72ff37e62e3146f0dc14682badd7197799135f0b00ade7671742bfe022100f27f3ddc7124b1b58579573a835650e7a8bad5eeb96e9da215cd7bf9a2a039ed", "result" : "valid", "flags" : [] }, { "tcId" : 271, "comment" : "special case hash", "msg" : "313333383731363438", "sig" : "3045022100da7fdd05b5badabd619d805c4ee7d9a84f84ddd5cf9c5bf4d4338140d689ef08022028f1cf4fa1c3c5862cfa149c0013cf5fe6cf5076cae000511063e7de25bb38e5", "result" : "valid", "flags" : [] }, { "tcId" : 272, "comment" : "special case hash", "msg" : "333232313434313632", "sig" : "3046022100d3027c656f6d4fdfd8ede22093e3c303b0133c340d615e7756f6253aea927238022100f6510f9f371b31068d68bfeeaa720eb9bbdc8040145fcf88d4e0b58de0777d2a", "result" : "valid", "flags" : [] }, { "tcId" : 273, "comment" : "special case hash", "msg" : "3130363836363535353436", "sig" : "304402200bf6c0188dc9571cd0e21eecac5fbb19d2434988e9cc10244593ef3a98099f6902204864a562661f9221ec88e3dd0bc2f6e27ac128c30cc1a80f79ec670a22b042ee", "result" : "valid", "flags" : [] }, { "tcId" : 274, "comment" : "special case hash", "msg" : "3632313535323436", "sig" : "3045022100ae459640d5d1179be47a47fa538e16d94ddea5585e7a244804a51742c686443a02206c8e30e530a634fae80b3ceb062978b39edbe19777e0a24553b68886181fd897", "result" : "valid", "flags" : [] }, { "tcId" : 275, "comment" : "special case hash", "msg" : "37303330383138373734", "sig" : "304402201cf3517ba3bf2ab8b9ead4ebb6e866cb88a1deacb6a785d3b63b483ca02ac4950220249a798b73606f55f5f1c70de67cb1a0cff95d7dc50b3a617df861bad3c6b1c9", "result" : "valid", "flags" : [] }, { "tcId" : 276, "comment" : "special case hash", "msg" : "35393234353233373434", "sig" : "3045022100e69b5238265ea35d77e4dd172288d8cea19810a10292617d5976519dc5757cb802204b03c5bc47e826bdb27328abd38d3056d77476b2130f3df6ec4891af08ba1e29", "result" : "valid", "flags" : [] }, { "tcId" : 277, "comment" : "special case hash", "msg" : "31343935353836363231", "sig" : "304402205f9d7d7c870d085fc1d49fff69e4a275812800d2cf8973e7325866cb40fa2b6f02206d1f5491d9f717a597a15fd540406486d76a44697b3f0d9d6dcef6669f8a0a56", "result" : "valid", "flags" : [] }, { "tcId" : 278, "comment" : "special case hash", "msg" : "34303035333134343036", "sig" : "304402200a7d5b1959f71df9f817146ee49bd5c89b431e7993e2fdecab6858957da685ae02200f8aad2d254690bdc13f34a4fec44a02fd745a422df05ccbb54635a8b86b9609", "result" : "valid", "flags" : [] }, { "tcId" : 279, "comment" : "special case hash", "msg" : "33303936343537353132", "sig" : "3044022079e88bf576b74bc07ca142395fda28f03d3d5e640b0b4ff0752c6d94cd553408022032cea05bd2d706c8f6036a507e2ab7766004f0904e2e5c5862749c0073245d6a", "result" : "valid", "flags" : [] }, { "tcId" : 280, "comment" : "special case hash", "msg" : "32373834303235363230", "sig" : "30450221009d54e037a00212b377bc8874798b8da080564bbdf7e07591b861285809d01488022018b4e557667a82bd95965f0706f81a29243fbdd86968a7ebeb43069db3b18c7f", "result" : "valid", "flags" : [] }, { "tcId" : 281, "comment" : "special case hash", "msg" : "32363138373837343138", "sig" : "304402202664f1ffa982fedbcc7cab1b8bc6e2cb420218d2a6077ad08e591ba9feab33bd022049f5c7cb515e83872a3d41b4cdb85f242ad9d61a5bfc01debfbb52c6c84ba728", "result" : "valid", "flags" : [] }, { "tcId" : 282, "comment" : "special case hash", "msg" : "31363432363235323632", "sig" : "304502205827518344844fd6a7de73cbb0a6befdea7b13d2dee4475317f0f18ffc81524b022100b0a334b1f4b774a5a289f553224d286d239ef8a90929ed2d91423e024eb7fa66", "result" : "valid", "flags" : [] }, { "tcId" : 283, "comment" : "special case hash", "msg" : "36383234313839343336", "sig" : "304602210097ab19bd139cac319325869218b1bce111875d63fb12098a04b0cd59b6fdd3a3022100bce26315c5dbc7b8cfc31425a9b89bccea7aa9477d711a4d377f833dcc28f820", "result" : "valid", "flags" : [] }, { "tcId" : 284, "comment" : "special case hash", "msg" : "343834323435343235", "sig" : "3044022052c683144e44119ae2013749d4964ef67509278f6d38ba869adcfa69970e123d02203479910167408f45bda420a626ec9c4ec711c1274be092198b4187c018b562ca", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", "wx" : "07310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc362", "wy" : "26a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEBzEPkKnq4UmghAL1QZSg97SsQnv42b1s\ndoEHHcR9w2ImptN6xG1h/WAMC/G/+HaJ7RF92msOWTGK4BChl6JsoA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 285, "comment" : "k*G has a large x-coordinate", "msg" : "313233343030", "sig" : "30360211014551231950b75fc4402da1722fc9baeb022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", "result" : "valid", "flags" : [] }, { "tcId" : 286, "comment" : "r too large", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", "result" : "invalid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", "wx" : "00bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22", "wy" : "705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvJfnWF7srUjhZoO8QJFwjhqTDGg/xHAB\n1LODWU8sTiJwWYnPadrq3U5OS4FR7YiN/sIPsBco2J1Ws/OPKunIxQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 287, "comment" : "r,s are large", "msg" : "313233343030", "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", "wx" : "44ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252", "wy" : "00b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERK0zmvvCHpq/e2AqXKU16jeBNbbRDYEx\nC92Ck9HfMlK2P/fQd0dw+P4dFyL6g6zQL0NOT8EQoMyPbd3TfVbEYw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 288, "comment" : "r and s^-1 have a large Hamming weight", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203e9a7582886089c62fb840cf3b83061cd1cff3ae4341808bb5bdee6191174177", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", "wx" : "1260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c", "wy" : "5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEmDCEiyeJE4a9RUb7eDDriO1TXxZaIHT\n7rrSHzfdh4xcmgwamt52c3qIEb1qf5KHyXjuOWqonBHkcinSzLVS8A==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 289, "comment" : "r and s^-1 have a large Hamming weight", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022024238e70b431b1a64efdf9032669939d4b77f249503fc6905feb7540dea3e6d2", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", "wx" : "1877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce", "wy" : "00821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGHcEW+JdNKHQYA+dXADQZFoqVDebbO76\n0ua/XCozUs6CGlMswXUe4dNtQcPWq06bFD5E7EbXNHjqanmlwOVBWQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 290, "comment" : "small r and s", "msg" : "313233343030", "sig" : "3006020101020101", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", "wx" : "455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50", "wy" : "00aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERVQ5/MPS3uzt3q7OYOe9FzBPNuu2Aq31\noi4Ljx20alCuw4+yuvIh6ajRiHx79iIt0YNGNOdyYzFa9tI2CdBPdw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 291, "comment" : "small r and s", "msg" : "313233343030", "sig" : "3006020101020102", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", "wx" : "2e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece718", "wy" : "0449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELh9GawJMDDrOJDfeCRJ/7QS3BvlLGaIb\nscKs81zs5xgESa41I9clNOlklyz9OzivC93ZYZ5a8iPk0aQPNM+fHQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 292, "comment" : "small r and s", "msg" : "313233343030", "sig" : "3006020101020103", "result" : "valid", "flags" : [] }, { "tcId" : 293, "comment" : "r is larger than n", "msg" : "313233343030", "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020103", "result" : "invalid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04dda95d7b0698de5d2d0b4f0034dbe35b50f978fcc518a84abf9c99efd96a25305adc08d6a63dbe831ab99cd9146e3c4c45492ad19521612542256d6af60e7888", "wx" : "00dda95d7b0698de5d2d0b4f0034dbe35b50f978fcc518a84abf9c99efd96a2530", "wy" : "5adc08d6a63dbe831ab99cd9146e3c4c45492ad19521612542256d6af60e7888" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004dda95d7b0698de5d2d0b4f0034dbe35b50f978fcc518a84abf9c99efd96a25305adc08d6a63dbe831ab99cd9146e3c4c45492ad19521612542256d6af60e7888", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE3aldewaY3l0tC08ANNvjW1D5ePzFGKhK\nv5yZ79lqJTBa3AjWpj2+gxq5nNkUbjxMRUkq0ZUhYSVCJW1q9g54iA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 294, "comment" : "s is larger than n", "msg" : "313233343030", "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd04917c8", "result" : "invalid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", "wx" : "02ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee77", "wy" : "7eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAu9NbWz9WpTx13hCJuPipsCkNsVYOWGf\nOPtEcrX57nd+tKzU7r2lzXKHX/0qLyYinC3GtGUAkZpDLIZznzroZg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 295, "comment" : "small r and s^-1", "msg" : "313233343030", "sig" : "302702020101022100c58b162c58b162c58b162c58b162c58a1b242973853e16db75c8a1a71da4d39d", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", "wx" : "464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584", "wy" : "00b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERk9P9xVynK5Qcso72AHTGVtnrsZemwGq\n0gopQ9y8tYSxr9KdMaOaEdVwqhWXQ5s7LRlxvy8avxVDLQIHsQ0dCA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 296, "comment" : "smallish r and s^-1", "msg" : "313233343030", "sig" : "302c02072d9b4d347952cc022100fcbc5103d0da267477d1791461cf2aa44bf9d43198f79507bd8779d69a13108e", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", "wx" : "157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4c", "wy" : "00deadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFX+P3fNz619Jz88Q2LhTz5HLzX1mXDUi\nun3XON23mkzerfGlxEjqPJ9BkaiZmr/MdXrG1kVn7wcsR/7GE0Q7jw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 297, "comment" : "100-bit r and small s^-1", "msg" : "313233343030", "sig" : "3032020d1033e67e37b32b445580bf4efc022100906f906f906f906f906f906f906f906ed8e426f7b1968c35a204236a579723d2", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", "wx" : "0934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0", "wy" : "00d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECTSlN0ZsB0MOLEj+uZC7Gft4zsyc7kJO\npNEwKRqiN/DU+S0jtGKAS1toxSVYwByZltv3J/zKu+7bliGkAFNa+g==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 298, "comment" : "small r and 100 bit s^-1", "msg" : "313233343030", "sig" : "3026020201010220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", "wx" : "00d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c65", "wy" : "4a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1u8gvmbIk/dBqb+Q2bdGddHCoxKWOXrL\nPvF0/QswDGVKDJVHjKADmRYtfw8tyJ79wrKKMPur4oWFcpWksMTiZQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 299, "comment" : "100-bit r and s^-1", "msg" : "313233343030", "sig" : "3031020d062522bbd3ecbe7c39e93e7c260220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", "wx" : "00b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee06", "wy" : "29c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEtykdFATgwMB9q5NyGJ9L1Y0s6qjRXt5U\nTZUUVFup7gYpyaY9XjCHacww7CdqQQ5kZKJ+6v2eWZ2xDwU6T+SoKQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 300, "comment" : "r and s^-1 are close to n", "msg" : "313233343030", "sig" : "3045022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c1022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", "wx" : "00bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c", "wy" : "1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEu3n2GFf3Q7+htucRHOQJQ3claWnk4VFZ\nEj2VSKzDvmwfnZ+IYNz/0+s23Wwx/y5yJsIAnEyU2NfStWhr96vWdw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 301, "comment" : "s == 1", "msg" : "313233343030", "sig" : "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020101", "result" : "valid", "flags" : [] }, { "tcId" : 302, "comment" : "s == 0", "msg" : "313233343030", "sig" : "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020100", "result" : "invalid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", "wx" : "00d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b4150874", "wy" : "01b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1TO3iaSviQ+nqCofrljEBPmmKlC0mtr6\ns0nFE7QVCHQBtBcbgD52s0qYYeEPe8KJoGb9Ab0p+EyYehCl+xjC1A==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 303, "comment" : "point at infinity during verify", "msg" : "313233343030", "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", "result" : "invalid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", "wx" : "3a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4", "wy" : "221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOjFQeYyK9p0ebpgfOkVAK6HXMvS+gzDF\nFk9J4Q7FVbQiG9hCvF5Nl+/zcWX2DjmYpCTXKkUM+V6kd8eCh9A0Og==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 304, "comment" : "edge case for signature malleability", "msg" : "313233343030", "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", "wx" : "3b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e80", "wy" : "0de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOzffX7NHxpoPF9hcDHyoNzaIOoJeExQ9\nD8/IEB6FHoAN48CQtsohulQ1FzMMBLEvlIxrrfFKY6v/3074x1NwJg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 305, "comment" : "edge case for signature malleability", "msg" : "313233343030", "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", "wx" : "00feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82c", "wy" : "00e87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/rUWOw7OMP8+A8fVXEOA+i+oHuLANUlC\n/28IyZ0M2CzofeBe4b2gidPk4kj6D3IRAqz//fUOZUvigUM5md+Jfg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 306, "comment" : "u1 == 1", "msg" : "313233343030", "sig" : "3045022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", "wx" : "238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd4149228976", "wy" : "40683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEI4ztABzyK4hT4C7cicvspQULp+BCp6d/\nk4LNQUkiiXZAaD0wlGQ4QPKViQqkwYqjm0HXfdD7O7JwDk+ewoT/wg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 307, "comment" : "u1 == n - 1", "msg" : "313233343030", "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", "wx" : "00961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35e", "wy" : "00d2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElhz2SBfAbA5Rs8JzbJIv3hi9jEkG/Nf1\n72bEZ4UI817SxdGBaM++cPLxI710GSMruS3WkRPilBBhiJSBxaAnvw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 308, "comment" : "u2 == 1", "msg" : "313233343030", "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", "wx" : "13681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b10288", "wy" : "16528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEE2gerhaM1Op88uKkXQUnQtEKn2TnloZ9\nvcuCn+CxAogWUodg0Xc3bAnfed45VXwynMF1NRes/+j6LsKYAmuDhA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 309, "comment" : "u2 == n - 1", "msg" : "313233343030", "sig" : "3045022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b89", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", "wx" : "5aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c2", "wy" : "0091c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWqer/ba0CG1UMyXl15xulc5C+GbSu4SQ\nljOgS7GqMcKRyACIeUkF4dozM22HTi+RzPRcxZGFvt5d1vP3rKrhiw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 310, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100e91e1ba6ba898620a46bcb51dc0b8b4ad1dc35dad892c4552d1847b2ce444637", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", "wx" : "277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e4", "wy" : "64108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEACd3kbMFpFsrOVkLLwXTOSpsgYLO9OtU\nASDg9cIGw+RkEIIz+wuMOsiS15744Pv5LtEzrdtFVCcBMlhNxS7vQQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 311, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100e36bf0cec06d9b841da81332812f74f30bbaec9f202319206c6f0b8a0a400ff7", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", "wx" : "6efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1a", "wy" : "00c75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbvoJK2jelGDwvMkZAFpfboDhnemJaL48\n0sdwqZSb+xrHXm5Qh9ZVDV+b6x555QKTB7wlUjXi1dyZJBrDq4hsSQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 312, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100ea26b57af884b6c06e348efe139c1e4e9ec9518d60c340f6bac7d278ca08d8a6", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", "wx" : "72d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058", "wy" : "00e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEctShnE+dLPWEjqQERbcNRpa18C1jLAxl\nTMfX7rDG0FjoxM2ZQ+RZF0x6wB+nQhmOR+bBmmvbDE9sI3gxwbP5Qg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 313, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205b1d27a7694c146244a5ad0bd0636d9d9ef3b9fb58385418d9c982105077d1b7", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", "wx" : "2a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e7402", "wy" : "58f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEKo6i9Q3M7QwhdXW9+nzUfRxvEABB7A41\nUSeUwb5+dAJY+MFxIu0wP9pxQ+tYvt5wKVtlMmYBOwsOvT8FMTf27A==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 314, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100d27a7694c146244a5ad0bd0636d9e12abe687897e8e9998ddbd4e59a78520d0f", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", "wx" : "0088de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b8", "wy" : "0c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiN5onOmvHpS+aiCJyKixJT/9u2yOnIYk\nm6IgABpK07gMSZjlSEL0E7ntsYJay7YzXoHk0YSysByL69yF0fKJRg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 315, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100a4f4ed29828c4894b5a17a0c6db3c256c2221449228a92dff7d76ca8206dd8dd", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", "wx" : "00fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7", "wy" : "00b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/qLTH3D5DV+z4A4YasQqs8FhXO5xTgtO\nETGz1NgiW/ewN6GN8qwVND8w90Bn3fKegX1fd/jc4FcU2lnAlPDNqQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 316, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220694c146244a5ad0bd0636d9e12bc9e09e60e68b90d0b5e6c5dddd0cb694d8799", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", "wx" : "7258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db", "wy" : "17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEcliRHj1CM0kWZHnb4Lg0Gvf70D0KfhDt\nzLNrbO6lo9sXrCuJknkRKPo7ltwvvUyjv6eC7ygy/GZWlD2xjnNGsA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 317, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203d7f487c07bfc5f30846938a3dcef696444707cf9677254a92b06c63ab867d22", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", "wx" : "4f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914", "wy" : "00c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAETyhGHepkR01rs00Umcl9N7npVjPfHO7q\nrNRQFsmLORTIgYgQuMwG3bQOihJhxSj6pYlFXVpt+Tt3vF4OSTx0cA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 318, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206c7648fc0fbf8a06adb8b839f97b4ff7a800f11b1e37c593b261394599792ba4", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", "wx" : "74f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66", "wy" : "00eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEdPKoFPtdjsqRppteYHEnMrOTfeMoKb6X\nTte2jFwvXWbv8PB8VvmHplf0IZYgX1iMDx2W/YpjpfI4tI9Hh4j+Ow==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 319, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0221009be363a286f23f6322c205449d320baad417953ecb70f6214e90d49d7d1f26a8", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", "wx" : "195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6a", "wy" : "00b2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGVtRp8xKIbgnSnCpDed5gUw8jKNYMoII\nwJop8za4LWqyQWt8kv/9wpw7EoLdKnek0E3390UgRzk9hJmJxc7prQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 320, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022029798c5c45bdf58b4a7b2fdc2c46ab4af1218c7eeb9f0f27a88f1267674de3b0", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", "wx" : "622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa", "wy" : "736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYi/HRzIDS+wt3zvBbTSz0fejJ90qjBm6\ntLtP46JLWKpzay8vrnb0367MkJYzOwEyjVHrP9qckifpDQtEmYPE8A==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 321, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02200b70f22ca2bb3cefadca1a5711fa3a59f4695385eb5aedf3495d0b6d00f8fd85", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", "wx" : "1f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c7", "wy" : "0827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH3+FyvLXVQ56+bZQI+u03ONFAxFpIwnb\nJplpuDS2EccIJ/RbeAIOy7r0hP3Vv6rmhw8RhMIVgbr274K9e1MPkw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 322, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022016e1e459457679df5b9434ae23f474b3e8d2a70bd6b5dbe692ba16da01f1fb0a", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", "wx" : "49c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377a", "wy" : "00efc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEScGX3ICtHaR6Q0K5OJPo4fsLuU/DOoPn\ng8ALJMeBN3rvwg2pK6x2KVH3JHS+zHNNTMIrqBuJXigv2sTfevDzfQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 323, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202252d685e831b6cf095e4f0535eeaf0ddd3bfa91c210c9d9dc17224702eaf88f", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", "wx" : "00d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe", "wy" : "7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2MtoUXthalZACqOGhjXlS29plZii9hZ3\nV2VJgLr2rL5+yM9EnISaoDRhow762kFFPFfG5vvJO7xvpJrabcBVXA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 324, "comment" : "edge case for u1", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022075135abd7c425b60371a477f09ce0f274f64a8c6b061a07b5d63e93c65046c53", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", "wx" : "030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3", "wy" : "00b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAwcT+2Pyqm/iyt8bIO/CWcd0Rdr6h9rD\nmLhAZco0ffOyJ4GN4aObWJywcdg+UxfMzcIzjlHjEv4x2Nw0pIAXUA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 325, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100d55555555555555555555555555555547c74934474db157d2a8c3f088aced62a", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", "wx" : "00babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7", "wy" : "252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEurs2d7CVWALY6SmkE1VkDq8eoTU/incT\nMcSUbjSAr6clLxlsh+09KlnTsbVZE3/tABP+zvwZ+1qSaCubylG5UA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 326, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100c1777c8853938e536213c02464a936000ba1e21c0fc62075d46c624e23b52f31", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", "wx" : "1aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60", "wy" : "00bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGqsgGHk0cREaig6bFD/eAvyVkgeW06Y9\n4ym0JDlvumC75BMHBRdHkkQbMY06ox3+hXeCHptEbsVz0nLgNsTr6Q==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 327, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022030bbb794db588363b40679f6c182a50d3ce9679acdd3ffbe36d7813dacbdc818", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", "wx" : "008cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff", "wy" : "47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjLC5CUmcg+qAbNiFsd1GegEZ8GqIoCdu\nsM/aJ0U1qP9HtUKIM7w/LIv52QQRWM8zcYpplhzQFym8ABHR5YardQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 328, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202c37fd995622c4fb7fffffffffffffffc7cee745110cb45ab558ed7c90c15a2f", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", "wx" : "008f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d", "wy" : "3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjwPPGkInK7FTJyMJP3Lm/urIXhcA6fvp\npqLdZC10v107iacYna2M91/CL28ViqJ/nCygDaynhb4zWPK9o4YsoA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 329, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02207fd995622c4fb7ffffffffffffffffff5d883ffab5b32652ccdcaa290fccb97d", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", "wx" : "44de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8ace", "wy" : "00a2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERN47nHpXqMnoIJUnU0IefZh7s9efcfAT\ngFyJfgGPis6iRgdYyPmNP9zhIalDZZ43LDJv/y5fwq5/o/edquE8Eg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 330, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100ffb32ac4589f6ffffffffffffffffffebb107ff56b664ca599b954521f9972fa", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", "wx" : "6fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a", "wy" : "0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEb7iytI4zAxJorWpRdITciDnqkPZmnqDH\nrDIz4qwxOUoKyLvn9zwv9N+ZeHJ6wd/C/VhkfSDzH5kQUxa2RnHyBA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 331, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205622c4fb7fffffffffffffffffffffff928a8f1c7ac7bec1808b9f61c01ec327", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", "wx" : "00bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6", "wy" : "00f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvqcRIqBIaT6QX/YCs8+d0Yr2m5/J2EMd\nKx3Sa5Qsleb0PHuLletiCCwS2529p/445Fy+SkiGkH+4G9sMXqkkbA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 332, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022044104104104104104104104104104103b87853fd3b7d3f8e175125b4382f25ed", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", "wx" : "00da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156", "wy" : "00e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2pGMcxugaiDLlO8zt3jpgaQEowXxlB/j\nNma0WwM1MVbiuyaU9XW0UYO+eOXJtSEL879Ij9TIKUUW2JVyyk9TkQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 333, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202739ce739ce739ce739ce739ce739ce705560298d1f2f08dc419ac273a5b54d9", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", "wx" : "3007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d", "wy" : "5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMAfpLDk32t55ZN+jWw7/Ax9+sCrtCgMU\nQREGzetw/j1adUb8BVKZeyDj1vQT514stm4RYyJpcRS3m6xzS/xNxQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 334, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100b777777777777777777777777777777688e6a1fe808a97a348671222ff16b863", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", "wx" : "60e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9b", "wy" : "00d2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYOc071Yk08vw3dN1ARvWY9bWrrxkTrWZ\n/fmNvc0YzpvS2Qs6wx8TmvgyzM9sy7ssbqEfqXNw3JkG2kdNfYp1Zw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 335, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206492492492492492492492492492492406dd3a19b8d5fb875235963c593bd2d3", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", "wx" : "0085a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba337", "wy" : "69744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEhakA6XhY9pPAt9+iYeOA2tbqBG0fZd3u\n7dX32K8LozdpdE0VrdT2wLw7DaKuyTs0y4xl+TQN33TnsACe7szOPA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 336, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100955555555555555555555555555555547c74934474db157d2a8c3f088aced62c", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", "wx" : "38066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046", "wy" : "00a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOAZvddiO/EyT3jb0ngN7I0zBix3lYIdQ\npiyrA0VAEEaj6EvtjPy4Ge9NVQRE8s5LZRdmtp4uKQH4iDb/kANP7Q==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 337, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3e3a49a23a6d8abe95461f8445676b17", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", "wx" : "0098f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabf", "wy" : "00a33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmPaBd9yVwbTL+lJFSIylI6fVYpRw0DXW\nIaRDxy85qr+jPSlUb6HGSPLH1cz3DPHOSrebXbGsBZ2+zQaNvf8biQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 338, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022100bffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", "wx" : "5c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277", "wy" : "00e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEXCu/ojybmtB/A4qom0kwvyZ9lAHkJV3p\n6NoKUHjsgnfj6IKjHV5qN54Hk5g8ze05uVxDU6sv8B6lNpukewwxkQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 339, "comment" : "edge case for u2", "msg" : "313233343030", "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220185ddbca6dac41b1da033cfb60c152869e74b3cd66e9ffdf1b6bc09ed65ee40c", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", "wx" : "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", "wy" : "3547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4U1R4CCmESO215wGt6EzV+xrJVnul6Ptoprkz7EtcyEzA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 340, "comment" : "point duplication during verification", "msg" : "313233343030", "sig" : "3045022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022100d612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", "result" : "valid", "flags" : [ "PointDuplication" ] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", "wx" : "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", "wy" : "00cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4XKuH99Z7txJKGP5SF7MqBOU2qYRaFwSXWUbME6SjN3Yw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 341, "comment" : "duplication bug", "msg" : "313233343030", "sig" : "3045022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022100d612c2984c2afa416aa7f2882a486d4a8426cb6cfc91ed5b737278f9fca8be68", "result" : "invalid", "flags" : [ "PointDuplication" ] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", "wx" : "008aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e", "wy" : "1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiqLGT6nGQ3Vjq/vL0AsgSNSMGMFSoqb0\nkDbedkfr6C4c5kOHmVxooGD6O8A5mwXMBu7H1Zj3UEGkkX5pK39R/w==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 342, "comment" : "comparison with point at infinity ", "msg" : "313233343030", "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0022033333333333333333333333333333332f222f8faefdb533f265d461c29a47373", "result" : "invalid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", "wx" : "391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71f", "wy" : "00dd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEORQn/37ngBPBSux9lqigYiCSmKeDg16U\n/WVJ1QL/9x/dZiTsNDrZ/PTZhyGB5Z+EL5ukzMrgmmwJcvtqxrTGvQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 343, "comment" : "extreme value for k and edgecase s", "msg" : "313233343030", "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", "wx" : "00e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138e", "wy" : "00c1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE52K4ohm08YAhnMepBZJF5JYb0ZHAOJl4\nnHo0uJ6ME47BUz7wQZu3N24L/ekxnRCgaWh5HZ6g7tnBzmNFrtl1ng==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 344, "comment" : "extreme value for k and s^-1", "msg" : "313233343030", "sig" : "3046022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022100b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", "wx" : "009aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952", "wy" : "00fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmu2w0oHbFk4TAADFaX+uDzBe+Ei+b/+0\nOsWT+7lQ6VL6b2MzWb3NgrVrC5+WWwN3idRrmoFBt5GyrvpxP5bBdQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 345, "comment" : "extreme value for k and s^-1", "msg" : "313233343030", "sig" : "3046022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502210099999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", "wx" : "008ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee", "wy" : "1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEitRF22KBYmDk5of9GITki5/AY20DFUfW\nMxXnkuGb+u4d5k+Z1fHNi27Jyw94emVK6GmTuj2xAI70PP8GhMsivQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 346, "comment" : "extreme value for k and s^-1", "msg" : "313233343030", "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", "wx" : "1f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32", "wy" : "00e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH1eZyVvokGOyTybkDLkowahop2+wCUYH\n6AQ9tAnJHDLnVyToE6QZHjqDkAfwji6Jc4iwbUoA3m3mDlNtkfq1Zg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 347, "comment" : "extreme value for k and s^-1", "msg" : "313233343030", "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", "wx" : "00a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc", "wy" : "28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEozMaThtCI+wsAn7dSCySihTtNY2T8dQh\nfTmr9p/LXMwo1oTSqqvNY4N3XKpiOd4m1MaTe7YD7LQZYIL0z/1QnQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 348, "comment" : "extreme value for k", "msg" : "313233343030", "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", "wx" : "3f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb24818", "wy" : "5ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEPzlSGZd0x885s4tmyxBCpiYNhoCAOEXk\n1DOtujuySBhepJW2jLx+1Bc+5jyQQtxQJiXH634h+wLKmpEU4KOhjQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 349, "comment" : "extreme value for k and edgecase s", "msg" : "313233343030", "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", "wx" : "00cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e", "wy" : "054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzfuMD0IuFE4TfCQSyGwXH1/j+j9bu1RO\nkHYojzzteG4FT9ByG3fBHHm+rLPJQhGwoZvaCGUu/q+SUTo7ChY2mA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 350, "comment" : "extreme value for k and s^-1", "msg" : "313233343030", "sig" : "3045022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022100b6db6db6db6db6db6db6db6db6db6db5f30f30127d33e02aad96438927022e9c", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", "wx" : "73598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3", "wy" : "00cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEc1mKahxoJ4+mv9DOQGTmgjW8HA9rIKko\nEIvjNnMPh+PLrmElGbUDLsyFrtgRJxqV/nk51dNGAUC6MY9NFKujHQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 351, "comment" : "extreme value for k and s^-1", "msg" : "313233343030", "sig" : "3045022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802210099999999999999999999999999999998d668eaf0cf91f9bd7317d2547ced5a5a", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", "wx" : "58debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a1", "wy" : "6773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWN69mn7iydWRMkeKVECuTV1+1Dcwg2n5\nLqhsghg/EKFnc+dvXtv02g5PG9/6wPVyV+HfpGWEKTEwmiQkX9pqXQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 352, "comment" : "extreme value for k and s^-1", "msg" : "313233343030", "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", "wx" : "008b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b", "wy" : "00950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEi5BN5HlnNAxfjDVypyCSTvdXhjf+qxlJ\nrLJBpaasP1uVCQRJb5gksdY/MxO64huJ+uia/fyBG17OA/1aowGGTw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 353, "comment" : "extreme value for k and s^-1", "msg" : "313233343030", "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", "wx" : "00f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a", "wy" : "346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE9IkrbVJcdx4DXyolJwjzeE5II4YEtPlN\nxW6qHlRtlBo0axqgvOaLHFDltS9Qn7VSLlwl4Ci8j4Y0Au23vK2LGw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 354, "comment" : "extreme value for k", "msg" : "313233343030", "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", "wx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", "wy" : "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio/Re0SKaFVBmcR9CP+xDUuA==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 355, "comment" : "testing point duplication", "msg" : "313233343030", "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", "result" : "invalid", "flags" : [] }, { "tcId" : 356, "comment" : "testing point duplication", "msg" : "313233343030", "sig" : "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", "result" : "invalid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", "wx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", "wy" : "00b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5i3xSWI2Vw7mqJbBAPx7vdXAuhLt1l6q+ZjuC9vBO8ndw==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 357, "comment" : "testing point duplication", "msg" : "313233343030", "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", "result" : "invalid", "flags" : [] }, { "tcId" : 358, "comment" : "testing point duplication", "msg" : "313233343030", "sig" : "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", "result" : "invalid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", "wx" : "782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963", "wy" : "00af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeCyO0X47Kng7VGTzOwllKnHGeOBexR6E\n4rz8Zjo96WOvmstCgLjH98QvTvmrpiRewewXEv04oPqWQY2M1qphUg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 359, "comment" : "pseudorandom signature", "msg" : "", "sig" : "3046022100f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dc022100b303e26be1f73465315221f0b331528807a1a9b6eb068ede6eebeaaa49af8a36", "result" : "valid", "flags" : [] }, { "tcId" : 360, "comment" : "pseudorandom signature", "msg" : "4d7367", "sig" : "30450220109cd8ae0374358984a8249c0a843628f2835ffad1df1a9a69aa2fe72355545c022100ac6f00daf53bd8b1e34da329359b6e08019c5b037fed79ee383ae39f85a159c6", "result" : "valid", "flags" : [] }, { "tcId" : 361, "comment" : "pseudorandom signature", "msg" : "313233343030", "sig" : "3045022100d035ee1f17fdb0b2681b163e33c359932659990af77dca632012b30b27a057b302201939d9f3b2858bc13e3474cb50e6a82be44faa71940f876c1cba4c3e989202b6", "result" : "valid", "flags" : [] }, { "tcId" : 362, "comment" : "pseudorandom signature", "msg" : "0000000000000000000000000000000000000000", "sig" : "304402204f053f563ad34b74fd8c9934ce59e79c2eb8e6eca0fef5b323ca67d5ac7ed23802204d4b05daa0719e773d8617dce5631c5fd6f59c9bdc748e4b55c970040af01be5", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", "wx" : "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", "wy" : "01060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv8AAAABBgSS1aVnPg8l2NUPt+WMSdhtRtQhaVXgqj1A4Q==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 363, "comment" : "y-coordinate of the public key is small", "msg" : "4d657373616765", "sig" : "304402206d6a4f556ccce154e7fb9f19e76c3deca13d59cc2aeb4ecad968aab2ded45965022053b9fa74803ede0fc4441bf683d56c564d3e274e09ccf47390badd1471c05fb7", "result" : "valid", "flags" : [] }, { "tcId" : 364, "comment" : "y-coordinate of the public key is small", "msg" : "4d657373616765", "sig" : "3046022100aad503de9b9fd66b948e9acf596f0a0e65e700b28b26ec56e6e45e846489b3c4022100fff223c5d0765447e8447a3f9d31fd0696e89d244422022ff61a110b2a8c2f04", "result" : "valid", "flags" : [] }, { "tcId" : 365, "comment" : "y-coordinate of the public key is small", "msg" : "4d657373616765", "sig" : "30460221009182cebd3bb8ab572e167174397209ef4b1d439af3b200cdf003620089e43225022100abb88367d15fe62d1efffb6803da03109ee22e90bc9c78e8b4ed23630b82ea9d", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", "wx" : "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", "wy" : "00fffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv/////++fttKlqYwfDaJyrwSBpztieSuSvelqoeVcK7Tg==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 366, "comment" : "y-coordinate of the public key is large", "msg" : "4d657373616765", "sig" : "304502203854a3998aebdf2dbc28adac4181462ccac7873907ab7f212c42db0e69b56ed8022100c12c09475c772fd0c1b2060d5163e42bf71d727e4ae7c03eeba954bf50b43bb3", "result" : "valid", "flags" : [] }, { "tcId" : 367, "comment" : "y-coordinate of the public key is large", "msg" : "4d657373616765", "sig" : "3046022100e94dbdc38795fe5c904d8f16d969d3b587f0a25d2de90b6d8c5c53ff887e3607022100856b8c963e9b68dade44750bf97ec4d11b1a0a3804f4cb79aa27bdea78ac14e4", "result" : "valid", "flags" : [] }, { "tcId" : 368, "comment" : "y-coordinate of the public key is large", "msg" : "4d657373616765", "sig" : "3044022049fc102a08ca47b60e0858cd0284d22cddd7233f94aaffbb2db1dd2cf08425e102205b16fca5a12cdb39701697ad8e39ffd6bdec0024298afaa2326aea09200b14d6", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", "wx" : "013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0", "wy" : "00f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAAAAAT/SIkjWTZX3PCm0irSGMYUL5QP9\nAPhGi18PcOD27nqkO8LG/SWx2CaSQcvdnbsNrJbcliMfQwcF+DhxfQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 369, "comment" : "x-coordinate of the public key is small", "msg" : "4d657373616765", "sig" : "3045022041efa7d3f05a0010675fcb918a45c693da4b348df21a59d6f9cd73e0d831d67a022100bbab52596c1a1d9484296cdc92cbf07e665259a13791a8fe8845e2c07cf3fc67", "result" : "valid", "flags" : [] }, { "tcId" : 370, "comment" : "x-coordinate of the public key is small", "msg" : "4d657373616765", "sig" : "3046022100b615698c358b35920dd883eca625a6c5f7563970cdfc378f8fe0cee17092144c022100da0b84cd94a41e049ef477aeac157b2a9bfa6b7ac8de06ed3858c5eede6ddd6d", "result" : "valid", "flags" : [] }, { "tcId" : 371, "comment" : "x-coordinate of the public key is small", "msg" : "4d657373616765", "sig" : "304602210087cf8c0eb82d44f69c60a2ff5457d3aaa322e7ec61ae5aecfd678ae1c1932b0e022100c522c4eea7eafb82914cbf5c1ff76760109f55ddddcf58274d41c9bc4311e06e", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "0425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", "wx" : "25afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dffffffff", "wy" : "00fa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a0342000425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJa/WiayrrtZ8Hylt5ZQG+MVQ9XFGoLTs\nLJeHbf/////6RqduUgMi37xJHsTwzBl0IPxOpYg9j23VPDVLxPZ8NQ==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 372, "comment" : "x-coordinate of the public key has many trailing 1's", "msg" : "4d657373616765", "sig" : "3045022062f48ef71ace27bf5a01834de1f7e3f948b9dce1ca1e911d5e13d3b104471d82022100a1570cc0f388768d3ba7df7f212564caa256ff825df997f21f72f5280d53011f", "result" : "valid", "flags" : [] }, { "tcId" : 373, "comment" : "x-coordinate of the public key has many trailing 1's", "msg" : "4d657373616765", "sig" : "3046022100f6b0e2f6fe020cf7c0c20137434344ed7add6c4be51861e2d14cbda472a6ffb40221009be93722c1a3ad7d4cf91723700cb5486de5479d8c1b38ae4e8e5ba1638e9732", "result" : "valid", "flags" : [] }, { "tcId" : 374, "comment" : "x-coordinate of the public key has many trailing 1's", "msg" : "4d657373616765", "sig" : "3045022100db09d8460f05eff23bc7e436b67da563fa4b4edb58ac24ce201fa8a358125057022046da116754602940c8999c8d665f786c50f5772c0a3cdbda075e77eabc64df16", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "04d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", "wx" : "00d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb9", "wy" : "3f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0S5sZrZ3NMPITSYBz1013Al+J2N/CspK\nT9t0tqrdO7k/W9/4i9VzbfiY5pkAbtdQ8RzwfFhmzXrXDHEh/////w==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 375, "comment" : "y-coordinate of the public key has many trailing 1's", "msg" : "4d657373616765", "sig" : "30450220592c41e16517f12fcabd98267674f974b588e9f35d35406c1a7bb2ed1d19b7b8022100c19a5f942607c3551484ff0dc97281f0cdc82bc48e2205a0645c0cf3d7f59da0", "result" : "valid", "flags" : [] }, { "tcId" : 376, "comment" : "y-coordinate of the public key has many trailing 1's", "msg" : "4d657373616765", "sig" : "3046022100be0d70887d5e40821a61b68047de4ea03debfdf51cdf4d4b195558b959a032b20221008266b4d270e24414ecacb14c091a233134b918d37320c6557d60ad0a63544ac4", "result" : "valid", "flags" : [] }, { "tcId" : 377, "comment" : "y-coordinate of the public key has many trailing 1's", "msg" : "4d657373616765", "sig" : "3046022100fae92dfcb2ee392d270af3a5739faa26d4f97bfd39ed3cbee4d29e26af3b206a02210093645c80605595e02c09a0dc4b17ac2a51846a728b3e8d60442ed6449fd3342b", "result" : "valid", "flags" : [] } ] }, { "key" : { "curve" : "secp256k1", "keySize" : 256, "type" : "EcPublicKey", "uncompressed" : "046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", "wx" : "6d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000", "wy" : "00e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb" }, "keyDer" : "3056301006072a8648ce3d020106052b8104000a034200046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbUp/YNR3Sk8KqLve25U8fup5CUB+MWR1\nVmS8KAAAAADmWdNOTfONnoyeqt+6NmEsdpGVvobHeqw/NueLU4aA+w==\n-----END PUBLIC KEY-----", "sha" : "SHA-256", "type" : "EcdsaVerify", "tests" : [ { "tcId" : 378, "comment" : "x-coordinate of the public key has many trailing 0's", "msg" : "4d657373616765", "sig" : "30450220176a2557566ffa518b11226694eb9802ed2098bfe278e5570fe1d5d7af18a943022100ed6e2095f12a03f2eaf6718f430ec5fe2829fd1646ab648701656fd31221b97d", "result" : "valid", "flags" : [] }, { "tcId" : 379, "comment" : "x-coordinate of the public key has many trailing 0's", "msg" : "4d657373616765", "sig" : "3045022060be20c3dbc162dd34d26780621c104bbe5dace630171b2daef0d826409ee5c2022100bd8081b27762ab6e8f425956bf604e332fa066a99b59f87e27dc1198b26f5caa", "result" : "valid", "flags" : [] }, { "tcId" : 380, "comment" : "x-coordinate of the public key has many trailing 0's", "msg" : "4d657373616765", "sig" : "3046022100edf03cf63f658883289a1a593d1007895b9f236d27c9c1f1313089aaed6b16ae022100e5b22903f7eb23adc2e01057e39b0408d495f694c83f306f1216c9bf87506074", "result" : "valid", "flags" : [] } ] } ] } ================================================ FILE: rustfmt.toml ================================================ ================================================ FILE: src/lib.rs ================================================ //! Pure Rust implementation of the secp256k1 curve and fast ECDSA //! signatures. The secp256k1 curve is used extensively in Bitcoin and //! Ethereum-alike cryptocurrencies. #![deny( unused_import_braces, unused_imports, unused_comparisons, unused_must_use, unused_variables, non_shorthand_field_patterns, unreachable_code, unused_parens )] #![cfg_attr(not(feature = "std"), no_std)] pub use libsecp256k1_core::*; use arrayref::{array_mut_ref, array_ref}; use base64::{engine::Engine as _, prelude::BASE64_STANDARD}; use core::convert::TryFrom; use digest::{generic_array::GenericArray, Digest}; use rand::Rng; #[cfg(feature = "std")] use core::fmt; #[cfg(feature = "hmac")] use hmac_drbg::HmacDRBG; #[cfg(feature = "std")] use serde::{de, ser::Serializer, Deserialize, Serialize}; #[cfg(feature = "hmac")] use sha2::Sha256; #[cfg(feature = "hmac")] use typenum::U32; use crate::{ curve::{Affine, ECMultContext, ECMultGenContext, Field, Jacobian, Scalar}, util::{Decoder, SignatureArray}, }; #[cfg(feature = "lazy-static-context")] lazy_static::lazy_static! { /// A static ECMult context. pub static ref ECMULT_CONTEXT: Box = ECMultContext::new_boxed(); /// A static ECMultGen context. pub static ref ECMULT_GEN_CONTEXT: Box = ECMultGenContext::new_boxed(); } #[cfg(all(feature = "static-context", not(feature = "lazy-static-context")))] /// A static ECMult context. // Correct `pre_g` values are fed into `ECMultContext::new_from_raw`, generated by build script. pub static ECMULT_CONTEXT: ECMultContext = unsafe { ECMultContext::new_from_raw(include!(concat!(env!("OUT_DIR"), "/const.rs"))) }; #[cfg(all(feature = "static-context", not(feature = "lazy-static-context")))] /// A static ECMultGen context. // Correct `prec` values are fed into `ECMultGenContext::new_from_raw`, generated by build script. pub static ECMULT_GEN_CONTEXT: ECMultGenContext = unsafe { ECMultGenContext::new_from_raw(include!(concat!(env!("OUT_DIR"), "/const_gen.rs"))) }; #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// Public key on a secp256k1 curve. pub struct PublicKey(Affine); #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// Secret key (256-bit) on a secp256k1 curve. pub struct SecretKey(Scalar); #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// An ECDSA signature. pub struct Signature { pub r: Scalar, pub s: Scalar, } #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// Tag used for public key recovery from signatures. pub struct RecoveryId(u8); #[derive(Debug, Clone, Copy, Eq, PartialEq)] /// Hashed message input to an ECDSA signature. pub struct Message(pub Scalar); #[derive(Debug, Clone, Eq, PartialEq)] /// Shared secret using ECDH. pub struct SharedSecret(GenericArray); impl Copy for SharedSecret where D: Copy + Digest, GenericArray: Copy, { } /// Format for public key parsing. pub enum PublicKeyFormat { /// Compressed public key, 33 bytes. Compressed, /// Full length public key, 65 bytes. Full, /// Raw public key, 64 bytes. Raw, } impl PublicKey { pub fn from_secret_key_with_context( seckey: &SecretKey, context: &ECMultGenContext, ) -> PublicKey { let mut pj = Jacobian::default(); context.ecmult_gen(&mut pj, &seckey.0); let mut p = Affine::default(); p.set_gej(&pj); PublicKey(p) } #[cfg(any(feature = "static-context", feature = "lazy-static-context"))] pub fn from_secret_key(seckey: &SecretKey) -> PublicKey { Self::from_secret_key_with_context(seckey, &ECMULT_GEN_CONTEXT) } pub fn parse_slice(p: &[u8], format: Option) -> Result { let format = match (p.len(), format) { (util::FULL_PUBLIC_KEY_SIZE, None) | (util::FULL_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Full)) => PublicKeyFormat::Full, (util::COMPRESSED_PUBLIC_KEY_SIZE, None) | (util::COMPRESSED_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Compressed)) => { PublicKeyFormat::Compressed } (util::RAW_PUBLIC_KEY_SIZE, None) | (util::RAW_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Raw)) => PublicKeyFormat::Raw, _ => return Err(Error::InvalidInputLength), }; match format { PublicKeyFormat::Full => { let mut a = [0; util::FULL_PUBLIC_KEY_SIZE]; a.copy_from_slice(p); Self::parse(&a) } PublicKeyFormat::Raw => { use util::TAG_PUBKEY_FULL; let mut a = [0; util::FULL_PUBLIC_KEY_SIZE]; a[0] = TAG_PUBKEY_FULL; a[1..].copy_from_slice(p); Self::parse(&a) } PublicKeyFormat::Compressed => { let mut a = [0; util::COMPRESSED_PUBLIC_KEY_SIZE]; a.copy_from_slice(p); Self::parse_compressed(&a) } } } pub fn parse(p: &[u8; util::FULL_PUBLIC_KEY_SIZE]) -> Result { use util::{TAG_PUBKEY_FULL, TAG_PUBKEY_HYBRID_EVEN, TAG_PUBKEY_HYBRID_ODD}; if !(p[0] == TAG_PUBKEY_FULL || p[0] == TAG_PUBKEY_HYBRID_EVEN || p[0] == TAG_PUBKEY_HYBRID_ODD) { return Err(Error::InvalidPublicKey); } let mut x = Field::default(); let mut y = Field::default(); if !x.set_b32(array_ref!(p, 1, 32)) { return Err(Error::InvalidPublicKey); } if !y.set_b32(array_ref!(p, 33, 32)) { return Err(Error::InvalidPublicKey); } let mut elem = Affine::default(); elem.set_xy(&x, &y); if (p[0] == TAG_PUBKEY_HYBRID_EVEN || p[0] == TAG_PUBKEY_HYBRID_ODD) && (y.is_odd() != (p[0] == TAG_PUBKEY_HYBRID_ODD)) { return Err(Error::InvalidPublicKey); } if elem.is_infinity() { return Err(Error::InvalidPublicKey); } if elem.is_valid_var() { Ok(PublicKey(elem)) } else { Err(Error::InvalidPublicKey) } } pub fn parse_compressed( p: &[u8; util::COMPRESSED_PUBLIC_KEY_SIZE], ) -> Result { use util::{TAG_PUBKEY_EVEN, TAG_PUBKEY_ODD}; if !(p[0] == TAG_PUBKEY_EVEN || p[0] == TAG_PUBKEY_ODD) { return Err(Error::InvalidPublicKey); } let mut x = Field::default(); if !x.set_b32(array_ref!(p, 1, 32)) { return Err(Error::InvalidPublicKey); } let mut elem = Affine::default(); elem.set_xo_var(&x, p[0] == TAG_PUBKEY_ODD); if elem.is_infinity() { return Err(Error::InvalidPublicKey); } if elem.is_valid_var() { Ok(PublicKey(elem)) } else { Err(Error::InvalidPublicKey) } } pub fn serialize(&self) -> [u8; util::FULL_PUBLIC_KEY_SIZE] { use util::TAG_PUBKEY_FULL; debug_assert!(!self.0.is_infinity()); let mut ret = [0u8; 65]; let mut elem = self.0; elem.x.normalize_var(); elem.y.normalize_var(); elem.x.fill_b32(array_mut_ref!(ret, 1, 32)); elem.y.fill_b32(array_mut_ref!(ret, 33, 32)); ret[0] = TAG_PUBKEY_FULL; ret } pub fn serialize_compressed(&self) -> [u8; util::COMPRESSED_PUBLIC_KEY_SIZE] { use util::{TAG_PUBKEY_EVEN, TAG_PUBKEY_ODD}; debug_assert!(!self.0.is_infinity()); let mut ret = [0u8; 33]; let mut elem = self.0; elem.x.normalize_var(); elem.y.normalize_var(); elem.x.fill_b32(array_mut_ref!(ret, 1, 32)); ret[0] = if elem.y.is_odd() { TAG_PUBKEY_ODD } else { TAG_PUBKEY_EVEN }; ret } pub fn tweak_add_assign_with_context( &mut self, tweak: &SecretKey, context: &ECMultContext, ) -> Result<(), Error> { let mut r = Jacobian::default(); let a = Jacobian::from_ge(&self.0); let one = Scalar::from_int(1); context.ecmult(&mut r, &a, &one, &tweak.0); if r.is_infinity() { return Err(Error::TweakOutOfRange); } self.0.set_gej(&r); Ok(()) } #[cfg(any(feature = "static-context", feature = "lazy-static-context"))] pub fn tweak_add_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> { self.tweak_add_assign_with_context(tweak, &ECMULT_CONTEXT) } pub fn tweak_mul_assign_with_context( &mut self, tweak: &SecretKey, context: &ECMultContext, ) -> Result<(), Error> { if tweak.0.is_zero() { return Err(Error::TweakOutOfRange); } let mut r = Jacobian::default(); let zero = Scalar::from_int(0); let pt = Jacobian::from_ge(&self.0); context.ecmult(&mut r, &pt, &tweak.0, &zero); self.0.set_gej(&r); Ok(()) } #[cfg(any(feature = "static-context", feature = "lazy-static-context"))] pub fn tweak_mul_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> { self.tweak_mul_assign_with_context(tweak, &ECMULT_CONTEXT) } pub fn combine(keys: &[PublicKey]) -> Result { let mut qj = Jacobian::default(); qj.set_infinity(); for key in keys { qj = qj.add_ge(&key.0); } if qj.is_infinity() { return Err(Error::InvalidPublicKey); } let q = Affine::from_gej(&qj); Ok(PublicKey(q)) } } impl Into for PublicKey { fn into(self) -> Affine { self.0 } } impl TryFrom for PublicKey { type Error = Error; fn try_from(value: Affine) -> Result { if value.is_infinity() || !value.is_valid_var() { Err(Error::InvalidAffine) } else { Ok(PublicKey(value)) } } } #[cfg(feature = "std")] impl Serialize for PublicKey { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if serializer.is_human_readable() { serializer.serialize_str(&BASE64_STANDARD.encode(&self.serialize()[..])) } else { serializer.serialize_bytes(&self.serialize()) } } } #[cfg(feature = "std")] struct PublicKeyStrVisitor; #[cfg(feature = "std")] impl<'de> de::Visitor<'de> for PublicKeyStrVisitor { type Value = PublicKey; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .write_str("a bytestring of either 33 (compressed), 64 (raw), or 65 bytes in length") } fn visit_str(self, value: &str) -> Result where E: de::Error, { let value: &[u8] = &BASE64_STANDARD.decode(value).map_err(|e| E::custom(e))?; let key_format = match value.len() { 33 => PublicKeyFormat::Compressed, 64 => PublicKeyFormat::Raw, 65 => PublicKeyFormat::Full, _ => return Err(E::custom(Error::InvalidInputLength)), }; PublicKey::parse_slice(value, Some(key_format)) .map_err(|_e| E::custom(Error::InvalidPublicKey)) } } #[cfg(feature = "std")] struct PublicKeyBytesVisitor; #[cfg(feature = "std")] impl<'de> de::Visitor<'de> for PublicKeyBytesVisitor { type Value = PublicKey; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str( "a byte slice that is either 33 (compressed), 64 (raw), or 65 bytes in length", ) } fn visit_bytes(self, value: &[u8]) -> Result where E: de::Error, { PublicKey::parse_slice(value, None).map_err(|_e| E::custom(Error::InvalidPublicKey)) } } #[cfg(feature = "std")] impl<'de> Deserialize<'de> for PublicKey { fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { if deserializer.is_human_readable() { deserializer.deserialize_str(PublicKeyStrVisitor) } else { deserializer.deserialize_bytes(PublicKeyBytesVisitor) } } } impl SecretKey { pub fn parse(p: &[u8; util::SECRET_KEY_SIZE]) -> Result { let mut elem = Scalar::default(); if !bool::from(elem.set_b32(p)) { Self::try_from(elem) } else { Err(Error::InvalidSecretKey) } } pub fn parse_slice(p: &[u8]) -> Result { if p.len() != util::SECRET_KEY_SIZE { return Err(Error::InvalidInputLength); } let mut a = [0; 32]; a.copy_from_slice(p); Self::parse(&a) } pub fn random(rng: &mut R) -> SecretKey { loop { let mut ret = [0u8; util::SECRET_KEY_SIZE]; rng.fill_bytes(&mut ret); if let Ok(key) = Self::parse(&ret) { return key; } } } pub fn serialize(&self) -> [u8; util::SECRET_KEY_SIZE] { self.0.b32() } pub fn tweak_add_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> { let v = self.0 + tweak.0; if v.is_zero() { return Err(Error::TweakOutOfRange); } self.0 = v; Ok(()) } pub fn tweak_mul_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> { if tweak.0.is_zero() { return Err(Error::TweakOutOfRange); } self.0 *= &tweak.0; Ok(()) } pub fn inv(&self) -> Self { SecretKey(self.0.inv()) } pub fn clear(&mut self) { self.0.clear(); } pub fn is_zero(&self) -> bool { self.0.is_zero() } } impl Default for SecretKey { fn default() -> SecretKey { let mut elem = Scalar::default(); let overflowed = bool::from(elem.set_b32(&[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ])); debug_assert!(!overflowed); debug_assert!(!elem.is_zero()); SecretKey(elem) } } impl Into for SecretKey { fn into(self) -> Scalar { self.0 } } impl TryFrom for SecretKey { type Error = Error; fn try_from(scalar: Scalar) -> Result { if scalar.is_zero() { Err(Error::InvalidSecretKey) } else { Ok(Self(scalar)) } } } impl core::fmt::LowerHex for SecretKey { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let scalar = self.0; write!(f, "{:x}", scalar) } } impl Signature { /// Parse an possibly overflowing signature. /// /// A SECP256K1 signature is usually required to be within 0 and curve /// order. This function, however, allows signatures larger than curve order /// by taking the signature and minus curve order. /// /// Note that while this function is technically safe, it is non-standard, /// meaning you will have compatibility issues if you also use other /// SECP256K1 libraries. It's not recommended to use this function. Please /// use `parse_standard` instead. pub fn parse_overflowing(p: &[u8; util::SIGNATURE_SIZE]) -> Signature { let mut r = Scalar::default(); let mut s = Scalar::default(); // Okay for signature to overflow let _ = r.set_b32(array_ref!(p, 0, 32)); let _ = s.set_b32(array_ref!(p, 32, 32)); Signature { r, s } } /// Parse a standard SECP256K1 signature. The signature is required to be /// within 0 and curve order. Returns error if it overflows. pub fn parse_standard(p: &[u8; util::SIGNATURE_SIZE]) -> Result { let mut r = Scalar::default(); let mut s = Scalar::default(); // It's okay for the signature to overflow here, it's checked below. let overflowed_r = r.set_b32(array_ref!(p, 0, 32)); let overflowed_s = s.set_b32(array_ref!(p, 32, 32)); if bool::from(overflowed_r | overflowed_s) { return Err(Error::InvalidSignature); } Ok(Signature { r, s }) } /// Parse a possibly overflowing signature slice. See also /// `parse_overflowing`. /// /// It's not recommended to use this function. Please use /// `parse_standard_slice` instead. pub fn parse_overflowing_slice(p: &[u8]) -> Result { if p.len() != util::SIGNATURE_SIZE { return Err(Error::InvalidInputLength); } let mut a = [0; util::SIGNATURE_SIZE]; a.copy_from_slice(p); Ok(Self::parse_overflowing(&a)) } /// Parse a standard signature slice. See also `parse_standard`. pub fn parse_standard_slice(p: &[u8]) -> Result { if p.len() != util::SIGNATURE_SIZE { return Err(Error::InvalidInputLength); } let mut a = [0; util::SIGNATURE_SIZE]; a.copy_from_slice(p); Ok(Self::parse_standard(&a)?) } /// Parse a DER-encoded byte slice to a signature. pub fn parse_der(p: &[u8]) -> Result { let mut decoder = Decoder::new(p); decoder.read_constructed_sequence()?; let rlen = decoder.read_len()?; if rlen != decoder.remaining_len() { return Err(Error::InvalidSignature); } let r = decoder.read_integer()?; let s = decoder.read_integer()?; if decoder.remaining_len() != 0 { return Err(Error::InvalidSignature); } Ok(Signature { r, s }) } /// Converts a "lax DER"-encoded byte slice to a signature. This is basically /// only useful for validating signatures in the Bitcoin blockchain from before /// 2016. It should never be used in new applications. This library does not /// support serializing to this "format" pub fn parse_der_lax(p: &[u8]) -> Result { let mut decoder = Decoder::new(p); decoder.read_constructed_sequence()?; decoder.read_seq_len_lax()?; let r = decoder.read_integer_lax()?; let s = decoder.read_integer_lax()?; Ok(Signature { r, s }) } /// Normalizes a signature to a "low S" form. In ECDSA, signatures are /// of the form (r, s) where r and s are numbers lying in some finite /// field. The verification equation will pass for (r, s) iff it passes /// for (r, -s), so it is possible to ``modify'' signatures in transit /// by flipping the sign of s. This does not constitute a forgery since /// the signed message still cannot be changed, but for some applications, /// changing even the signature itself can be a problem. Such applications /// require a "strong signature". It is believed that ECDSA is a strong /// signature except for this ambiguity in the sign of s, so to accommodate /// these applications libsecp256k1 will only accept signatures for which /// s is in the lower half of the field range. This eliminates the /// ambiguity. /// /// However, for some systems, signatures with high s-values are considered /// valid. (For example, parsing the historic Bitcoin blockchain requires /// this.) For these applications we provide this normalization function, /// which ensures that the s value lies in the lower half of its range. pub fn normalize_s(&mut self) { if self.s.is_high() { self.s = -self.s; } } /// Serialize a signature to a standard byte representation. This is the /// reverse of `parse_standard`. pub fn serialize(&self) -> [u8; util::SIGNATURE_SIZE] { let mut ret = [0u8; 64]; self.r.fill_b32(array_mut_ref!(ret, 0, 32)); self.s.fill_b32(array_mut_ref!(ret, 32, 32)); ret } /// Serialize a signature to a DER encoding. This is the reverse of /// `parse_der`. pub fn serialize_der(&self) -> SignatureArray { fn fill_scalar_with_leading_zero(scalar: &Scalar) -> [u8; 33] { let mut ret = [0u8; 33]; scalar.fill_b32(array_mut_ref!(ret, 1, 32)); ret } let r_full = fill_scalar_with_leading_zero(&self.r); let s_full = fill_scalar_with_leading_zero(&self.s); fn integer_slice(full: &[u8; 33]) -> &[u8] { let mut len = 33; while len > 1 && full[full.len() - len] == 0 && full[full.len() - len + 1] < 0x80 { len -= 1; } &full[(full.len() - len)..] } let r = integer_slice(&r_full); let s = integer_slice(&s_full); let mut ret = SignatureArray::new(6 + r.len() + s.len()); { let l = ret.as_mut(); l[0] = 0x30; l[1] = 4 + r.len() as u8 + s.len() as u8; l[2] = 0x02; l[3] = r.len() as u8; l[4..(4 + r.len())].copy_from_slice(r); l[4 + r.len()] = 0x02; l[5 + r.len()] = s.len() as u8; l[(6 + r.len())..(6 + r.len() + s.len())].copy_from_slice(s); } ret } } impl Message { pub fn parse(p: &[u8; util::MESSAGE_SIZE]) -> Message { let mut m = Scalar::default(); // Okay for message to overflow. let _ = m.set_b32(p); Message(m) } pub fn parse_slice(p: &[u8]) -> Result { if p.len() != util::MESSAGE_SIZE { return Err(Error::InvalidInputLength); } let mut a = [0; util::MESSAGE_SIZE]; a.copy_from_slice(p); Ok(Self::parse(&a)) } pub fn serialize(&self) -> [u8; util::MESSAGE_SIZE] { self.0.b32() } } impl RecoveryId { /// Parse recovery ID starting with 0. pub fn parse(p: u8) -> Result { if p < 4 { Ok(RecoveryId(p)) } else { Err(Error::InvalidRecoveryId) } } /// Parse recovery ID as Ethereum RPC format, starting with 27. pub fn parse_rpc(p: u8) -> Result { if p >= 27 && p < 27 + 4 { RecoveryId::parse(p - 27) } else { Err(Error::InvalidRecoveryId) } } pub fn serialize(&self) -> u8 { self.0 } } impl Into for RecoveryId { fn into(self) -> u8 { self.0 } } impl Into for RecoveryId { fn into(self) -> i32 { self.0 as i32 } } impl SharedSecret { pub fn new_with_context( pubkey: &PublicKey, seckey: &SecretKey, context: &ECMultContext, ) -> Result, Error> { let inner = match context.ecdh_raw::(&pubkey.0, &seckey.0) { Some(val) => val, None => return Err(Error::InvalidSecretKey), }; Ok(SharedSecret(inner)) } #[cfg(any(feature = "static-context", feature = "lazy-static-context"))] pub fn new(pubkey: &PublicKey, seckey: &SecretKey) -> Result, Error> { Self::new_with_context(pubkey, seckey, &ECMULT_CONTEXT) } } impl AsRef<[u8]> for SharedSecret { fn as_ref(&self) -> &[u8] { &self.0.as_ref() } } /// Check signature is a valid message signed by public key, using the given context. pub fn verify_with_context( message: &Message, signature: &Signature, pubkey: &PublicKey, context: &ECMultContext, ) -> bool { context.verify_raw(&signature.r, &signature.s, &pubkey.0, &message.0) } #[cfg(any(feature = "static-context", feature = "lazy-static-context"))] /// Check signature is a valid message signed by public key. pub fn verify(message: &Message, signature: &Signature, pubkey: &PublicKey) -> bool { verify_with_context(message, signature, pubkey, &ECMULT_CONTEXT) } /// Recover public key from a signed message, using the given context. pub fn recover_with_context( message: &Message, signature: &Signature, recovery_id: &RecoveryId, context: &ECMultContext, ) -> Result { context .recover_raw(&signature.r, &signature.s, recovery_id.0, &message.0) .map(PublicKey) } #[cfg(any(feature = "static-context", feature = "lazy-static-context"))] /// Recover public key from a signed message. pub fn recover( message: &Message, signature: &Signature, recovery_id: &RecoveryId, ) -> Result { recover_with_context(message, signature, recovery_id, &ECMULT_CONTEXT) } #[cfg(feature = "hmac")] /// Sign a message using the secret key, with the given context. pub fn sign_with_context( message: &Message, seckey: &SecretKey, context: &ECMultGenContext, ) -> (Signature, RecoveryId) { let seckey_b32 = seckey.0.b32(); let message_b32 = message.0.b32(); let mut drbg = HmacDRBG::::new(&seckey_b32, &message_b32, &[]); let mut nonce = Scalar::default(); let mut overflow; let result; loop { let generated = drbg.generate::(None); overflow = bool::from(nonce.set_b32(array_ref!(generated, 0, 32))); if !overflow && !nonce.is_zero() { if let Ok(val) = context.sign_raw(&seckey.0, &message.0, &nonce) { result = val; break; } } } #[allow(unused_assignments)] { nonce = Scalar::default(); } let (sigr, sigs, recid) = result; (Signature { r: sigr, s: sigs }, RecoveryId(recid)) } #[cfg(all( feature = "hmac", any(feature = "static-context", feature = "lazy-static-context") ))] /// Sign a message using the secret key. pub fn sign(message: &Message, seckey: &SecretKey) -> (Signature, RecoveryId) { sign_with_context(message, seckey, &ECMULT_GEN_CONTEXT) } #[cfg(test)] mod tests { use crate::SecretKey; use hex_literal::hex; #[test] fn secret_key_inverse_is_sane() { let sk = SecretKey::parse(&[1; 32]).unwrap(); let inv = sk.inv(); let invinv = inv.inv(); assert_eq!(sk, invinv); // Check that the inverse of `[1; 32]` is same as rust-secp256k1 assert_eq!( inv, SecretKey::parse(&hex!( "1536f1d756d1abf83aaf173bc5ee3fc487c93010f18624d80bd6d4038fadd59e" )) .unwrap() ) } #[test] fn secret_key_clear_is_correct() { let mut sk = SecretKey::parse(&[1; 32]).unwrap(); sk.clear(); assert_eq!(sk.is_zero(), true); } } ================================================ FILE: tests/serde.rs ================================================ #![cfg(feature = "std")] use libsecp256k1::*; const DEBUG_SECRET_KEY: [u8; 32] = [1u8; 32]; // Public key for debug secret key const SERIALIZED_DEBUG_PUBLIC_KEY: &str = "\"BBuExVZ7EmRAmV0+1aq6BWXXHhg0YEgZ/5wX9enV3QePcL6vj1iLVBUH/tamQsWrQt/fgSCn9jneUSLUemmo6NE=\""; fn debug_public_key() -> PublicKey { let skey = SecretKey::parse(&DEBUG_SECRET_KEY).unwrap(); PublicKey::from_secret_key(&skey) } #[test] fn test_serialize_public_key() { let pkey = debug_public_key(); let serialized_pkey = serde_json::to_string(&pkey).unwrap(); assert_eq!(serialized_pkey, SERIALIZED_DEBUG_PUBLIC_KEY); } #[test] fn test_deserialize_public_key() { let pkey: PublicKey = serde_json::from_str(&SERIALIZED_DEBUG_PUBLIC_KEY).unwrap(); assert_eq!(pkey, debug_public_key()); } #[test] fn test_public_key_bincode_serde() { let pkey = debug_public_key(); let serialized_pkey: Vec = bincode::serialize(&pkey).unwrap(); let pkey2 = bincode::deserialize(&serialized_pkey).unwrap(); assert_eq!(pkey, pkey2); } ================================================ FILE: tests/verify.rs ================================================ use libsecp256k1::*; use secp256k1_test::{ key, rand::thread_rng, Error as SecpError, Message as SecpMessage, Secp256k1, Signature as SecpSignature, }; #[cfg(feature = "hmac")] mod signatures { use crate::{recover, sign, verify, Message, PublicKey, SecretKey, SharedSecret, Signature}; use secp256k1_test::{ ecdh::SharedSecret as SecpSharedSecret, key, rand::thread_rng, recovery::{ RecoverableSignature as SecpRecoverableSignature, RecoveryId as SecpRecoveryId, }, All, Message as SecpMessage, Secp256k1, Signature as SecpSignature, }; use sha2::Sha256; fn genkey( secp256k1: &Secp256k1, ) -> (key::PublicKey, key::SecretKey, PublicKey, SecretKey) { let (secp_privkey, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()); let pubkey_a = secp_pubkey.serialize_uncompressed(); assert_eq!(pubkey_a.len(), 65); let pubkey = PublicKey::parse(&pubkey_a).unwrap(); let mut seckey_a = [0u8; 32]; for i in 0..32 { seckey_a[i] = secp_privkey[i]; } let seckey = SecretKey::parse(&seckey_a).unwrap(); (secp_pubkey, secp_privkey, pubkey, seckey) } #[test] fn test_signature_der() { let secp256k1 = Secp256k1::new(); let message_arr = [5u8; 32]; let (privkey, _) = secp256k1.generate_keypair(&mut thread_rng()); assert!(privkey[..].len() == 32); let mut privkey_a = [0u8; 32]; for i in 0..32 { privkey_a[i] = privkey[i]; } let ctx_privkey = SecretKey::parse(&privkey_a).unwrap(); let ctx_message = Message::parse(&message_arr); let (signature, _) = sign(&ctx_message, &ctx_privkey); let reconstructed = Signature::parse_der(signature.serialize_der().as_ref()).unwrap(); assert_eq!(signature, reconstructed); } #[test] fn test_sign_verify() { let secp256k1 = Secp256k1::new(); let message_arr = [6u8; 32]; let (secp_privkey, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()); let secp_message = SecpMessage::from_slice(&message_arr).unwrap(); let pubkey_a = secp_pubkey.serialize_uncompressed(); assert_eq!(pubkey_a.len(), 65); let pubkey = PublicKey::parse(&pubkey_a).unwrap(); let mut seckey_a = [0u8; 32]; for i in 0..32 { seckey_a[i] = secp_privkey[i]; } let seckey = SecretKey::parse(&seckey_a).unwrap(); let message = Message::parse(&message_arr); let (sig, recid) = sign(&message, &seckey); // Self verify assert!(verify(&message, &sig, &pubkey)); // Self recover let recovered_pubkey = recover(&message, &sig, &recid).unwrap(); let rpa = recovered_pubkey.serialize(); let opa = pubkey.serialize(); let rpr: &[u8] = &rpa; let opr: &[u8] = &opa; assert_eq!(rpr, opr); let signature_a = sig.serialize(); let secp_recid = SecpRecoveryId::from_i32(recid.into()).unwrap(); let secp_rec_signature = SecpRecoverableSignature::from_compact(&signature_a, secp_recid).unwrap(); let secp_signature = SecpSignature::from_compact(&signature_a).unwrap(); // External verify secp256k1 .verify(&secp_message, &secp_signature, &secp_pubkey) .unwrap(); // External recover let recovered_pubkey = secp256k1 .recover(&secp_message, &secp_rec_signature) .unwrap(); let rpa = recovered_pubkey.serialize_uncompressed(); let rpr: &[u8] = &rpa; assert_eq!(rpr, opr); } #[test] fn test_failing_sign_verify() { let seckey_a: [u8; 32] = [ 169, 195, 92, 103, 2, 159, 75, 46, 158, 79, 249, 49, 208, 28, 48, 210, 5, 47, 136, 77, 21, 51, 224, 54, 213, 165, 90, 122, 233, 199, 0, 248, ]; let seckey = SecretKey::parse(&seckey_a).unwrap(); let pubkey = PublicKey::from_secret_key(&seckey); let message_arr = [6u8; 32]; let message = Message::parse(&message_arr); let (sig, recid) = sign(&message, &seckey); let tmp: u8 = recid.into(); assert_eq!(tmp, 1u8); let recovered_pubkey = recover(&message, &sig, &recid).unwrap(); let rpa = recovered_pubkey.serialize(); let opa = pubkey.serialize(); let rpr: &[u8] = &rpa; let opr: &[u8] = &opa; assert_eq!(rpr, opr); } #[test] fn test_shared_secret() { let secp256k1 = Secp256k1::new(); let (spub1, ssec1, pub1, sec1) = genkey(&secp256k1); let (spub2, ssec2, pub2, sec2) = genkey(&secp256k1); let shared1 = SharedSecret::::new(&pub1, &sec2).unwrap(); let shared2 = SharedSecret::::new(&pub2, &sec1).unwrap(); let secp_shared1 = SecpSharedSecret::new(&spub1, &ssec2); let secp_shared2 = SecpSharedSecret::new(&spub2, &ssec1); assert_eq!(shared1.as_ref(), shared2.as_ref()); for i in 0..32 { assert_eq!(shared1.as_ref()[i], secp_shared1[i]); } for i in 0..32 { assert_eq!(shared2.as_ref()[i], secp_shared2[i]); } } } #[test] fn test_verify() { let secp256k1 = Secp256k1::new(); let message_arr = [5u8; 32]; let (privkey, pubkey) = secp256k1.generate_keypair(&mut thread_rng()); let message = SecpMessage::from_slice(&message_arr).unwrap(); let signature = secp256k1.sign(&message, &privkey); let pubkey_a = pubkey.serialize_uncompressed(); assert_eq!(pubkey_a.len(), 65); let ctx_pubkey = PublicKey::parse(&pubkey_a).unwrap(); let ctx_message = Message::parse(&message_arr); let signature_a = signature.serialize_compact(); assert_eq!(signature_a.len(), 64); let ctx_sig = Signature::parse_standard(&signature_a).expect("signature is valid"); secp256k1.verify(&message, &signature, &pubkey).unwrap(); assert!(verify(&ctx_message, &ctx_sig, &ctx_pubkey)); let mut f_ctx_sig = ctx_sig; f_ctx_sig.r.set_int(0); if f_ctx_sig.r != ctx_sig.r { assert!(!ECMULT_CONTEXT.verify_raw( &f_ctx_sig.r, &ctx_sig.s, &ctx_pubkey.into(), &ctx_message.0 )); } f_ctx_sig.r.set_int(1); if f_ctx_sig.r != ctx_sig.r { assert!(!ECMULT_CONTEXT.verify_raw( &f_ctx_sig.r, &ctx_sig.s, &ctx_pubkey.into(), &ctx_message.0 )); } } #[test] fn secret_clear_on_drop() { let secret: [u8; 32] = [1; 32]; let mut seckey = SecretKey::parse(&secret).unwrap(); clear_on_drop::clear::Clear::clear(&mut seckey); assert_eq!(seckey, SecretKey::default()); } #[test] fn test_recover() { let secp256k1 = Secp256k1::new(); let message_arr = [5u8; 32]; let (privkey, pubkey) = secp256k1.generate_keypair(&mut thread_rng()); let message = SecpMessage::from_slice(&message_arr).unwrap(); let signature = secp256k1.sign_recoverable(&message, &privkey); let pubkey_a = pubkey.serialize_uncompressed(); assert_eq!(pubkey_a.len(), 65); let ctx_message = Message::parse(&message_arr); let (rec_id, signature_a) = signature.serialize_compact(); assert_eq!(signature_a.len(), 64); let ctx_sig = Signature::parse_standard(&signature_a).expect("signature is valid"); // secp256k1.recover(&message, &signature).unwrap(); let ctx_pubkey = recover( &ctx_message, &ctx_sig, &RecoveryId::parse(rec_id.to_i32() as u8).unwrap(), ) .unwrap(); let sp = ctx_pubkey.serialize(); let sps: &[u8] = &sp; let gps: &[u8] = &pubkey_a; assert_eq!(sps, gps); } fn from_hex(hex: &str, target: &mut [u8]) -> Result { if hex.len() % 2 == 1 || hex.len() > target.len() * 2 { return Err(()); } let mut b = 0; let mut idx = 0; for c in hex.bytes() { b <<= 4; match c { b'A'..=b'F' => b |= c - b'A' + 10, b'a'..=b'f' => b |= c - b'a' + 10, b'0'..=b'9' => b |= c - b'0', _ => return Err(()), } if (idx & 1) == 1 { target[idx / 2] = b; b = 0; } idx += 1; } Ok(idx / 2) } macro_rules! hex { ($hex:expr) => {{ let mut result = vec![0; $hex.len() / 2]; from_hex($hex, &mut result).expect("valid hex string"); result }}; } #[test] fn test_signature_der_lax() { macro_rules! check_lax_sig { ($hex:expr) => {{ let sig = hex!($hex); assert!(Signature::parse_der_lax(&sig[..]).is_ok()); }}; } check_lax_sig!("304402204c2dd8a9b6f8d425fcd8ee9a20ac73b619906a6367eac6cb93e70375225ec0160220356878eff111ff3663d7e6bf08947f94443845e0dcc54961664d922f7660b80c"); check_lax_sig!("304402202ea9d51c7173b1d96d331bd41b3d1b4e78e66148e64ed5992abd6ca66290321c0220628c47517e049b3e41509e9d71e480a0cdc766f8cdec265ef0017711c1b5336f"); check_lax_sig!("3045022100bf8e050c85ffa1c313108ad8c482c4849027937916374617af3f2e9a881861c9022023f65814222cab09d5ec41032ce9c72ca96a5676020736614de7b78a4e55325a"); check_lax_sig!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); check_lax_sig!("3046022100eaa5f90483eb20224616775891397d47efa64c68b969db1dacb1c30acdfc50aa022100cf9903bbefb1c8000cf482b0aeeb5af19287af20bd794de11d82716f9bae3db1"); check_lax_sig!("3045022047d512bc85842ac463ca3b669b62666ab8672ee60725b6c06759e476cebdc6c102210083805e93bd941770109bcc797784a71db9e48913f702c56e60b1c3e2ff379a60"); check_lax_sig!("3044022023ee4e95151b2fbbb08a72f35babe02830d14d54bd7ed1320e4751751d1baa4802206235245254f58fd1be6ff19ca291817da76da65c2f6d81d654b5185dd86b8acf"); } #[test] fn test_low_s() { // nb this is a transaction on testnet // txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9 // input number 3 let sig = hex!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); let pk = hex!("031ee99d2b786ab3b0991325f2de8489246a6a3fdb700f6d0511b1d80cf5f4cd43"); let msg = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d"); let secp = Secp256k1::new(); let mut sig = Signature::parse_der(&sig[..]).unwrap(); let pk = key::PublicKey::from_slice(&pk[..]).unwrap(); let msg = SecpMessage::from_slice(&msg[..]).unwrap(); // without normalization we expect this will fail assert_eq!( secp.verify( &msg, &SecpSignature::from_compact(&sig.serialize()).unwrap(), &pk ), Err(SecpError::IncorrectSignature) ); // after normalization it should pass sig.normalize_s(); assert_eq!( secp.verify( &msg, &SecpSignature::from_compact(&sig.serialize()).unwrap(), &pk ), Ok(()) ); } #[test] fn test_convert_key1() { let secret: [u8; 32] = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ]; let expected: &[u8] = &[ 0x04, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, ]; let seckey = SecretKey::parse(&secret).unwrap(); let pubkey = PublicKey::from_secret_key(&seckey); assert_eq!(expected, &pubkey.serialize()[..]); let pubkey_compressed = PublicKey::parse_compressed(&pubkey.serialize_compressed()).unwrap(); assert_eq!(expected, &pubkey_compressed.serialize()[..]); } #[test] fn test_convert_key2() { let secret: [u8; 32] = [ 0x4d, 0x5d, 0xb4, 0x10, 0x7d, 0x23, 0x7d, 0xf6, 0xa3, 0xd5, 0x8e, 0xe5, 0xf7, 0x0a, 0xe6, 0x3d, 0x73, 0xd7, 0x65, 0x8d, 0x40, 0x26, 0xf2, 0xee, 0xfd, 0x2f, 0x20, 0x4c, 0x81, 0x68, 0x2c, 0xb7, ]; let expected: &[u8] = &[ 0x04, 0x3f, 0xa8, 0xc0, 0x8c, 0x65, 0xa8, 0x3f, 0x6b, 0x4e, 0xa3, 0xe0, 0x4e, 0x1c, 0xc7, 0x0c, 0xbe, 0x3c, 0xd3, 0x91, 0x49, 0x9e, 0x3e, 0x05, 0xab, 0x7d, 0xed, 0xf2, 0x8a, 0xff, 0x9a, 0xfc, 0x53, 0x82, 0x00, 0xff, 0x93, 0xe3, 0xf2, 0xb2, 0xcb, 0x50, 0x29, 0xf0, 0x3c, 0x7e, 0xbe, 0xe8, 0x20, 0xd6, 0x3a, 0x4c, 0x5a, 0x95, 0x41, 0xc8, 0x3a, 0xce, 0xbe, 0x29, 0x3f, 0x54, 0xca, 0xcf, 0x0e, ]; let seckey = SecretKey::parse(&secret).unwrap(); let pubkey = PublicKey::from_secret_key(&seckey); assert_eq!(expected, &pubkey.serialize()[..]); let pubkey_compressed = PublicKey::parse_compressed(&pubkey.serialize_compressed()).unwrap(); assert_eq!(expected, &pubkey_compressed.serialize()[..]); } #[test] fn test_convert_anykey() { let secp256k1 = Secp256k1::new(); let (secp_privkey, secp_pubkey) = secp256k1.generate_keypair(&mut thread_rng()); let mut secret = [0u8; 32]; for i in 0..32 { secret[i] = secp_privkey[i]; } let seckey = SecretKey::parse(&secret).unwrap(); let pubkey = PublicKey::from_secret_key(&seckey); let public = pubkey.serialize(); let public_compressed = pubkey.serialize_compressed(); let pubkey_r: &[u8] = &public; let pubkey_compressed_r: &[u8] = &public_compressed; let secp_pubkey_a = secp_pubkey.serialize_uncompressed(); assert_eq!(secp_pubkey_a.len(), 65); let secp_pubkey_compressed_a = secp_pubkey.serialize(); assert_eq!(secp_pubkey_compressed_a.len(), 33); let secp_pubkey_r: &[u8] = &secp_pubkey_a; let secp_pubkey_compressed_r: &[u8] = &secp_pubkey_compressed_a; assert_eq!(secp_pubkey_r, pubkey_r); assert_eq!(secp_pubkey_compressed_r, pubkey_compressed_r); } #[test] fn test_pubkey_combine() { let pk1 = PublicKey::parse(&[ 4, 126, 60, 36, 91, 73, 177, 194, 111, 11, 3, 99, 246, 204, 86, 122, 109, 85, 28, 43, 169, 243, 35, 76, 152, 90, 76, 241, 17, 108, 232, 215, 115, 15, 19, 23, 164, 151, 43, 28, 44, 59, 141, 167, 134, 112, 105, 251, 15, 193, 183, 224, 238, 154, 204, 230, 163, 216, 235, 112, 77, 239, 98, 135, 132, ]) .unwrap(); let pk2 = PublicKey::parse(&[ 4, 40, 127, 167, 223, 38, 53, 6, 223, 67, 83, 204, 60, 226, 227, 107, 231, 172, 34, 3, 187, 79, 112, 167, 0, 217, 118, 69, 218, 189, 208, 150, 190, 54, 186, 220, 95, 80, 220, 183, 202, 117, 160, 18, 84, 245, 181, 23, 32, 51, 73, 178, 173, 92, 118, 92, 122, 83, 49, 54, 195, 194, 16, 229, 39, ]) .unwrap(); let cpk = PublicKey::parse(&[ 4, 101, 166, 20, 152, 34, 76, 121, 113, 139, 80, 13, 92, 122, 96, 38, 194, 205, 149, 93, 19, 147, 132, 195, 173, 42, 86, 26, 221, 170, 127, 180, 168, 145, 21, 75, 45, 248, 90, 114, 118, 62, 196, 194, 143, 245, 204, 184, 16, 175, 202, 175, 228, 207, 112, 219, 94, 237, 75, 105, 186, 56, 102, 46, 147, ]) .unwrap(); assert_eq!(PublicKey::combine(&[pk1, pk2]).unwrap(), cpk); } #[test] fn test_pubkey_equality() { for _ in 0..10 { let secret = SecretKey::random(&mut rand::rngs::OsRng); let public = PublicKey::from_secret_key(&secret); let public2 = PublicKey::parse(&public.serialize()).unwrap(); let public3 = PublicKey::parse_compressed(&public.serialize_compressed()).unwrap(); // Reflexivity assert_eq!(public, public); assert_eq!(public2, public2); assert_eq!(public3, public3); // Symmetry assert_eq!(public2, public); assert_eq!(public, public2); assert_eq!(public2, public3); assert_eq!(public3, public2); // Transitivity assert_eq!(public, public3); assert_eq!(public3, public); } } ================================================ FILE: tests/wycheproof.rs ================================================ use serde::Deserialize; use sha2::Digest; use std::collections::HashMap; #[derive(Deserialize)] #[serde(rename_all = "camelCase")] #[allow(dead_code)] struct TestCollection { algorithm: String, generator_version: String, number_of_tests: usize, header: Vec, notes: HashMap, schema: String, test_groups: Vec, } #[derive(Deserialize)] #[serde(rename_all = "camelCase")] #[allow(dead_code)] struct TestGroup { key: TestKey, key_der: String, key_pem: String, sha: String, #[serde(rename = "type")] typ: String, tests: Vec, } #[derive(Deserialize)] #[serde(rename_all = "camelCase")] #[allow(dead_code)] struct TestKey { curve: String, key_size: usize, #[serde(rename = "type")] typ: String, uncompressed: String, wx: String, wy: String, } #[derive(Deserialize)] #[serde(rename_all = "camelCase")] #[allow(dead_code)] struct TestUnit { tc_id: usize, comment: String, msg: String, sig: String, result: TestResult, flags: Vec, } #[derive(Deserialize, PartialEq, Eq, Debug)] #[serde(rename_all = "camelCase")] enum TestResult { Valid, Acceptable, Invalid, } enum TestError { MessageDecoding, SignatureDecoding, Verification, } fn test_unit(test: &TestUnit, key: &libsecp256k1::PublicKey) -> Result<(), TestError> { println!("tcId: {}, comment: {}", test.tc_id, test.comment); let msg_raw = hex::decode(&test.msg).unwrap(); let sig_raw = hex::decode(&test.sig).unwrap(); let msg_hashed_raw = sha2::Sha256::digest(&msg_raw); let msg = libsecp256k1::Message::parse_slice(&msg_hashed_raw) .map_err(|_| TestError::MessageDecoding)?; let sig = libsecp256k1::Signature::parse_der(&sig_raw).map_err(|_| TestError::SignatureDecoding)?; if libsecp256k1::verify(&msg, &sig, &key) { Ok(()) } else { Err(TestError::Verification) } } #[test] fn test_wycheproof() { let test_collection_str = include_str!("../res/ecdsa_secp256k1_sha256_test.json"); let test_collection: TestCollection = serde_json::from_str(test_collection_str).unwrap(); for test_group in test_collection.test_groups { assert_eq!(test_group.key.typ, "EcPublicKey"); assert_eq!(test_group.key.curve, "secp256k1"); assert_eq!(test_group.key.key_size, 256); let key_raw = hex::decode(test_group.key.uncompressed).unwrap(); let key = libsecp256k1::PublicKey::parse_slice(&key_raw, None).unwrap(); for test in test_group.tests { let res = test_unit(&test, &key); match res { Ok(()) => assert!(test.result == TestResult::Valid), Err(TestError::Verification) => assert_eq!(test.result, TestResult::Invalid), Err(TestError::MessageDecoding) => assert_eq!(test.result, TestResult::Invalid), // libsecp256k1 do not use any legacy formats, so "acceptable" // result in wycheproof is considered the same as invalid. Err(TestError::SignatureDecoding) => assert!( test.result == TestResult::Acceptable || test.result == TestResult::Invalid ), } } } }