diff --git a/.github/workflows/cross.yml b/.github/workflows/cross.yml new file mode 100644 index 000000000..40e89f40a --- /dev/null +++ b/.github/workflows/cross.yml @@ -0,0 +1,44 @@ +name: Cross + +on: + push: + branches: [ '**' ] + pull_request: + branches: [ '**' ] + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: '-D warnings' + +jobs: + + test-cross: + name: Test + strategy: + matrix: + include: + # ARM32 + - target: armv7-unknown-linux-gnueabihf + rust: stable + + # ARM64 + - target: aarch64-unknown-linux-gnu + rust: stable + + # PPC32 + - target: powerpc-unknown-linux-gnu + rust: stable + + # TODO: We only test x/ed/curve for cross as derive is platform specifics + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: ${{ matrix.deps }} + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - uses: RustCrypto/actions/cross-install@master + - run: cross test -p curve25519-dalek --release --target ${{ matrix.target }} + - run: cross test -p ed25519-dalek --release --target ${{ matrix.target }} + - run: cross test -p x25519-dalek --release --target ${{ matrix.target }} diff --git a/.github/workflows/curve25519-dalek.yml b/.github/workflows/curve25519-dalek.yml new file mode 100644 index 000000000..461356a22 --- /dev/null +++ b/.github/workflows/curve25519-dalek.yml @@ -0,0 +1,117 @@ +name: curve25519 Rust + +on: + push: + branches: [ '**' ] + paths: 'curve25519-dalek/**' + pull_request: + branches: [ '**' ] + paths: 'curve25519-dalek/**' + +defaults: + run: + working-directory: curve25519-dalek + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: '-D warnings' + +jobs: + + test-fiat: + name: Test fiat backend + runs-on: ubuntu-latest + strategy: + matrix: + include: + # 32-bit target + - target: i686-unknown-linux-gnu + deps: sudo apt update && sudo apt install gcc-multilib + + # 64-bit target + - target: x86_64-unknown-linux-gnu + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - run: rustup target add ${{ matrix.target }} + - run: ${{ matrix.deps }} + - env: + RUSTFLAGS: '--cfg curve25519_dalek_backend="fiat"' + run: cargo test --target ${{ matrix.target }} + + test-serial: + name: Test serial backend + runs-on: ubuntu-latest + strategy: + matrix: + include: + # 32-bit target + - target: i686-unknown-linux-gnu + deps: sudo apt update && sudo apt install gcc-multilib + + # 64-bit target + - target: x86_64-unknown-linux-gnu + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - run: rustup target add ${{ matrix.target }} + - run: ${{ matrix.deps }} + - env: + RUSTFLAGS: '--cfg curve25519_dalek_backend="serial"' + run: cargo test --target ${{ matrix.target }} + + build-script: + name: Test Build Script + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + targets: wasm32-unknown-unknown,x86_64-unknown-linux-gnu,i686-unknown-linux-gnu + - run: bash tests/build_tests.sh + + test-simd-nightly: + name: Test simd backend (nightly) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly + - env: + # This will: + # 1) build all of the x86_64 SIMD code, + # 2) run all of the SIMD-specific tests that the test runner supports, + # 3) run all of the normal tests using the best available SIMD backend. + # This should automatically pick up the simd backend in a x84_64 runner + RUSTFLAGS: '-C target_cpu=native' + run: cargo test --target x86_64-unknown-linux-gnu + + test-simd-stable: + name: Test simd backend (stable) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - env: + # This will run AVX2-specific tests and run all of the normal tests + # with the AVX2 backend, even if the runner supports AVX512. + # This should automatically pick up the simd backend in a x86_64 runner + # It should pick AVX2 due to stable toolchain used since AVX512 requires nigthly + RUSTFLAGS: '-C target_feature=+avx2' + run: cargo test --no-default-features --features alloc,precomputed-tables,zeroize --target x86_64-unknown-linux-gnu + + msrv: + name: Current MSRV is 1.60.0 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + # First run `cargo +nightly -Z minimal-verisons check` in order to get a + # Cargo.lock with the oldest possible deps + - uses: dtolnay/rust-toolchain@nightly + - run: cargo -Z minimal-versions check --no-default-features --features serde + # Now check that `cargo build` works with respect to the oldest possible + # deps and the stated MSRV + - uses: dtolnay/rust-toolchain@1.60.0 + - run: cargo build --no-default-features --features serde + # Also make sure the AVX2 build works + - run: cargo build --target x86_64-unknown-linux-gnu diff --git a/.github/workflows/ed25519-dalek.yml b/.github/workflows/ed25519-dalek.yml new file mode 100644 index 000000000..83a926daf --- /dev/null +++ b/.github/workflows/ed25519-dalek.yml @@ -0,0 +1,36 @@ +name: ed25519 Rust + +on: + push: + branches: [ '**' ] + paths: 'ed25519-dalek/**' + pull_request: + branches: [ '**' ] + paths: 'ed25519-dalek/**' + +defaults: + run: + working-directory: ed25519-dalek + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: '-D warnings' + RUSTDOCFLAGS: '-D warnings' + +jobs: + + msrv: + name: Current MSRV is 1.60.0 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + # First delete the checked-in `Cargo.lock`. We're going to regenerate it + - run: rm Cargo.lock + # Now run `cargo +nightly -Z minimal-verisons check` in order to get a + # Cargo.lock with the oldest possible deps + - uses: dtolnay/rust-toolchain@nightly + - run: cargo -Z minimal-versions check --no-default-features --features serde + # Now check that `cargo build` works with respect to the oldest possible + # deps and the stated MSRV + - uses: dtolnay/rust-toolchain@1.60.0 + - run: cargo build diff --git a/.github/workflows/no_std.yml b/.github/workflows/no_std.yml new file mode 100644 index 000000000..c99fbffaa --- /dev/null +++ b/.github/workflows/no_std.yml @@ -0,0 +1,35 @@ +name: no_std + +on: + push: + branches: [ '**' ] + pull_request: + branches: [ '**' ] + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: '-D warnings' + +jobs: + + build-nostd: + name: Build on no_std target (thumbv7em-none-eabi) + runs-on: ubuntu-latest + strategy: + matrix: + include: + - crate: curve25519-dalek + - crate: ed25519-dalek + - crate: x25519-dalek + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + targets: thumbv7em-none-eabi + - uses: taiki-e/install-action@cargo-hack + # No default features build + - name: no_std / no feat ${{ matrix.crate }} + run: cargo build -p ${{ matrix.crate }} --target thumbv7em-none-eabi --release --no-default-features + - name: no_std / cargo hack ${{ matrix.crate }} + run: cargo hack build -p ${{ matrix.crate }} --target thumbv7em-none-eabi --release --each-feature --exclude-features default,std,getrandom diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml deleted file mode 100644 index 77d38581c..000000000 --- a/.github/workflows/rust.yml +++ /dev/null @@ -1,230 +0,0 @@ -name: Rust - -on: - push: - branches: [ '**' ] - pull_request: - branches: [ '**' ] - -env: - CARGO_TERM_COLOR: always - RUSTFLAGS: '-D warnings' - -jobs: - test-auto: - runs-on: ubuntu-latest - strategy: - matrix: - include: - # 32-bit target - - target: i686-unknown-linux-gnu - deps: sudo apt update && sudo apt install gcc-multilib - - # 64-bit target - - target: x86_64-unknown-linux-gnu - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable - - run: rustup target add ${{ matrix.target }} - - run: ${{ matrix.deps }} - - run: cargo test --target ${{ matrix.target }} --no-default-features - - run: cargo test --target ${{ matrix.target }} --no-default-features --features alloc - - run: cargo test --target ${{ matrix.target }} --no-default-features --features digest - - run: cargo test --target ${{ matrix.target }} --no-default-features --features precomputed-tables - - run: cargo test --target ${{ matrix.target }} --no-default-features --features rand_core - - run: cargo test --target ${{ matrix.target }} --no-default-features --features serde - - run: cargo test --target ${{ matrix.target }} --no-default-features --features zeroize - - run: cargo test --target ${{ matrix.target }} - - run: cargo test --target ${{ matrix.target }} --features digest - - run: cargo test --target ${{ matrix.target }} --features rand_core - - run: cargo test --target ${{ matrix.target }} --features serde - - test-fiat: - runs-on: ubuntu-latest - strategy: - matrix: - include: - # 32-bit target - - target: i686-unknown-linux-gnu - deps: sudo apt update && sudo apt install gcc-multilib - - # 64-bit target - - target: x86_64-unknown-linux-gnu - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable - - run: rustup target add ${{ matrix.target }} - - run: ${{ matrix.deps }} - - env: - RUSTFLAGS: '--cfg curve25519_dalek_backend="fiat"' - run: cargo test --target ${{ matrix.target }} - - test-serial: - runs-on: ubuntu-latest - strategy: - matrix: - include: - # 32-bit target - - target: i686-unknown-linux-gnu - deps: sudo apt update && sudo apt install gcc-multilib - - # 64-bit target - - target: x86_64-unknown-linux-gnu - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable - - run: rustup target add ${{ matrix.target }} - - run: ${{ matrix.deps }} - - env: - RUSTFLAGS: '--cfg curve25519_dalek_backend="serial"' - run: cargo test --target ${{ matrix.target }} - - build-script: - name: Test Build Script - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - targets: wasm32-unknown-unknown,x86_64-unknown-linux-gnu,i686-unknown-linux-gnu - - run: bash tests/build_tests.sh - - build-nostd: - name: Build on no_std target (thumbv7em-none-eabi) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: stable - targets: thumbv7em-none-eabi - - run: cargo build --target thumbv7em-none-eabi --release --no-default-features - - run: cargo build --target thumbv7em-none-eabi --release - - run: cargo build --target thumbv7em-none-eabi --release --features serde - - test-simd-nightly: - name: Test simd backend (nightly) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@nightly - - env: - # This will: - # 1) build all of the x86_64 SIMD code, - # 2) run all of the SIMD-specific tests that the test runner supports, - # 3) run all of the normal tests using the best available SIMD backend. - # This should automatically pick up the simd backend in a x84_64 runner - RUSTFLAGS: '-C target_cpu=native' - run: cargo test --target x86_64-unknown-linux-gnu - - test-simd-stable: - name: Test simd backend (stable) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable - - env: - # This will run AVX2-specific tests and run all of the normal tests - # with the AVX2 backend, even if the runner supports AVX512. - # This should automatically pick up the simd backend in a x86_64 runner - # It should pick AVX2 due to stable toolchain used since AVX512 requires nigthly - RUSTFLAGS: '-C target_feature=+avx2' - run: cargo test --no-default-features --features alloc,precomputed-tables,zeroize --target x86_64-unknown-linux-gnu - - build-docs: - name: Build docs - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@nightly - - run: make doc - - run: make doc-internal - - cross: - strategy: - matrix: - include: - # ARM32 - - target: armv7-unknown-linux-gnueabihf - rust: stable - - # ARM64 - - target: aarch64-unknown-linux-gnu - rust: stable - - # PPC32 - - target: powerpc-unknown-linux-gnu - rust: stable - - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - run: ${{ matrix.deps }} - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ matrix.rust }} - targets: ${{ matrix.target }} - - uses: RustCrypto/actions/cross-install@master - - run: cross test --release --target ${{ matrix.target }} - - nightly: - name: Test nightly compiler - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@nightly - - run: cargo test - - clippy: - name: Check that clippy is happy - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@nightly - with: - components: clippy - - run: cargo clippy --target x86_64-unknown-linux-gnu - - rustfmt: - name: Check formatting - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable - with: - components: rustfmt - - run: cargo fmt --all -- --check - - msrv: - name: Current MSRV is 1.60.0 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - # First run `cargo +nightly -Z minimal-verisons check` in order to get a - # Cargo.lock with the oldest possible deps - - uses: dtolnay/rust-toolchain@nightly - - run: cargo -Z minimal-versions check --no-default-features --features serde - # Now check that `cargo build` works with respect to the oldest possible - # deps and the stated MSRV - - uses: dtolnay/rust-toolchain@1.60.0 - - run: cargo build --no-default-features --features serde - # Also make sure the AVX2 build works - - run: cargo build --target x86_64-unknown-linux-gnu - - bench: - name: Check that benchmarks compile - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable - - name: Build u32 bench - env: - RUSTFLAGS: '--cfg curve25519_dalek_bits="32"' - run: cargo build --benches - - name: Build u64 bench - env: - RUSTFLAGS: '--cfg curve25519_dalek_bits="64"' - run: cargo build --benches - - name: Build default (host native) bench - run: cargo build --benches diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml new file mode 100644 index 000000000..6d01743d5 --- /dev/null +++ b/.github/workflows/workspace.yml @@ -0,0 +1,88 @@ +name: All + +on: + push: + branches: [ '**' ] + pull_request: + branches: [ '**' ] + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: '-D warnings' + +jobs: + test-stable: + name: Test 32/64 bit stable + runs-on: ubuntu-latest + strategy: + matrix: + include: + # 32-bit target + - target: i686-unknown-linux-gnu + deps: sudo apt update && sudo apt install gcc-multilib + + # 64-bit target + - target: x86_64-unknown-linux-gnu + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - run: rustup target add ${{ matrix.target }} + - run: ${{ matrix.deps }} + - run: cargo test --target ${{ matrix.target }} --no-default-features + - run: cargo test --target ${{ matrix.target }} + - run: cargo test --target ${{ matrix.target }} --all-features + + test-nightly: + name: Test Nightly + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo test + + bench: + name: Check that benchmarks compile + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - name: Build u32 bench + env: + RUSTFLAGS: '--cfg curve25519_dalek_bits="32"' + run: cargo build --benches + - name: Build u64 bench + env: + RUSTFLAGS: '--cfg curve25519_dalek_bits="64"' + run: cargo build --benches + - name: Build default (host native) bench + run: cargo build --benches + + clippy: + name: Check that clippy is happy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy + - run: cargo clippy --target x86_64-unknown-linux-gnu + + rustfmt: + name: Check formatting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - run: cargo fmt --all -- --check + + doc: + name: Check docs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + - run: cargo doc --all-features diff --git a/.github/workflows/x25519-dalek.yml b/.github/workflows/x25519-dalek.yml new file mode 100644 index 000000000..218f6f8f9 --- /dev/null +++ b/.github/workflows/x25519-dalek.yml @@ -0,0 +1,36 @@ +name: x25519 Rust + +on: + push: + branches: [ '**' ] + paths: 'x25519-dalek/**' + pull_request: + branches: [ '**' ] + paths: 'x25519-dalek/**' + +defaults: + run: + working-directory: x25519-dalek + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: '-D warnings' + RUSTDOCFLAGS: '-D warnings' + +jobs: + + msrv: + name: Current MSRV is 1.60.0 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + # First delete the checked-in `Cargo.lock`. We're going to regenerate it + - run: rm Cargo.lock + # Now run `cargo +nightly -Z minimal-verisons check` in order to get a + # Cargo.lock with the oldest possible deps + - uses: dtolnay/rust-toolchain@nightly + - run: cargo -Z minimal-versions check --no-default-features --features serde + # Now check that `cargo build` works with respect to the oldest possible + # deps and the stated MSRV + - uses: dtolnay/rust-toolchain@1.60.0 + - run: cargo build diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index a802fde53..000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,8 +0,0 @@ -# Code of Conduct - -We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html), -with the following additional clauses: - -* We respect the rights to privacy and anonymity for contributors and people in - the community. If someone wishes to contribute under a pseudonym different to - their primary identity, that wish is to be respected by all contributors. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d4e0ff8e5..243e927f2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ Patches are welcomed as pull requests on email (preferably sent to all of the authors listed in `Cargo.toml`). All issues on curve25519-dalek are mentored, if you want help with a bug just -ask @isislovecruft or @hdevalence. +ask @rozbb or @tarcieri. Some issues are easier than others. The `easy` label can be used to find the easy issues. If you want to work on an issue, please leave a comment so that we diff --git a/Cargo.toml b/Cargo.toml index cc7a5ca58..a891c6705 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,73 +1,12 @@ -[package] -name = "curve25519-dalek" -# Before incrementing: -# - update CHANGELOG -# - update README if required by semver -# - if README was updated, also update module documentation in src/lib.rs -version = "4.0.0-rc.3" -edition = "2021" -rust-version = "1.60.0" -authors = ["Isis Lovecruft ", - "Henry de Valence "] -readme = "README.md" -license = "BSD-3-Clause" -repository = "https://github.com/dalek-cryptography/curve25519-dalek" -homepage = "https://github.com/dalek-cryptography/curve25519-dalek" -documentation = "https://docs.rs/curve25519-dalek" -categories = ["cryptography", "no-std"] -keywords = ["cryptography", "crypto", "ristretto", "curve25519", "ristretto255"] -description = "A pure-Rust implementation of group operations on ristretto255 and Curve25519" -exclude = [ - "**/.gitignore", - ".gitignore", +[workspace] +members = [ + "curve25519-dalek", + "curve25519-dalek-derive", + "ed25519-dalek", + "x25519-dalek" ] - -[package.metadata.docs.rs] -rustdoc-args = [ - "--html-in-header", "docs/assets/rustdoc-include-katex-header.html", - "--cfg", "docsrs", -] -features = ["serde", "rand_core", "digest", "legacy_compatibility"] - -[dev-dependencies] -sha2 = { version = "0.10", default-features = false } -bincode = "1" -criterion = { version = "0.4.0", features = ["html_reports"] } -hex = "0.4.2" -rand = "0.8" -rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } - -[build-dependencies] -platforms = "3.0.2" -rustc_version = "0.4.0" - -[[bench]] -name = "dalek_benchmarks" -harness = false -required-features = ["alloc", "rand_core"] - -[dependencies] -cfg-if = "1" -rand_core = { version = "0.6.4", default-features = false, optional = true } -digest = { version = "0.10", default-features = false, optional = true } -subtle = { version = "2.3.0", default-features = false } -serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } -zeroize = { version = "1", default-features = false, optional = true } - -[target.'cfg(target_arch = "x86_64")'.dependencies] -cpufeatures = "0.2.6" - -[target.'cfg(curve25519_dalek_backend = "fiat")'.dependencies] -fiat-crypto = "0.1.19" - -[features] -default = ["alloc", "precomputed-tables", "zeroize"] -alloc = ["zeroize?/alloc"] -precomputed-tables = [] -legacy_compatibility = [] - -[target.'cfg(all(not(curve25519_dalek_backend = "fiat"), not(curve25519_dalek_backend = "serial"), target_arch = "x86_64"))'.dependencies] -curve25519-dalek-derive = { version = "0.1", path = "curve25519-dalek-derive" } +resolver = "2" [profile.dev] opt-level = 2 + diff --git a/README.md b/README.md index d26eaa367..03ae9ba87 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,3 @@ - -# curve25519-dalek [![](https://buildstats.info/crate/curve25519-dalek)](https://crates.io/crates/curve25519-dalek) [![](https://img.shields.io/docsrs/curve25519-dalek)](https://docs.rs/curve25519-dalek) [![Rust](https://github.com/dalek-cryptography/curve25519-dalek/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/dalek-cryptography/curve25519-dalek/actions/workflows/rust.yml) -

dalek-cryptography logo: a dalek with edwards curves as sparkles coming out of its radar-schnozzley blaster thingies

-**A pure-Rust implementation of group operations on Ristretto and Curve25519.** - -`curve25519-dalek` is a library providing group operations on the Edwards and -Montgomery forms of Curve25519, and on the prime-order Ristretto group. - -`curve25519-dalek` is not intended to provide implementations of any particular -crypto protocol. Rather, implementations of those protocols (such as -[`x25519-dalek`][x25519-dalek] and [`ed25519-dalek`][ed25519-dalek]) should use -`curve25519-dalek` as a library. - -`curve25519-dalek` is intended to provide a clean and safe _mid-level_ API for use -implementing a wide range of ECC-based crypto protocols, such as key agreement, -signatures, anonymous credentials, rangeproofs, and zero-knowledge proof -systems. - -In particular, `curve25519-dalek` implements Ristretto, which constructs a -prime-order group from a non-prime-order Edwards curve. This provides the -speed and safety benefits of Edwards curve arithmetic, without the pitfalls of -cofactor-related abstraction mismatches. - -# Use - -## Stable - -To import `curve25519-dalek`, add the following to the dependencies section of -your project's `Cargo.toml`: -```toml -curve25519-dalek = "3" -``` - -## Beta - -To use the latest prerelease (see changes [below](#breaking-changes-in-400)), -use the following line in your project's `Cargo.toml`: -```toml -curve25519-dalek = "4.0.0-rc.3" -``` - -## Feature Flags - -| Feature | Default? | Description | -| :--- | :---: | :--- | -| `alloc` | ✓ | Enables Edwards and Ristretto multiscalar multiplication, batch scalar inversion, and batch Ristretto double-and-compress. Also enables `zeroize`. | -| `zeroize` | ✓ | Enables [`Zeroize`][zeroize-trait] for all scalar and curve point types. | -| `precomputed-tables` | ✓ | Includes precomputed basepoint multiplication tables. This speeds up `EdwardsPoint::mul_base` and `RistrettoPoint::mul_base` by ~4x, at the cost of ~30KB added to the code size. | -| `rand_core` | | Enables `Scalar::random` and `RistrettoPoint::random`. This is an optional dependency whose version is not subject to SemVer. See [below](#public-api-semver-exemptions) for more details. | -| `digest` | | Enables `RistrettoPoint::{from_hash, hash_from_bytes}` and `Scalar::{from_hash, hash_from_bytes}`. This is an optional dependency whose version is not subject to SemVer. See [below](#public-api-semver-exemptions) for more details. | -| `serde` | | Enables `serde` serialization/deserialization for all the point and scalar types. | -| `legacy_compatibility`| | Enables `Scalar::from_bits`, which allows the user to build unreduced scalars whose arithmetic is broken. Do not use this unless you know what you're doing. | - -To disable the default features when using `curve25519-dalek` as a dependency, -add `default-features = false` to the dependency in your `Cargo.toml`. To -disable it when running `cargo`, add the `--no-default-features` CLI flag. - -## Major Version API Changes - -Breaking changes for each major version release can be found in -[`CHANGELOG.md`](CHANGELOG.md), under the "Breaking changes" subheader. The -latest breaking changes in high level are below: - -### Breaking changes in 4.0.0 - -* Update the MSRV from 1.41 to 1.60 -* Provide SemVer policy -* Make `digest` and `rand_core` optional features -* Remove `std` and `nightly` features -* Replace backend selection - See [CHANGELOG.md](CHANGELOG.md) and [backends](#backends) -* Replace methods `Scalar::{zero, one}` with constants `Scalar::{ZERO, ONE}` -* `Scalar::from_canonical_bytes` now returns `CtOption` -* `Scalar::is_canonical` now returns `Choice` -* Remove `Scalar::from_bytes_clamped` and `Scalar::reduce` -* Deprecate and feature-gate `Scalar::from_bits` behind `legacy_compatibility` -* Deprecate `EdwardsPoint::hash_from_bytes` and rename it - `EdwardsPoint::nonspec_map_to_curve` -* Require including a new trait, `use curve25519_dalek::traits::BasepointTable` - whenever using `EdwardsBasepointTable` or `RistrettoBasepointTable` - -This release also does a lot of dependency updates and relaxations to unblock upstream build issues. - -# Backends - -Curve arithmetic is implemented and used by one of the following backends: - -| Backend | Selection | Implementation | Bits / Word sizes | -| :--- | :--- | :--- | :--- | -| `serial` | Automatic | An optimized, non-parllel implementation | `32` and `64` | -| `fiat` | Manual | Formally verified field arithmetic from [fiat-crypto] | `32` and `64` | -| `simd` | Automatic | Intel AVX2 / AVX512 IFMA accelerated backend | `64` only | - -At runtime, `curve25519-dalek` selects an arithmetic backend from the set of backends it was compiled to support. For Intel x86-64 targets, unless otherwise specified, it will build itself with `simd` support, and default to `serial` at runtime if the appropriate CPU features aren't detected. See [SIMD backend] for more details. - -In the future, `simd` backend may be extended to cover more instruction sets. This change will be non-breaking as this is considered as implementation detail. - -## Manual Backend Override - -You can force the crate to compile with specific backend support, e.g., `serial` for x86-64 targets to save code size, or `fiat` to force the runtime to use verified code. To do this, set the environment variable: -```sh -RUSTFLAGS='--cfg curve25519_dalek_backend="BACKEND"' -``` -Equivalently, you can write to -`~/.cargo/config`: -```toml -[build] -rustflags = ['--cfg=curve25519_dalek_backend="BACKEND"'] -``` -More info [here](https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags). - -Note for contributors: The target backends are not entirely independent of each -other. The [SIMD backend] directly depends on parts of the serial backend to -function. - -## Bits / Word size - -`curve25519-dalek` will automatically choose the word size for the `fiat` and -`serial` backends, based on the build target. -For example, building for a 64-bit machine, the default 64 bit word size is -automatically chosen when either the `serial` or `fiat` backend is selected. - -In some targets it might be required to override the word size for better -performance. -Backend word size can be overridden for `serial` and `fiat` by setting the -environment variable: -```sh -RUSTFLAGS='--cfg curve25519_dalek_bits="SIZE"' -``` -`SIZE` is `32` or `64`. As in the above section, this can also be placed -in `~/.cargo/config`. - -Note: The [SIMD backend] requires a word size of 64 bits. Attempting to set bits=32 and backend=`simd` will yield a compile error. - -### Cross-compilation - -Because backend selection is done by target, cross-compiling will select the correct word size automatically. For example, if a x86-64 Linux machine runs the following commands, `curve25519-dalek` will be compiled with the 32-bit `serial` backend. -```console -$ sudo apt install gcc-multilib # (or whatever package manager you use) -$ rustup target add i686-unknown-linux-gnu -$ cargo build --target i686-unknown-linux-gnu -``` +# Dalek elliptic curve cryptography -## SIMD backend +This repo contains pure-Rust crates for elliptic curve cryptography: -The specific SIMD backend (AVX512 / AVX2 / `serial` default) is selected automatically at runtime, depending on the currently available CPU features, and whether Rust nightly is being used for compilation. The precise conditions are specified below. -For a given CPU feature, you can also specify an appropriate `-C target_feature` to build a binary which assumes the required SIMD instructions are always available. Don't do this if you don't have a good reason. +| Crate | Description | Crates.io | Docs | CI | +-------------------------------------------|----------------|-----------|------|------- +| [`curve25519-dalek`](./curve25519-dalek) | A library for arithmetic over the Curve25519 and Ristretto elliptic curves and their associated scalars. | [![](https://buildstats.info/crate/curve25519-dalek)](https://crates.io/crates/curve25519-dalek) | [![](https://img.shields.io/docsrs/curve25519-dalek)](https://docs.rs/curve25519-dalek) | [![Rust](https://github.com/dalek-cryptography/curve25519-dalek/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/dalek-cryptography/curve25519-dalek/actions/workflows/rust.yml) | +| [`ed25519-dalek`](./ed25519-dalek) | An implementation of the EdDSA digital signature scheme over Curve25519. | [![](https://img.shields.io/crates/v/ed25519-dalek.svg)](https://crates.io/crates/ed25519-dalek) | [![](https://docs.rs/ed25519-dalek/badge.svg)](https://docs.rs/ed25519-dalek) | [![Rust](https://github.com/dalek-cryptography/ed25519-dalek/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/dalek-cryptography/ed25519-dalek/actions/workflows/rust.yml) | +| [`x25519-dalek`](./x25519-dalek) | An implementation of elliptic curve Diffie-Hellman key exchange over Curve25519. | [![](https://img.shields.io/crates/v/x25519-dalek.svg)](https://crates.io/crates/x25519-dalek) | [![](https://docs.rs/x25519-dalek/badge.svg)](https://docs.rs/x25519-dalek) | [![](https://travis-ci.org/dalek-cryptography/x25519-dalek.svg?branch=master)](https://travis-ci.org/dalek-cryptography/x25519-dalek) | -| Backend | `RUSTFLAGS` | Requires nightly? | -| :--- | :--- | :--- | -| avx2 | `-C target_feature=+avx2` | no | -| avx512 | `-C target_feature=+avx512ifma,+avx512vl` | yes | - -If compiled on a non-nightly compiler, `curve25519-dalek` will not include AVX512 code, and therefore will never select it at runtime. - -# Documentation - -The semver-stable, public-facing `curve25519-dalek` API is documented [here][docs]. - -## Building Docs Locally - -The `curve25519-dalek` documentation requires a custom HTML header to include -KaTeX for math support. Unfortunately `cargo doc` does not currently support -this, but docs can be built using -```sh -make doc -``` -for regular docs, and -```sh -make doc-internal -``` -for docs that include private items. - -# Maintenance Policies - -All on-by-default features of this library are covered by -[semantic versioning][semver] (SemVer). SemVer exemptions are outlined below -for MSRV and public API. - -## Minimum Supported Rust Version - -| Releases | MSRV | -| :--- |:-------| -| 4.x | 1.60.0 | -| 3.x | 1.41.0 | - -From 4.x and on, MSRV changes will be accompanied by a minor version bump. - -## Public API SemVer Exemptions - -Breaking changes to SemVer exempted components affecting the public API will be accompanied by -_some_ version bump. Below are the specific policies: - -| Releases | Public API Component(s) | Policy | -| :--- | :--- | :--- | -| 4.x | Dependencies `digest` and `rand_core` | Minor SemVer bump | - -# Safety - -The `curve25519-dalek` types are designed to make illegal states -unrepresentable. For example, any instance of an `EdwardsPoint` is -guaranteed to hold a point on the Edwards curve, and any instance of a -`RistrettoPoint` is guaranteed to hold a valid point in the Ristretto -group. - -All operations are implemented using constant-time logic (no -secret-dependent branches, no secret-dependent memory accesses), -unless specifically marked as being variable-time code. -We believe that our constant-time logic is lowered to constant-time -assembly, at least on `x86_64` targets. - -As an additional guard against possible future compiler optimizations, -the `subtle` crate places an optimization barrier before every -conditional move or assignment. More details can be found in [the -documentation for the `subtle` crate][subtle_doc]. - -Some functionality (e.g., multiscalar multiplication or batch -inversion) requires heap allocation for temporary buffers. All -heap-allocated buffers of potentially secret data are explicitly -zeroed before release. - -However, we do not attempt to zero stack data, for two reasons. -First, it's not possible to do so correctly: we don't have control -over stack allocations, so there's no way to know how much data to -wipe. Second, because `curve25519-dalek` provides a mid-level API, -the correct place to start zeroing stack data is likely not at the -entrypoints of `curve25519-dalek` functions, but at the entrypoints of -functions in other crates. - -The implementation is memory-safe, and contains no significant -`unsafe` code. The SIMD backend uses `unsafe` internally to call SIMD -intrinsics. These are marked `unsafe` only because invoking them on an -inappropriate CPU would cause `SIGILL`, but the entire backend is only -invoked when the appropriate CPU features are detected at runtime, or -when the whole program is compiled with the appropriate `target_feature`s. - -# Performance - -Benchmarks are run using [`criterion.rs`][criterion]: - -```sh -cargo bench --features "rand_core" -export RUSTFLAGS='-C target_cpu=native' -cargo +nightly bench --features "rand_core" -``` - -Performance is a secondary goal behind correctness, safety, and -clarity, but we aim to be competitive with other implementations. - -# FFI - -Unfortunately, we have no plans to add FFI to `curve25519-dalek` directly. The -reason is that we use Rust features to provide an API that maintains safety -invariants, which are not possible to maintain across an FFI boundary. For -instance, as described in the _Safety_ section above, invalid points are -impossible to construct, and this would not be the case if we exposed point -operations over FFI. - -However, `curve25519-dalek` is designed as a *mid-level* API, aimed at -implementing other, higher-level primitives. Instead of providing FFI at the -mid-level, our suggestion is to implement the higher-level primitive (a -signature, PAKE, ZKP, etc) in Rust, using `curve25519-dalek` as a dependency, -and have that crate provide a minimal, byte-buffer-oriented FFI specific to -that primitive. +There is also the [`curve25519-dalek-derive`](./curve25519-dalek-derive) crate, which is just a helper crate with some macros that make curve25519-dalek easier to write. # Contributing -Please see [CONTRIBUTING.md][contributing]. - -# About - -**SPOILER ALERT:** *The Twelfth Doctor's first encounter with the Daleks is in -his second full episode, "Into the Dalek". A beleaguered ship of the "Combined -Galactic Resistance" has discovered a broken Dalek that has turned "good", -desiring to kill all other Daleks. The Doctor, Clara and a team of soldiers -are miniaturized and enter the Dalek, which the Doctor names Rusty. They -repair the damage, but accidentally restore it to its original nature, causing -it to go on the rampage and alert the Dalek fleet to the whereabouts of the -rebel ship. However, the Doctor manages to return Rusty to its previous state -by linking his mind with the Dalek's: Rusty shares the Doctor's view of the -universe's beauty, but also his deep hatred of the Daleks. Rusty destroys the -other Daleks and departs the ship, determined to track down and bring an end -to the Dalek race.* - -`curve25519-dalek` is authored by Isis Agora Lovecruft and Henry de Valence. - -Portions of this library were originally a port of [Adam Langley's -Golang ed25519 library](https://github.com/agl/ed25519), which was in -turn a port of the reference `ref10` implementation. Most of this code, -including the 32-bit field arithmetic, has since been rewritten. - -The fast `u32` and `u64` scalar arithmetic was implemented by Andrew Moon, and -the addition chain for scalar inversion was provided by Brian Smith. The -optimised batch inversion was contributed by Sean Bowe and Daira Hopwood. - -The `no_std` and `zeroize` support was contributed by Tony Arcieri. +Please see [`CONTRIBUTING.md`](./CONTRIBUTING.md). -The formally verified `fiat_backend` integrates Rust code generated by the -[Fiat Crypto project](https://github.com/mit-plv/fiat-crypto) and was -contributed by François Garillot. +# Code of Conduct -Thanks also to Ashley Hauck, Lucas Salibian, Manish Goregaokar, Jack Grigg, -Pratyush Mishra, Michael Rosenberg, @pinkforest, and countless others for their -contributions. +We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html), +with the following additional clauses: -[ed25519-dalek]: https://github.com/dalek-cryptography/ed25519-dalek -[x25519-dalek]: https://github.com/dalek-cryptography/x25519-dalek -[docs]: https://docs.rs/curve25519-dalek/ -[contributing]: https://github.com/dalek-cryptography/curve25519-dalek/blob/master/CONTRIBUTING.md -[criterion]: https://github.com/japaric/criterion.rs -[parallel_doc]: https://docs.rs/curve25519-dalek/latest/curve25519_dalek/backend/vector/index.html -[subtle_doc]: https://docs.rs/subtle -[fiat-crypto]: https://github.com/mit-plv/fiat-crypto -[semver]: https://semver.org/spec/v2.0.0.html -[rngcorestd]: https://github.com/rust-random/rand/tree/7aa25d577e2df84a5156f824077bb7f6bdf28d97/rand_core#crate-features -[zeroize-trait]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html -[SIMD backend]: #simd-backend +* We respect the rights to privacy and anonymity for contributors and people in + the community. If someone wishes to contribute under a pseudonym different to + their primary identity, that wish is to be respected by all contributors. diff --git a/CHANGELOG.md b/curve25519-dalek/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to curve25519-dalek/CHANGELOG.md diff --git a/curve25519-dalek/Cargo.toml b/curve25519-dalek/Cargo.toml new file mode 100644 index 000000000..7b1d9acdc --- /dev/null +++ b/curve25519-dalek/Cargo.toml @@ -0,0 +1,70 @@ +[package] +name = "curve25519-dalek" +# Before incrementing: +# - update CHANGELOG +# - update README if required by semver +# - if README was updated, also update module documentation in src/lib.rs +version = "4.0.0-rc.3" +edition = "2021" +rust-version = "1.60.0" +authors = ["Isis Lovecruft ", + "Henry de Valence "] +readme = "README.md" +license = "BSD-3-Clause" +repository = "https://github.com/dalek-cryptography/curve25519-dalek" +homepage = "https://github.com/dalek-cryptography/curve25519-dalek" +documentation = "https://docs.rs/curve25519-dalek" +categories = ["cryptography", "no-std"] +keywords = ["cryptography", "crypto", "ristretto", "curve25519", "ristretto255"] +description = "A pure-Rust implementation of group operations on ristretto255 and Curve25519" +exclude = [ + "**/.gitignore", + ".gitignore", +] + +[package.metadata.docs.rs] +rustdoc-args = [ + "--html-in-header", "docs/assets/rustdoc-include-katex-header.html", + "--cfg", "docsrs", +] +features = ["serde", "rand_core", "digest", "legacy_compatibility"] + +[dev-dependencies] +sha2 = { version = "0.10", default-features = false } +bincode = "1" +criterion = { version = "0.4.0", features = ["html_reports"] } +hex = "0.4.2" +rand = "0.8" +rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } + +[build-dependencies] +platforms = "3.0.2" +rustc_version = "0.4.0" + +[[bench]] +name = "dalek_benchmarks" +harness = false +required-features = ["alloc", "rand_core"] + +[dependencies] +cfg-if = "1" +rand_core = { version = "0.6.4", default-features = false, optional = true } +digest = { version = "0.10", default-features = false, optional = true } +subtle = { version = "2.3.0", default-features = false } +serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } +zeroize = { version = "1", default-features = false, optional = true } + +[target.'cfg(target_arch = "x86_64")'.dependencies] +cpufeatures = "0.2.6" + +[target.'cfg(curve25519_dalek_backend = "fiat")'.dependencies] +fiat-crypto = "0.1.19" + +[features] +default = ["alloc", "precomputed-tables", "zeroize"] +alloc = ["zeroize?/alloc"] +precomputed-tables = [] +legacy_compatibility = [] + +[target.'cfg(all(not(curve25519_dalek_backend = "fiat"), not(curve25519_dalek_backend = "serial"), target_arch = "x86_64"))'.dependencies] +curve25519-dalek-derive = { version = "0.1", path = "../curve25519-dalek-derive" } diff --git a/LICENSE b/curve25519-dalek/LICENSE similarity index 100% rename from LICENSE rename to curve25519-dalek/LICENSE diff --git a/Makefile b/curve25519-dalek/Makefile similarity index 100% rename from Makefile rename to curve25519-dalek/Makefile diff --git a/curve25519-dalek/README.md b/curve25519-dalek/README.md new file mode 100644 index 000000000..d26eaa367 --- /dev/null +++ b/curve25519-dalek/README.md @@ -0,0 +1,324 @@ + +# curve25519-dalek [![](https://buildstats.info/crate/curve25519-dalek)](https://crates.io/crates/curve25519-dalek) [![](https://img.shields.io/docsrs/curve25519-dalek)](https://docs.rs/curve25519-dalek) [![Rust](https://github.com/dalek-cryptography/curve25519-dalek/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/dalek-cryptography/curve25519-dalek/actions/workflows/rust.yml) + +

+dalek-cryptography logo: a dalek with edwards curves as sparkles coming out of its radar-schnozzley blaster thingies +

+ +**A pure-Rust implementation of group operations on Ristretto and Curve25519.** + +`curve25519-dalek` is a library providing group operations on the Edwards and +Montgomery forms of Curve25519, and on the prime-order Ristretto group. + +`curve25519-dalek` is not intended to provide implementations of any particular +crypto protocol. Rather, implementations of those protocols (such as +[`x25519-dalek`][x25519-dalek] and [`ed25519-dalek`][ed25519-dalek]) should use +`curve25519-dalek` as a library. + +`curve25519-dalek` is intended to provide a clean and safe _mid-level_ API for use +implementing a wide range of ECC-based crypto protocols, such as key agreement, +signatures, anonymous credentials, rangeproofs, and zero-knowledge proof +systems. + +In particular, `curve25519-dalek` implements Ristretto, which constructs a +prime-order group from a non-prime-order Edwards curve. This provides the +speed and safety benefits of Edwards curve arithmetic, without the pitfalls of +cofactor-related abstraction mismatches. + +# Use + +## Stable + +To import `curve25519-dalek`, add the following to the dependencies section of +your project's `Cargo.toml`: +```toml +curve25519-dalek = "3" +``` + +## Beta + +To use the latest prerelease (see changes [below](#breaking-changes-in-400)), +use the following line in your project's `Cargo.toml`: +```toml +curve25519-dalek = "4.0.0-rc.3" +``` + +## Feature Flags + +| Feature | Default? | Description | +| :--- | :---: | :--- | +| `alloc` | ✓ | Enables Edwards and Ristretto multiscalar multiplication, batch scalar inversion, and batch Ristretto double-and-compress. Also enables `zeroize`. | +| `zeroize` | ✓ | Enables [`Zeroize`][zeroize-trait] for all scalar and curve point types. | +| `precomputed-tables` | ✓ | Includes precomputed basepoint multiplication tables. This speeds up `EdwardsPoint::mul_base` and `RistrettoPoint::mul_base` by ~4x, at the cost of ~30KB added to the code size. | +| `rand_core` | | Enables `Scalar::random` and `RistrettoPoint::random`. This is an optional dependency whose version is not subject to SemVer. See [below](#public-api-semver-exemptions) for more details. | +| `digest` | | Enables `RistrettoPoint::{from_hash, hash_from_bytes}` and `Scalar::{from_hash, hash_from_bytes}`. This is an optional dependency whose version is not subject to SemVer. See [below](#public-api-semver-exemptions) for more details. | +| `serde` | | Enables `serde` serialization/deserialization for all the point and scalar types. | +| `legacy_compatibility`| | Enables `Scalar::from_bits`, which allows the user to build unreduced scalars whose arithmetic is broken. Do not use this unless you know what you're doing. | + +To disable the default features when using `curve25519-dalek` as a dependency, +add `default-features = false` to the dependency in your `Cargo.toml`. To +disable it when running `cargo`, add the `--no-default-features` CLI flag. + +## Major Version API Changes + +Breaking changes for each major version release can be found in +[`CHANGELOG.md`](CHANGELOG.md), under the "Breaking changes" subheader. The +latest breaking changes in high level are below: + +### Breaking changes in 4.0.0 + +* Update the MSRV from 1.41 to 1.60 +* Provide SemVer policy +* Make `digest` and `rand_core` optional features +* Remove `std` and `nightly` features +* Replace backend selection - See [CHANGELOG.md](CHANGELOG.md) and [backends](#backends) +* Replace methods `Scalar::{zero, one}` with constants `Scalar::{ZERO, ONE}` +* `Scalar::from_canonical_bytes` now returns `CtOption` +* `Scalar::is_canonical` now returns `Choice` +* Remove `Scalar::from_bytes_clamped` and `Scalar::reduce` +* Deprecate and feature-gate `Scalar::from_bits` behind `legacy_compatibility` +* Deprecate `EdwardsPoint::hash_from_bytes` and rename it + `EdwardsPoint::nonspec_map_to_curve` +* Require including a new trait, `use curve25519_dalek::traits::BasepointTable` + whenever using `EdwardsBasepointTable` or `RistrettoBasepointTable` + +This release also does a lot of dependency updates and relaxations to unblock upstream build issues. + +# Backends + +Curve arithmetic is implemented and used by one of the following backends: + +| Backend | Selection | Implementation | Bits / Word sizes | +| :--- | :--- | :--- | :--- | +| `serial` | Automatic | An optimized, non-parllel implementation | `32` and `64` | +| `fiat` | Manual | Formally verified field arithmetic from [fiat-crypto] | `32` and `64` | +| `simd` | Automatic | Intel AVX2 / AVX512 IFMA accelerated backend | `64` only | + +At runtime, `curve25519-dalek` selects an arithmetic backend from the set of backends it was compiled to support. For Intel x86-64 targets, unless otherwise specified, it will build itself with `simd` support, and default to `serial` at runtime if the appropriate CPU features aren't detected. See [SIMD backend] for more details. + +In the future, `simd` backend may be extended to cover more instruction sets. This change will be non-breaking as this is considered as implementation detail. + +## Manual Backend Override + +You can force the crate to compile with specific backend support, e.g., `serial` for x86-64 targets to save code size, or `fiat` to force the runtime to use verified code. To do this, set the environment variable: +```sh +RUSTFLAGS='--cfg curve25519_dalek_backend="BACKEND"' +``` +Equivalently, you can write to +`~/.cargo/config`: +```toml +[build] +rustflags = ['--cfg=curve25519_dalek_backend="BACKEND"'] +``` +More info [here](https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags). + +Note for contributors: The target backends are not entirely independent of each +other. The [SIMD backend] directly depends on parts of the serial backend to +function. + +## Bits / Word size + +`curve25519-dalek` will automatically choose the word size for the `fiat` and +`serial` backends, based on the build target. +For example, building for a 64-bit machine, the default 64 bit word size is +automatically chosen when either the `serial` or `fiat` backend is selected. + +In some targets it might be required to override the word size for better +performance. +Backend word size can be overridden for `serial` and `fiat` by setting the +environment variable: +```sh +RUSTFLAGS='--cfg curve25519_dalek_bits="SIZE"' +``` +`SIZE` is `32` or `64`. As in the above section, this can also be placed +in `~/.cargo/config`. + +Note: The [SIMD backend] requires a word size of 64 bits. Attempting to set bits=32 and backend=`simd` will yield a compile error. + +### Cross-compilation + +Because backend selection is done by target, cross-compiling will select the correct word size automatically. For example, if a x86-64 Linux machine runs the following commands, `curve25519-dalek` will be compiled with the 32-bit `serial` backend. +```console +$ sudo apt install gcc-multilib # (or whatever package manager you use) +$ rustup target add i686-unknown-linux-gnu +$ cargo build --target i686-unknown-linux-gnu +``` + +## SIMD backend + +The specific SIMD backend (AVX512 / AVX2 / `serial` default) is selected automatically at runtime, depending on the currently available CPU features, and whether Rust nightly is being used for compilation. The precise conditions are specified below. + +For a given CPU feature, you can also specify an appropriate `-C target_feature` to build a binary which assumes the required SIMD instructions are always available. Don't do this if you don't have a good reason. + +| Backend | `RUSTFLAGS` | Requires nightly? | +| :--- | :--- | :--- | +| avx2 | `-C target_feature=+avx2` | no | +| avx512 | `-C target_feature=+avx512ifma,+avx512vl` | yes | + +If compiled on a non-nightly compiler, `curve25519-dalek` will not include AVX512 code, and therefore will never select it at runtime. + +# Documentation + +The semver-stable, public-facing `curve25519-dalek` API is documented [here][docs]. + +## Building Docs Locally + +The `curve25519-dalek` documentation requires a custom HTML header to include +KaTeX for math support. Unfortunately `cargo doc` does not currently support +this, but docs can be built using +```sh +make doc +``` +for regular docs, and +```sh +make doc-internal +``` +for docs that include private items. + +# Maintenance Policies + +All on-by-default features of this library are covered by +[semantic versioning][semver] (SemVer). SemVer exemptions are outlined below +for MSRV and public API. + +## Minimum Supported Rust Version + +| Releases | MSRV | +| :--- |:-------| +| 4.x | 1.60.0 | +| 3.x | 1.41.0 | + +From 4.x and on, MSRV changes will be accompanied by a minor version bump. + +## Public API SemVer Exemptions + +Breaking changes to SemVer exempted components affecting the public API will be accompanied by +_some_ version bump. Below are the specific policies: + +| Releases | Public API Component(s) | Policy | +| :--- | :--- | :--- | +| 4.x | Dependencies `digest` and `rand_core` | Minor SemVer bump | + +# Safety + +The `curve25519-dalek` types are designed to make illegal states +unrepresentable. For example, any instance of an `EdwardsPoint` is +guaranteed to hold a point on the Edwards curve, and any instance of a +`RistrettoPoint` is guaranteed to hold a valid point in the Ristretto +group. + +All operations are implemented using constant-time logic (no +secret-dependent branches, no secret-dependent memory accesses), +unless specifically marked as being variable-time code. +We believe that our constant-time logic is lowered to constant-time +assembly, at least on `x86_64` targets. + +As an additional guard against possible future compiler optimizations, +the `subtle` crate places an optimization barrier before every +conditional move or assignment. More details can be found in [the +documentation for the `subtle` crate][subtle_doc]. + +Some functionality (e.g., multiscalar multiplication or batch +inversion) requires heap allocation for temporary buffers. All +heap-allocated buffers of potentially secret data are explicitly +zeroed before release. + +However, we do not attempt to zero stack data, for two reasons. +First, it's not possible to do so correctly: we don't have control +over stack allocations, so there's no way to know how much data to +wipe. Second, because `curve25519-dalek` provides a mid-level API, +the correct place to start zeroing stack data is likely not at the +entrypoints of `curve25519-dalek` functions, but at the entrypoints of +functions in other crates. + +The implementation is memory-safe, and contains no significant +`unsafe` code. The SIMD backend uses `unsafe` internally to call SIMD +intrinsics. These are marked `unsafe` only because invoking them on an +inappropriate CPU would cause `SIGILL`, but the entire backend is only +invoked when the appropriate CPU features are detected at runtime, or +when the whole program is compiled with the appropriate `target_feature`s. + +# Performance + +Benchmarks are run using [`criterion.rs`][criterion]: + +```sh +cargo bench --features "rand_core" +export RUSTFLAGS='-C target_cpu=native' +cargo +nightly bench --features "rand_core" +``` + +Performance is a secondary goal behind correctness, safety, and +clarity, but we aim to be competitive with other implementations. + +# FFI + +Unfortunately, we have no plans to add FFI to `curve25519-dalek` directly. The +reason is that we use Rust features to provide an API that maintains safety +invariants, which are not possible to maintain across an FFI boundary. For +instance, as described in the _Safety_ section above, invalid points are +impossible to construct, and this would not be the case if we exposed point +operations over FFI. + +However, `curve25519-dalek` is designed as a *mid-level* API, aimed at +implementing other, higher-level primitives. Instead of providing FFI at the +mid-level, our suggestion is to implement the higher-level primitive (a +signature, PAKE, ZKP, etc) in Rust, using `curve25519-dalek` as a dependency, +and have that crate provide a minimal, byte-buffer-oriented FFI specific to +that primitive. + +# Contributing + +Please see [CONTRIBUTING.md][contributing]. + +# About + +**SPOILER ALERT:** *The Twelfth Doctor's first encounter with the Daleks is in +his second full episode, "Into the Dalek". A beleaguered ship of the "Combined +Galactic Resistance" has discovered a broken Dalek that has turned "good", +desiring to kill all other Daleks. The Doctor, Clara and a team of soldiers +are miniaturized and enter the Dalek, which the Doctor names Rusty. They +repair the damage, but accidentally restore it to its original nature, causing +it to go on the rampage and alert the Dalek fleet to the whereabouts of the +rebel ship. However, the Doctor manages to return Rusty to its previous state +by linking his mind with the Dalek's: Rusty shares the Doctor's view of the +universe's beauty, but also his deep hatred of the Daleks. Rusty destroys the +other Daleks and departs the ship, determined to track down and bring an end +to the Dalek race.* + +`curve25519-dalek` is authored by Isis Agora Lovecruft and Henry de Valence. + +Portions of this library were originally a port of [Adam Langley's +Golang ed25519 library](https://github.com/agl/ed25519), which was in +turn a port of the reference `ref10` implementation. Most of this code, +including the 32-bit field arithmetic, has since been rewritten. + +The fast `u32` and `u64` scalar arithmetic was implemented by Andrew Moon, and +the addition chain for scalar inversion was provided by Brian Smith. The +optimised batch inversion was contributed by Sean Bowe and Daira Hopwood. + +The `no_std` and `zeroize` support was contributed by Tony Arcieri. + +The formally verified `fiat_backend` integrates Rust code generated by the +[Fiat Crypto project](https://github.com/mit-plv/fiat-crypto) and was +contributed by François Garillot. + +Thanks also to Ashley Hauck, Lucas Salibian, Manish Goregaokar, Jack Grigg, +Pratyush Mishra, Michael Rosenberg, @pinkforest, and countless others for their +contributions. + +[ed25519-dalek]: https://github.com/dalek-cryptography/ed25519-dalek +[x25519-dalek]: https://github.com/dalek-cryptography/x25519-dalek +[docs]: https://docs.rs/curve25519-dalek/ +[contributing]: https://github.com/dalek-cryptography/curve25519-dalek/blob/master/CONTRIBUTING.md +[criterion]: https://github.com/japaric/criterion.rs +[parallel_doc]: https://docs.rs/curve25519-dalek/latest/curve25519_dalek/backend/vector/index.html +[subtle_doc]: https://docs.rs/subtle +[fiat-crypto]: https://github.com/mit-plv/fiat-crypto +[semver]: https://semver.org/spec/v2.0.0.html +[rngcorestd]: https://github.com/rust-random/rand/tree/7aa25d577e2df84a5156f824077bb7f6bdf28d97/rand_core#crate-features +[zeroize-trait]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html +[SIMD backend]: #simd-backend diff --git a/benches/dalek_benchmarks.rs b/curve25519-dalek/benches/dalek_benchmarks.rs similarity index 100% rename from benches/dalek_benchmarks.rs rename to curve25519-dalek/benches/dalek_benchmarks.rs diff --git a/build.rs b/curve25519-dalek/build.rs similarity index 100% rename from build.rs rename to curve25519-dalek/build.rs diff --git a/docs/assets/rustdoc-include-katex-header.html b/curve25519-dalek/docs/assets/rustdoc-include-katex-header.html similarity index 100% rename from docs/assets/rustdoc-include-katex-header.html rename to curve25519-dalek/docs/assets/rustdoc-include-katex-header.html diff --git a/docs/avx2-notes.md b/curve25519-dalek/docs/avx2-notes.md similarity index 100% rename from docs/avx2-notes.md rename to curve25519-dalek/docs/avx2-notes.md diff --git a/docs/ifma-notes.md b/curve25519-dalek/docs/ifma-notes.md similarity index 100% rename from docs/ifma-notes.md rename to curve25519-dalek/docs/ifma-notes.md diff --git a/docs/parallel-formulas.md b/curve25519-dalek/docs/parallel-formulas.md similarity index 100% rename from docs/parallel-formulas.md rename to curve25519-dalek/docs/parallel-formulas.md diff --git a/src/backend/mod.rs b/curve25519-dalek/src/backend/mod.rs similarity index 100% rename from src/backend/mod.rs rename to curve25519-dalek/src/backend/mod.rs diff --git a/src/backend/serial/curve_models/mod.rs b/curve25519-dalek/src/backend/serial/curve_models/mod.rs similarity index 100% rename from src/backend/serial/curve_models/mod.rs rename to curve25519-dalek/src/backend/serial/curve_models/mod.rs diff --git a/src/backend/serial/fiat_u32/field.rs b/curve25519-dalek/src/backend/serial/fiat_u32/field.rs similarity index 100% rename from src/backend/serial/fiat_u32/field.rs rename to curve25519-dalek/src/backend/serial/fiat_u32/field.rs diff --git a/src/backend/serial/fiat_u32/mod.rs b/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs similarity index 100% rename from src/backend/serial/fiat_u32/mod.rs rename to curve25519-dalek/src/backend/serial/fiat_u32/mod.rs diff --git a/src/backend/serial/fiat_u64/field.rs b/curve25519-dalek/src/backend/serial/fiat_u64/field.rs similarity index 100% rename from src/backend/serial/fiat_u64/field.rs rename to curve25519-dalek/src/backend/serial/fiat_u64/field.rs diff --git a/src/backend/serial/fiat_u64/mod.rs b/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs similarity index 100% rename from src/backend/serial/fiat_u64/mod.rs rename to curve25519-dalek/src/backend/serial/fiat_u64/mod.rs diff --git a/src/backend/serial/mod.rs b/curve25519-dalek/src/backend/serial/mod.rs similarity index 100% rename from src/backend/serial/mod.rs rename to curve25519-dalek/src/backend/serial/mod.rs diff --git a/src/backend/serial/scalar_mul/mod.rs b/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs similarity index 100% rename from src/backend/serial/scalar_mul/mod.rs rename to curve25519-dalek/src/backend/serial/scalar_mul/mod.rs diff --git a/src/backend/serial/scalar_mul/pippenger.rs b/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs similarity index 100% rename from src/backend/serial/scalar_mul/pippenger.rs rename to curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs diff --git a/src/backend/serial/scalar_mul/precomputed_straus.rs b/curve25519-dalek/src/backend/serial/scalar_mul/precomputed_straus.rs similarity index 100% rename from src/backend/serial/scalar_mul/precomputed_straus.rs rename to curve25519-dalek/src/backend/serial/scalar_mul/precomputed_straus.rs diff --git a/src/backend/serial/scalar_mul/straus.rs b/curve25519-dalek/src/backend/serial/scalar_mul/straus.rs similarity index 100% rename from src/backend/serial/scalar_mul/straus.rs rename to curve25519-dalek/src/backend/serial/scalar_mul/straus.rs diff --git a/src/backend/serial/scalar_mul/variable_base.rs b/curve25519-dalek/src/backend/serial/scalar_mul/variable_base.rs similarity index 100% rename from src/backend/serial/scalar_mul/variable_base.rs rename to curve25519-dalek/src/backend/serial/scalar_mul/variable_base.rs diff --git a/src/backend/serial/scalar_mul/vartime_double_base.rs b/curve25519-dalek/src/backend/serial/scalar_mul/vartime_double_base.rs similarity index 100% rename from src/backend/serial/scalar_mul/vartime_double_base.rs rename to curve25519-dalek/src/backend/serial/scalar_mul/vartime_double_base.rs diff --git a/src/backend/serial/u32/constants.rs b/curve25519-dalek/src/backend/serial/u32/constants.rs similarity index 100% rename from src/backend/serial/u32/constants.rs rename to curve25519-dalek/src/backend/serial/u32/constants.rs diff --git a/src/backend/serial/u32/field.rs b/curve25519-dalek/src/backend/serial/u32/field.rs similarity index 100% rename from src/backend/serial/u32/field.rs rename to curve25519-dalek/src/backend/serial/u32/field.rs diff --git a/src/backend/serial/u32/mod.rs b/curve25519-dalek/src/backend/serial/u32/mod.rs similarity index 100% rename from src/backend/serial/u32/mod.rs rename to curve25519-dalek/src/backend/serial/u32/mod.rs diff --git a/src/backend/serial/u32/scalar.rs b/curve25519-dalek/src/backend/serial/u32/scalar.rs similarity index 100% rename from src/backend/serial/u32/scalar.rs rename to curve25519-dalek/src/backend/serial/u32/scalar.rs diff --git a/src/backend/serial/u64/constants.rs b/curve25519-dalek/src/backend/serial/u64/constants.rs similarity index 100% rename from src/backend/serial/u64/constants.rs rename to curve25519-dalek/src/backend/serial/u64/constants.rs diff --git a/src/backend/serial/u64/field.rs b/curve25519-dalek/src/backend/serial/u64/field.rs similarity index 100% rename from src/backend/serial/u64/field.rs rename to curve25519-dalek/src/backend/serial/u64/field.rs diff --git a/src/backend/serial/u64/mod.rs b/curve25519-dalek/src/backend/serial/u64/mod.rs similarity index 100% rename from src/backend/serial/u64/mod.rs rename to curve25519-dalek/src/backend/serial/u64/mod.rs diff --git a/src/backend/serial/u64/scalar.rs b/curve25519-dalek/src/backend/serial/u64/scalar.rs similarity index 100% rename from src/backend/serial/u64/scalar.rs rename to curve25519-dalek/src/backend/serial/u64/scalar.rs diff --git a/src/backend/vector/avx2/constants.rs b/curve25519-dalek/src/backend/vector/avx2/constants.rs similarity index 100% rename from src/backend/vector/avx2/constants.rs rename to curve25519-dalek/src/backend/vector/avx2/constants.rs diff --git a/src/backend/vector/avx2/edwards.rs b/curve25519-dalek/src/backend/vector/avx2/edwards.rs similarity index 100% rename from src/backend/vector/avx2/edwards.rs rename to curve25519-dalek/src/backend/vector/avx2/edwards.rs diff --git a/src/backend/vector/avx2/field.rs b/curve25519-dalek/src/backend/vector/avx2/field.rs similarity index 100% rename from src/backend/vector/avx2/field.rs rename to curve25519-dalek/src/backend/vector/avx2/field.rs diff --git a/src/backend/vector/avx2/mod.rs b/curve25519-dalek/src/backend/vector/avx2/mod.rs similarity index 100% rename from src/backend/vector/avx2/mod.rs rename to curve25519-dalek/src/backend/vector/avx2/mod.rs diff --git a/src/backend/vector/ifma/constants.rs b/curve25519-dalek/src/backend/vector/ifma/constants.rs similarity index 100% rename from src/backend/vector/ifma/constants.rs rename to curve25519-dalek/src/backend/vector/ifma/constants.rs diff --git a/src/backend/vector/ifma/edwards.rs b/curve25519-dalek/src/backend/vector/ifma/edwards.rs similarity index 100% rename from src/backend/vector/ifma/edwards.rs rename to curve25519-dalek/src/backend/vector/ifma/edwards.rs diff --git a/src/backend/vector/ifma/field.rs b/curve25519-dalek/src/backend/vector/ifma/field.rs similarity index 100% rename from src/backend/vector/ifma/field.rs rename to curve25519-dalek/src/backend/vector/ifma/field.rs diff --git a/src/backend/vector/ifma/mod.rs b/curve25519-dalek/src/backend/vector/ifma/mod.rs similarity index 100% rename from src/backend/vector/ifma/mod.rs rename to curve25519-dalek/src/backend/vector/ifma/mod.rs diff --git a/src/backend/vector/mod.rs b/curve25519-dalek/src/backend/vector/mod.rs similarity index 100% rename from src/backend/vector/mod.rs rename to curve25519-dalek/src/backend/vector/mod.rs diff --git a/src/backend/vector/packed_simd.rs b/curve25519-dalek/src/backend/vector/packed_simd.rs similarity index 100% rename from src/backend/vector/packed_simd.rs rename to curve25519-dalek/src/backend/vector/packed_simd.rs diff --git a/src/backend/vector/scalar_mul/mod.rs b/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs similarity index 100% rename from src/backend/vector/scalar_mul/mod.rs rename to curve25519-dalek/src/backend/vector/scalar_mul/mod.rs diff --git a/src/backend/vector/scalar_mul/pippenger.rs b/curve25519-dalek/src/backend/vector/scalar_mul/pippenger.rs similarity index 100% rename from src/backend/vector/scalar_mul/pippenger.rs rename to curve25519-dalek/src/backend/vector/scalar_mul/pippenger.rs diff --git a/src/backend/vector/scalar_mul/precomputed_straus.rs b/curve25519-dalek/src/backend/vector/scalar_mul/precomputed_straus.rs similarity index 100% rename from src/backend/vector/scalar_mul/precomputed_straus.rs rename to curve25519-dalek/src/backend/vector/scalar_mul/precomputed_straus.rs diff --git a/src/backend/vector/scalar_mul/straus.rs b/curve25519-dalek/src/backend/vector/scalar_mul/straus.rs similarity index 100% rename from src/backend/vector/scalar_mul/straus.rs rename to curve25519-dalek/src/backend/vector/scalar_mul/straus.rs diff --git a/src/backend/vector/scalar_mul/variable_base.rs b/curve25519-dalek/src/backend/vector/scalar_mul/variable_base.rs similarity index 100% rename from src/backend/vector/scalar_mul/variable_base.rs rename to curve25519-dalek/src/backend/vector/scalar_mul/variable_base.rs diff --git a/src/backend/vector/scalar_mul/vartime_double_base.rs b/curve25519-dalek/src/backend/vector/scalar_mul/vartime_double_base.rs similarity index 100% rename from src/backend/vector/scalar_mul/vartime_double_base.rs rename to curve25519-dalek/src/backend/vector/scalar_mul/vartime_double_base.rs diff --git a/src/constants.rs b/curve25519-dalek/src/constants.rs similarity index 100% rename from src/constants.rs rename to curve25519-dalek/src/constants.rs diff --git a/src/diagnostics.rs b/curve25519-dalek/src/diagnostics.rs similarity index 100% rename from src/diagnostics.rs rename to curve25519-dalek/src/diagnostics.rs diff --git a/src/edwards.rs b/curve25519-dalek/src/edwards.rs similarity index 100% rename from src/edwards.rs rename to curve25519-dalek/src/edwards.rs diff --git a/src/field.rs b/curve25519-dalek/src/field.rs similarity index 100% rename from src/field.rs rename to curve25519-dalek/src/field.rs diff --git a/src/lib.rs b/curve25519-dalek/src/lib.rs similarity index 100% rename from src/lib.rs rename to curve25519-dalek/src/lib.rs diff --git a/src/macros.rs b/curve25519-dalek/src/macros.rs similarity index 100% rename from src/macros.rs rename to curve25519-dalek/src/macros.rs diff --git a/src/montgomery.rs b/curve25519-dalek/src/montgomery.rs similarity index 100% rename from src/montgomery.rs rename to curve25519-dalek/src/montgomery.rs diff --git a/src/ristretto.rs b/curve25519-dalek/src/ristretto.rs similarity index 100% rename from src/ristretto.rs rename to curve25519-dalek/src/ristretto.rs diff --git a/src/scalar.rs b/curve25519-dalek/src/scalar.rs similarity index 100% rename from src/scalar.rs rename to curve25519-dalek/src/scalar.rs diff --git a/src/traits.rs b/curve25519-dalek/src/traits.rs similarity index 100% rename from src/traits.rs rename to curve25519-dalek/src/traits.rs diff --git a/src/window.rs b/curve25519-dalek/src/window.rs similarity index 100% rename from src/window.rs rename to curve25519-dalek/src/window.rs diff --git a/tests/build_tests.sh b/curve25519-dalek/tests/build_tests.sh similarity index 100% rename from tests/build_tests.sh rename to curve25519-dalek/tests/build_tests.sh diff --git a/vendor/ristretto.sage b/curve25519-dalek/vendor/ristretto.sage similarity index 100% rename from vendor/ristretto.sage rename to curve25519-dalek/vendor/ristretto.sage diff --git a/ed25519-dalek/.gitignore b/ed25519-dalek/.gitignore new file mode 100644 index 000000000..778540f75 --- /dev/null +++ b/ed25519-dalek/.gitignore @@ -0,0 +1,12 @@ +target + +.cargo + +*~ +\#* +.\#* +*.swp +*.orig +*.bak + +*.s diff --git a/ed25519-dalek/.travis.yml b/ed25519-dalek/.travis.yml new file mode 100644 index 000000000..72f94de7d --- /dev/null +++ b/ed25519-dalek/.travis.yml @@ -0,0 +1,33 @@ +language: rust + +rust: + - stable + - beta + - nightly + +env: + - TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='' + +matrix: + include: + # We use the 64-bit optimised curve backend by default, so also test with + # the 32-bit backend (this also exercises testing with `no_std`): + - rust: nightly + env: TEST_COMMAND=build EXTRA_FLAGS='--no-default-features' FEATURES='u32_backend alloc' + # Also test the batch feature: + - rust: nightly + env: TEST_COMMAND=build EXTRA_FLAGS='--no-default-features' FEATURES='u64_backend alloc batch' + # Test any nightly gated features on nightly: + - rust: nightly + env: TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='nightly' + # Test serde support on stable, assuming that if it works there it'll work everywhere: + - rust: stable + env: TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='serde' + +script: + - cargo $TEST_COMMAND --features="$FEATURES" $EXTRA_FLAGS + +notifications: + slack: + rooms: + - dalek-cryptography:Xxv9WotKYWdSoKlgKNqXiHoD#dalek-bots diff --git a/ed25519-dalek/CHANGELOG.md b/ed25519-dalek/CHANGELOG.md new file mode 100644 index 000000000..c3fc94a5c --- /dev/null +++ b/ed25519-dalek/CHANGELOG.md @@ -0,0 +1,41 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +Entries are listed in reverse chronological order per undeprecated major series. + +# 2.x series + +## 2.0.0 + +### Breaking changes + +* Bump MSRV from 1.41 to 1.60.0 +* Bump Rust edition +* Bump `signature` dependency to 2.0 +* Make `digest` an optional dependency +* Make `zeroize` an optional dependency +* Make `rand_core` an optional dependency +* [curve25519 backends] are now automatically selected +* [curve25519 backends] are now overridable via cfg instead of using additive features +* Make all batch verification deterministic remove `batch_deterministic` (PR [#256](https://github.com/dalek-cryptography/ed25519-dalek/pull/256)) +* Rename `Keypair` → `SigningKey` and `PublicKey` → `VerifyingKey` +* Remove default-public `ExpandedSecretKey` API (PR [#205](https://github.com/dalek-cryptography/ed25519-dalek/pull/205)) +* Make `hazmat` feature to expose `ExpandedSecretKey`, `raw_sign()`, `raw_sign_prehashed()`, `raw_verify()`, and `raw_verify_prehashed()` + +[curve25519 backends]: https://github.com/dalek-cryptography/curve25519-dalek/#backends + +### Other changes + +* Add `Context` type for prehashed signing +* Add `VerifyingKey::{verify_prehash_strict, is_weak}` +* Add `pkcs` feature to support PKCS #8 (de)serialization of `SigningKey` and `VerifyingKey` +* Add `fast` feature to include basepoint tables +* Add tests for validation criteria +* Impl `DigestSigner`/`DigestVerifier` for `SigningKey`/`VerifyingKey`, respectively +* Impl `Hash` for `VerifyingKey` +* Impl `Clone`, `Drop`, and `ZeroizeOnDrop` for `SigningKey` +* Remove `rand` dependency +* Improve key deserialization diagnostics diff --git a/ed25519-dalek/Cargo.lock b/ed25519-dalek/Cargo.lock new file mode 100644 index 000000000..17f94f29f --- /dev/null +++ b/ed25519-dalek/Cargo.lock @@ -0,0 +1,1012 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64ct" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "bitflags", + "clap_lex", + "indexmap", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "const-oid" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" + +[[package]] +name = "cpufeatures" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +dependencies = [ + "libc", +] + +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436ace70fc06e06f7f689d2624dc4e2f0ea666efb5aa704215f7249ae6e047a7" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rand_core", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + +[[package]] +name = "der" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc302fd9b18d66834a6f092d10ea85489c0ca8ad6b7304092135fab171d853cd" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "ed25519" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be522bee13fa6d8059f4903a4084aa3bd50725e18150202f0238deb615cd6371" +dependencies = [ + "pkcs8", + "serde", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.0.0-rc.3" +dependencies = [ + "bincode", + "blake2", + "criterion", + "curve25519-dalek", + "ed25519", + "hex", + "hex-literal", + "merlin", + "rand", + "rand_core", + "serde", + "serde_json", + "sha2", + "sha3", + "signature", + "toml", + "zeroize", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "fiat-crypto" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ace6ec7cc19c8ed33a32eaa9ea692d7faea05006b5356b9e2b668ec4bc3955" + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pkcs8" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34154ec92c136238e7c210443538e64350962b8e2788cadcf5f781a6da70c36" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "platforms" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" + +[[package]] +name = "plotters" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" + +[[package]] +name = "plotters-svg" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "serde_json" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", + "sha2-asm", +] + +[[package]] +name = "sha2-asm" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf27176fb5d15398e3a479c652c20459d9dac830dedd1fa55b42a77dbcdbfcea" +dependencies = [ + "cc", +] + +[[package]] +name = "sha3" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54c2bb1a323307527314a36bfb73f24febb08ce2b8a554bf4ffd6f51ad15198c" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "signature" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" +dependencies = [ + "digest", +] + +[[package]] +name = "spki" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0445c905640145c7ea8c1993555957f65e7c46d0535b91ba501bc9bfc85522f" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", + "unicode-xid", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.107", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", + "synstructure", +] diff --git a/ed25519-dalek/Cargo.toml b/ed25519-dalek/Cargo.toml new file mode 100644 index 000000000..d6fc526ae --- /dev/null +++ b/ed25519-dalek/Cargo.toml @@ -0,0 +1,75 @@ +[package] +name = "ed25519-dalek" +version = "2.0.0-rc.3" +edition = "2021" +authors = [ + "isis lovecruft ", + "Tony Arcieri ", + "Michael Rosenberg " +] +readme = "README.md" +license = "BSD-3-Clause" +repository = "https://github.com/dalek-cryptography/ed25519-dalek" +documentation = "https://docs.rs/ed25519-dalek" +keywords = ["cryptography", "ed25519", "curve25519", "signature", "ECC"] +categories = ["cryptography", "no-std"] +description = "Fast and efficient ed25519 EdDSA key generations, signing, and verification in pure Rust." +exclude = [ ".gitignore", "TESTVECTORS", "VALIDATIONVECTORS", "res/*" ] +rust-version = "1.60" + +[package.metadata.docs.rs] +rustdoc-args = [ + "--html-in-header", "docs/assets/rustdoc-include-katex-header.html", + "--cfg", "docsrs", +] +features = ["batch", "digest", "hazmat", "pem", "serde"] + +[dependencies] +curve25519-dalek = { version = "=4.0.0-rc.3", path = "../curve25519-dalek", default-features = false, features = ["digest"] } +ed25519 = { version = ">=2.2, <2.3", default-features = false } +signature = { version = ">=2.0, <2.1", optional = true, default-features = false } +sha2 = { version = "0.10", default-features = false } + +# optional features +merlin = { version = "3", default-features = false, optional = true } +rand_core = { version = "0.6.4", default-features = false, optional = true } +serde = { version = "1.0", default-features = false, optional = true } +zeroize = { version = "1.5", default-features = false, optional = true } + +[dev-dependencies] +curve25519-dalek = { version = "=4.0.0-rc.3", path = "../curve25519-dalek", default-features = false, features = ["digest", "rand_core"] } +blake2 = "0.10" +sha3 = "0.10" +hex = "0.4" +bincode = "1.0" +serde_json = "1.0" +criterion = { version = "0.4", features = ["html_reports"] } +hex-literal = "0.3" +rand = "0.8" +rand_core = { version = "0.6.4", default-features = false } +serde = { version = "1.0", features = ["derive"] } +toml = { version = "0.5" } + +[[bench]] +name = "ed25519_benchmarks" +harness = false +required-features = ["rand_core"] + +[features] +default = ["fast", "std", "zeroize"] +alloc = ["curve25519-dalek/alloc", "ed25519/alloc", "serde?/alloc", "zeroize/alloc"] +std = ["alloc", "ed25519/std", "serde?/std", "sha2/std"] + +asm = ["sha2/asm"] +batch = ["alloc", "merlin", "rand_core"] +fast = ["curve25519-dalek/precomputed-tables"] +digest = ["signature/digest"] +# Exposes the hazmat module +hazmat = [] +# Turns off stricter checking for scalar malleability in signatures +legacy_compatibility = ["curve25519-dalek/legacy_compatibility"] +pkcs8 = ["ed25519/pkcs8"] +pem = ["alloc", "ed25519/pem", "pkcs8"] +rand_core = ["dep:rand_core"] +serde = ["dep:serde", "ed25519/serde"] +zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"] diff --git a/ed25519-dalek/LICENSE b/ed25519-dalek/LICENSE new file mode 100644 index 000000000..acf8498e2 --- /dev/null +++ b/ed25519-dalek/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2017-2019 isis agora lovecruft. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/ed25519-dalek/README.md b/ed25519-dalek/README.md new file mode 100644 index 000000000..4d1e7b0cb --- /dev/null +++ b/ed25519-dalek/README.md @@ -0,0 +1,188 @@ +# ed25519-dalek [![](https://img.shields.io/crates/v/ed25519-dalek.svg)](https://crates.io/crates/ed25519-dalek) [![](https://docs.rs/ed25519-dalek/badge.svg)](https://docs.rs/ed25519-dalek) [![Rust](https://github.com/dalek-cryptography/ed25519-dalek/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/dalek-cryptography/ed25519-dalek/actions/workflows/rust.yml) + +Fast and efficient Rust implementation of ed25519 key generation, signing, and +verification. + +# Use + +## Stable + +To import `ed25519-dalek`, add the following to the dependencies section of +your project's `Cargo.toml`: +```toml +ed25519-dalek = "1" +``` + +## Beta + +To use the latest prerelease (see changes [below](#breaking-changes-in-200)), +use the following line in your project's `Cargo.toml`: +```toml +ed25519-dalek = "2.0.0-rc.3" +``` + +# Feature Flags + +This crate is `#[no_std]` compatible with `default-features = false`. + +| Feature | Default? | Description | +| :--- | :--- | :--- | +| `alloc` | ✓ | When `pkcs8` is enabled, implements `EncodePrivateKey`/`EncodePublicKey` for `SigningKey`/`VerifyingKey`, respectively. | +| `std` | ✓ | Implements `std::error::Error` for `SignatureError`. Also enables `alloc`. | +| `zeroize` | ✓ | Implements `Zeroize` and `ZeroizeOnDrop` for `SigningKey` | +| `rand_core` | | Enables `SigningKey::generate` | +| `batch` | | Enables `verify_batch` for verifying many signatures quickly. Also enables `rand_core`. | +| `digest` | | Enables `Context`, `SigningKey::{with_context, sign_prehashed}` and `VerifyingKey::{with_context, verify_prehashed, verify_prehashed_strict}` for Ed25519ph prehashed signatures | +| `asm` | | Enables assembly optimizations in the SHA-512 compression functions | +| `pkcs8` | | Enables [PKCS#8](https://en.wikipedia.org/wiki/PKCS_8) serialization/deserialization for `SigningKey` and `VerifyingKey` | +| `pem` | | Enables PEM serialization support for PKCS#8 private keys and SPKI public keys. Also enables `alloc`. | +| `legacy_compatibility` | | **Unsafe:** Disables certain signature checks. See [below](#malleability-and-the-legacy_compatibility-feature) | +| `hazmat` | | **Unsafe:** Exposes the `hazmat` module for raw signing/verifying. Misuse of these functions will expose the private key, as in the [signing oracle attack](https://github.com/MystenLabs/ed25519-unsafe-libs). | + +# Major Changes + +See [CHANGELOG.md](CHANGELOG.md) for a list of changes made in past version of this crate. + +## Breaking Changes in 2.0.0 + +* Bump MSRV from 1.41 to 1.60.0 +* Bump Rust edition +* Bump `signature` dependency to 2.0 +* Make `digest` an optional dependency +* Make `zeroize` an optional dependency +* Make `rand_core` an optional dependency +* Adopt [curve25519-backend selection](https://github.com/dalek-cryptography/curve25519-dalek/#backends) over features +* Make all batch verification deterministic remove `batch_deterministic` ([#256](https://github.com/dalek-cryptography/ed25519-dalek/pull/256)) +* Remove `ExpandedSecretKey` API ((#205)[https://github.com/dalek-cryptography/ed25519-dalek/pull/205]) +* Rename `Keypair` → `SigningKey` and `PublicKey` → `VerifyingKey` +* Make `hazmat` feature to expose, `ExpandedSecretKey`, `raw_sign()`, `raw_sign_prehashed()`, `raw_verify()`, and `raw_verify_prehashed()` + +# Documentation + +Documentation is available [here](https://docs.rs/ed25519-dalek). + +# Compatibility Policies + +All on-by-default features of this library are covered by [semantic versioning](https://semver.org/spec/v2.0.0.html) (SemVer). +SemVer exemptions are outlined below for MSRV and public API. + +## Minimum Supported Rust Version + +| Releases | MSRV | +| :--- | :--- | +| 2.x | 1.60 | +| 1.x | 1.41 | + +From 2.x and on, MSRV changes will be accompanied by a minor version bump. + +## Public API SemVer Exemptions + +Breaking changes to SemVer-exempted components affecting the public API will be accompanied by some version bump. + +Below are the specific policies: + +| Releases | Public API Component(s) | Policy | +| :--- | :--- | :--- | +| 2.x | Dependencies `digest`, `pkcs8` and `rand_core` | Minor SemVer bump | + +# Safety + +`ed25519-dalek` is designed to prevent misuse. Signing is constant-time, all signing keys are zeroed when they go out of scope (unless `zeroize` is disabled), detached public keys [cannot](https://github.com/MystenLabs/ed25519-unsafe-libs/blob/main/README.md) be used for signing, and extra functions like [`VerifyingKey::verify_strict`](#weak-key-forgery-and-verify_strict) are made available to avoid known gotchas. + +Further, this crate has no—and in fact forbids—unsafe code. You can opt in to using some highly optimized unsafe code that resides in `curve25519-dalek`, though. See [below](#microarchitecture-specific-backends) for more information on backend selection. + +# Performance + +Performance is a secondary goal behind correctness, safety, and clarity, but we +aim to be competitive with other implementations. + +## Benchmarks + +Benchmarks are run using [criterion.rs](https://github.com/japaric/criterion.rs): + +```sh +cargo bench --features "batch" +# Uses avx2 or ifma only if compiled for an appropriate target. +export RUSTFLAGS='-C target_cpu=native' +cargo +nightly bench --features "batch" +``` + +On an Intel 10700K running at stock comparing between the `curve25519-dalek` backends. + +| Benchmark | u64 | simd +avx2 | fiat | +| :--- | :---- | :--- | :--- | +| signing | 15.017 µs | 13.906 µs -7.3967% | 15.877 μs +5.7268% | +| signature verification | 40.144 µs | 25.963 µs -35.603% | 42.118 μs +4.9173% | +| strict signature verification | 41.334 µs | 27.874 µs -32.660% | 43.985 μs +6.4136% | +| batch signature verification/4 | 109.44 µs | 81.778 µs -25.079% | 117.80 μs +7.6389% | +| batch signature verification/8 | 182.75 µs | 138.40 µs -23.871% | 195.86 μs +7.1737% | +| batch signature verification/16 | 328.67 µs | 251.39 µs -23.744% | 351.55 μs +6.9614% | +| batch signature verification/32 | 619.49 µs | 477.36 µs -23.053% | 669.41 μs +8.0582% | +| batch signature verification/64 | 1.2136 ms | 936.85 µs -22.543% | 1.3028 ms +7.3500% | +| batch signature verification/96 | 1.8677 ms | 1.2357 ms -33.936% | 2.0552 ms +10.039% | +| batch signature verification/128| 2.3281 ms | 1.5795 ms -31.996% | 2.5596 ms +9.9437% | +| batch signature verification/256| 4.1868 ms | 2.8864 ms -31.061% | 4.6494 μs +11.049% | +| keypair generation | 13.973 µs | 13.108 µs -6.5062% | 15.099 μs +8.0584% | + +## Batch Performance + +If your protocol or application is able to batch signatures for verification, +the [`verify_batch`][func_verify_batch] function has greatly improved performance. + +As you can see, there's an optimal batch size for each machine, so you'll likely +want to test the benchmarks on your target CPU to discover the best size. + +## (Micro)Architecture Specific Backends + +A _backend_ refers to an implementation of elliptic curve and scalar arithmetic. Different backends have different use cases. For example, if you demand formally verified code, you want to use the `fiat` backend (as it was generated from [Fiat Crypto][fiat]). + +Backend selection details and instructions can be found in the [curve25519-dalek docs](https://github.com/dalek-cryptography/curve25519-dalek#backends). + +# Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) + +# Batch Signature Verification + +The standard variants of batch signature verification (i.e. many signatures made with potentially many different public keys over potentially many different messages) is available via the `batch` feature. It uses deterministic randomness, i.e., it hashes the inputs (using [`merlin`](https://merlin.cool/), which handles transcript item separation) and uses the result to generate random coefficients. Batch verification requires allocation, so this won't function in heapless settings. + +# Validation Criteria + +The _validation criteria_ of a signature scheme are the criteria that signatures and public keys must satisfy in order to be accepted. Unfortunately, Ed25519 has some underspecified parts, leading to different validation criteria across implementations. For a very good overview of this, see [Henry's post][validation]. + +In this section, we mention some specific details about our validation criteria, and how to navigate them. + +## Malleability and the `legacy_compatibility` Feature + +A signature scheme is considered to produce _malleable signatures_ if a passive attacker with knowledge of a public key _A_, message _m_, and valid signature _σ'_ can produce a distinct _σ'_ such that _σ'_ is a valid signature of _m_ with respect to _A_. A scheme is only malleable if the attacker can do this _without_ knowledge of the private key corresponding to _A_. + +`ed25519-dalek` is not a malleable signature scheme. + +Some other Ed25519 implementations are malleable, though, such as [libsodium with `ED25519_COMPAT` enabled](https://github.com/jedisct1/libsodium/blob/24211d370a9335373f0715664271dfe203c7c2cd/src/libsodium/crypto_sign/ed25519/ref10/open.c#L30), [ed25519-donna](https://github.com/floodyberry/ed25519-donna/blob/8757bd4cd209cb032853ece0ce413f122eef212c/ed25519.c#L100), [NaCl's ref10 impl](https://github.com/floodyberry/ed25519-donna/blob/8757bd4cd209cb032853ece0ce413f122eef212c/fuzz/ed25519-ref10.c#L4627), and probably a lot more. +If you need to interoperate with such implementations and accept otherwise invalid signatures, you can enable the `legacy_compatibility` flag. **Do not enable `legacy_compatibility`** if you don't have to, because it will make your signatures malleable. + +Note: [CIRCL](https://github.com/cloudflare/circl/blob/fa6e0cca79a443d7be18ed241e779adf9ed2a301/sign/ed25519/ed25519.go#L358) has no scalar range check at all. We do not have a feature flag for interoperating with the larger set of RFC-disallowed signatures that CIRCL accepts. + +## Weak key Forgery and `verify_strict()` + +A _signature forgery_ is what it sounds like: it's when an attacker, given a public key _A_, creates a signature _σ_ and message _m_ such that _σ_ is a valid signature of _m_ with respect to _A_. Since this is the core security definition of any signature scheme, Ed25519 signatures cannot be forged. + +However, there's a much looser kind of forgery that Ed25519 permits, which we call _weak key forgery_. An attacker can produce a special public key _A_ (which we call a _weak_ public key) and a signature _σ_ such that _σ_ is a valid signature of _any_ message _m_, with respect to _A_, with high probability. This attack is acknowledged in the [Ed25519 paper](https://ed25519.cr.yp.to/ed25519-20110926.pdf), and caused an exploitable bug in the Scuttlebutt protocol ([paper](https://eprint.iacr.org/2019/526.pdf), section 7.1). The [`VerifyingKey::verify()`][method_verify] function permits weak keys. + +We provide [`VerifyingKey::verify_strict`][method_verify_strict] (and [`verify_strict_prehashed`][method_verify_strict_ph]) to help users avoid these scenarios. These functions perform an extra check on _A_, ensuring it's not a weak public key. In addition, we provide the [`VerifyingKey::is_weak`][method_is_weak] to allow users to perform this check before attempting signature verification. + +## Batch verification + +As mentioned above, weak public keys can be used to produce signatures for unknown messages with high probability. This means that sometimes a weak forgery attempt will fail. In fact, it can fail up to 7/8 of the time. If you call `verify()` twice on the same failed forgery, it will return an error both times, as expected. However, if you call `verify_batch()` twice on two distinct otherwise-valid batches, both of which contain the failed forgery, there's a 21% chance that one fails and the other succeeds. + +Why is this? It's because `verify_batch()` does not do the weak key testing of `verify_strict()`, and it multiplies each verification equation by some random coefficient. If the failed forgery gets multiplied by 8, then the weak key (which is a low-order point) becomes 0, and the verification equation on the attempted forgery will succeed. + +Since `verify_batch()` is intended to be high-throughput, we think it's best not to put weak key checks in it. If you want to prevent weird behavior due to weak public keys in your batches, you should call [`VerifyingKey::is_weak`][method_is_weak] on the inputs in advance. + +[fiat]: https://github.com/mit-plv/fiat-crypto +[validation]: https://hdevalence.ca/blog/2020-10-04-its-25519am +[func_verify_batch]: https://docs.rs/ed25519-dalek/latest/ed25519_dalek/fn.verify_batch.html +[method_verify]: https://docs.rs/ed25519-dalek/latest/ed25519_dalek/struct.VerifyingKey.html#method.verify +[method_verify_strict]: https://docs.rs/ed25519-dalek/latest/ed25519_dalek/struct.VerifyingKey.html#method.verify_strict +[method_verify_strict_ph]: https://docs.rs/ed25519-dalek/latest/ed25519_dalek/struct.VerifyingKey.html#method.verify_strict_prehashed +[method_is_weak]: https://docs.rs/ed25519-dalek/latest/ed25519_dalek/struct.VerifyingKey.html#method.is_weak diff --git a/ed25519-dalek/TESTVECTORS b/ed25519-dalek/TESTVECTORS new file mode 100644 index 000000000..4234759c5 --- /dev/null +++ b/ed25519-dalek/TESTVECTORS @@ -0,0 +1,128 @@ +9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a:d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a::e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b: +4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c:3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c:72:92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c0072: +c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025:fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025:af82:6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40aaf82: +0d4a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057:e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057:cbc77b:d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db19b00ccbc77b: +6df9340c138cc188b5fe4464ebaa3f7fc206a2d55c3434707e74c9fc04e20ebbc0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7:c0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7:5f4c8989:124f6fc6b0d100842769e71bd530664d888df8507df6c56dedfdb509aeb93416e26b918d38aa06305df3095697c18b2aa832eaa52edc0ae49fbae5a85e150c075f4c8989: +b780381a65edf8b78f6945e8dbec7941ac049fd4c61040cf0c324357975a293ce253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01:e253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01:18b6bec097:b2fc46ad47af464478c199e1f8be169f1be6327c7f9a0a6689371ca94caf04064a01b22aff1520abd58951341603faed768cf78ce97ae7b038abfe456aa17c0918b6bec097: +78ae9effe6f245e924a7be63041146ebc670dbd3060cba67fbc6216febc44546fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d:fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d:89010d855972:6ed629fc1d9ce9e1468755ff636d5a3f40a5d9c91afd93b79d241830f7e5fa29854b8f20cc6eecbb248dbd8d16d14e99752194e4904d09c74d639518839d230089010d855972: +691865bfc82a1e4b574eecde4c7519093faf0cf867380234e3664645c61c5f7998a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63:98a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63:b4a8f381e70e7a:6e0af2fe55ae377a6b7a7278edfb419bd321e06d0df5e27037db8812e7e3529810fa5552f6c0020985ca17a0e02e036d7b222a24f99b77b75fdd16cb05568107b4a8f381e70e7a: +3b26516fb3dc88eb181b9ed73f0bcd52bcd6b4c788e4bcaf46057fd078bee073f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863:f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863:4284abc51bb67235:d6addec5afb0528ac17bb178d3e7f2887f9adbb1ad16e110545ef3bc57f9de2314a5c8388f723b8907be0f3ac90c6259bbe885ecc17645df3db7d488f805fa084284abc51bb67235: +edc6f5fbdd1cee4d101c063530a30490b221be68c036f5b07d0f953b745df192c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd:c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd:672bf8965d04bc5146:2c76a04af2391c147082e33faacdbe56642a1e134bd388620b852b901a6bc16ff6c9cc9404c41dea12ed281da067a1513866f9d964f8bdd24953856c50042901672bf8965d04bc5146: +4e7d21fb3b1897571a445833be0f9fd41cd62be3aa04040f8934e1fcbdcacd4531b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff:31b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff:33d7a786aded8c1bf691:28e4598c415ae9de01f03f9f3fab4e919e8bf537dd2b0cdf6e79b9e6559c9409d9151a4c40f083193937627c369488259e99da5a9f0a87497fa6696a5dd6ce0833d7a786aded8c1bf691: +a980f892db13c99a3e8971e965b2ff3d41eafd54093bc9f34d1fd22d84115bb644b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f:44b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f:3486f68848a65a0eb5507d:77d389e599630d934076329583cd4105a649a9292abc44cd28c40000c8e2f5ac7660a81c85b72af8452d7d25c070861dae91601c7803d656531650dd4e5c41003486f68848a65a0eb5507d: +5b5a619f8ce1c66d7ce26e5a2ae7b0c04febcd346d286c929e19d0d5973bfef96fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257:6fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257:5a8d9d0a22357e6655f9c785:0f9ad9793033a2fa06614b277d37381e6d94f65ac2a5a94558d09ed6ce922258c1a567952e863ac94297aec3c0d0c8ddf71084e504860bb6ba27449b55adc40e5a8d9d0a22357e6655f9c785: +940c89fe40a81dafbdb2416d14ae469119869744410c3303bfaa0241dac57800a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd:a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd:b87d3813e03f58cf19fd0b6395:d8bb64aad8c9955a115a793addd24f7f2b077648714f49c4694ec995b330d09d640df310f447fd7b6cb5c14f9fe9f490bcf8cfadbfd2169c8ac20d3b8af49a0cb87d3813e03f58cf19fd0b6395: +9acad959d216212d789a119252ebfe0c96512a23c73bd9f3b202292d6916a738cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291:cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291:55c7fa434f5ed8cdec2b7aeac173:6ee3fe81e23c60eb2312b2006b3b25e6838e02106623f844c44edb8dafd66ab0671087fd195df5b8f58a1d6e52af42908053d55c7321010092748795ef94cf0655c7fa434f5ed8cdec2b7aeac173: +d5aeee41eeb0e9d1bf8337f939587ebe296161e6bf5209f591ec939e1440c300fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5:fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5:0a688e79be24f866286d4646b5d81c:f68d04847e5b249737899c014d31c805c5007a62c0a10d50bb1538c5f35503951fbc1e08682f2cc0c92efe8f4985dec61dcbd54d4b94a22547d24451271c8b000a688e79be24f866286d4646b5d81c: +0a47d10452ae2febec518a1c7c362890c3fc1a49d34b03b6467d35c904a8362d34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b:34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b:c942fa7ac6b23ab7ff612fdc8e68ef39:2a3d27dc40d0a8127949a3b7f908b3688f63b7f14f651aacd715940bdbe27a0809aac142f47ab0e1e44fa490ba87ce5392f33a891539caf1ef4c367cae54500cc942fa7ac6b23ab7ff612fdc8e68ef39: +f8148f7506b775ef46fdc8e8c756516812d47d6cfbfa318c27c9a22641e56f170445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372:0445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372:7368724a5b0efb57d28d97622dbde725af:3653ccb21219202b8436fb41a32ba2618c4a133431e6e63463ceb3b6106c4d56e1d2ba165ba76eaad3dc39bffb130f1de3d8e6427db5b71938db4e272bc3e20b7368724a5b0efb57d28d97622dbde725af: +77f88691c4eff23ebb7364947092951a5ff3f10785b417e918823a552dab7c7574d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b:74d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b:bd8e05033f3a8bcdcbf4beceb70901c82e31:fbe929d743a03c17910575492f3092ee2a2bf14a60a3fcacec74a58c7334510fc262db582791322d6c8c41f1700adb80027ecabc14270b703444ae3ee7623e0abd8e05033f3a8bcdcbf4beceb70901c82e31: +ab6f7aee6a0837b334ba5eb1b2ad7fcecfab7e323cab187fe2e0a95d80eff1325b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c:5b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c:8171456f8b907189b1d779e26bc5afbb08c67a:73bca64e9dd0db88138eedfafcea8f5436cfb74bfb0e7733cf349baa0c49775c56d5934e1d38e36f39b7c5beb0a836510c45126f8ec4b6810519905b0ca07c098171456f8b907189b1d779e26bc5afbb08c67a: +8d135de7c8411bbdbd1b31e5dc678f2ac7109e792b60f38cd24936e8a898c32d1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f:1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f:8ba6a4c9a15a244a9c26bb2a59b1026f21348b49:a1adc2bc6a2d980662677e7fdff6424de7dba50f5795ca90fdf3e96e256f3285cac71d3360482e993d0294ba4ec7440c61affdf35fe83e6e04263937db93f1058ba6a4c9a15a244a9c26bb2a59b1026f21348b49: +0e765d720e705f9366c1ab8c3fa84c9a44370c06969f803296884b2846a652a47fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8:7fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8:1d566a6232bbaab3e6d8804bb518a498ed0f904986:bb61cf84de61862207c6a455258bc4db4e15eea0317ff88718b882a06b5cf6ec6fd20c5a269e5d5c805bafbcc579e2590af414c7c227273c102a10070cdfe80f1d566a6232bbaab3e6d8804bb518a498ed0f904986: +db36e326d676c2d19cc8fe0c14b709202ecfc761d27089eb6ea4b1bb021ecfa748359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85:48359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85:1b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4:b6dcd09989dfbac54322a3ce87876e1d62134da998c79d24b50bd7a6a797d86a0e14dc9d7491d6c14a673c652cfbec9f962a38c945da3b2f0879d0b68a9213001b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4: +c89955e0f7741d905df0730b3dc2b0ce1a13134e44fef3d40d60c020ef19df77fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c:fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c:507c94c8820d2a5793cbf3442b3d71936f35fe3afef316:7ef66e5e86f2360848e0014e94880ae2920ad8a3185a46b35d1e07dea8fa8ae4f6b843ba174d99fa7986654a0891c12a794455669375bf92af4cc2770b579e0c507c94c8820d2a5793cbf3442b3d71936f35fe3afef316: +4e62627fc221142478aee7f00781f817f662e3b75db29bb14ab47cf8e84104d6b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107:b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107:d3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5:836afa764d9c48aa4770a4388b654e97b3c16f082967febca27f2fc47ddfd9244b03cfc729698acf5109704346b60b230f255430089ddc56912399d1122de70ad3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5: +6b83d7da8908c3e7205b39864b56e5f3e17196a3fc9c2f5805aad0f5554c142dd0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6:d0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6:6ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c:16e462a29a6dd498685a3718b3eed00cc1598601ee47820486032d6b9acc9bf89f57684e08d8c0f05589cda2882a05dc4c63f9d0431d6552710812433003bc086ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c: +19a91fe23a4e9e33ecc474878f57c64cf154b394203487a7035e1ad9cd697b0d2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23:2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23:82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c:881f5b8c5a030df0f75b6634b070dd27bd1ee3c08738ae349338b3ee6469bbf9760b13578a237d5182535ede121283027a90b5f865d63a6537dca07b44049a0f82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c: +1d5b8cb6215c18141666baeefcf5d69dad5bea9a3493dddaa357a4397a13d4de94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835:94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835:a9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0:3acd39bec8c3cd2b44299722b5850a0400c1443590fd4861d59aae7496acb3df73fc3fdf7969ae5f50ba47dddc435246e5fd376f6b891cd4c2caf5d614b6170ca9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0: +6a91b3227c472299089bdce9356e726a40efd840f11002708b7ee55b64105ac29d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e:9d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e:5cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc:f5875423781b66216cb5e8998de5d9ffc29d1d67107054ace3374503a9c3ef811577f269de81296744bd706f1ac478caf09b54cdf871b3f802bd57f9a6cb91015cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc: +93eaa854d791f05372ce72b94fc6503b2ff8ae6819e6a21afe825e27ada9e4fb16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5:16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5:32fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5:d834197c1a3080614e0a5fa0aaaa808824f21c38d692e6ffbd200f7dfb3c8f44402a7382180b98ad0afc8eec1a02acecf3cb7fde627b9f18111f260ab1db9a0732fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5: +941cac69fb7b1815c57bb987c4d6c2ad2c35d5f9a3182a79d4ba13eab253a8ad23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b:23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b:bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa:0f8fad1e6bde771b4f5420eac75c378bae6db5ac6650cd2bc210c1823b432b48e016b10595458ffab92f7a8989b293ceb8dfed6c243a2038fc06652aaaf16f02bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa: +1acdbb793b0384934627470d795c3d1dd4d79cea59ef983f295b9b59179cbb283f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a:3f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a:7cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56:be71ef4806cb041d885effd9e6b0fbb73d65d7cdec47a89c8a994892f4e55a568c4cc78d61f901e80dbb628b86a23ccd594e712b57fa94c2d67ec266348785077cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56: +8ed7a797b9cea8a8370d419136bcdf683b759d2e3c6947f17e13e2485aa9d420b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9:b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9:a750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3:04266c033b91c1322ceb3446c901ffcf3cc40c4034e887c9597ca1893ba7330becbbd8b48142ef35c012c6ba51a66df9308cb6268ad6b1e4b03e70102495790ba750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3: +f2ab396fe8906e3e5633e99cabcd5b09df0859b516230b1e0450b580b65f616c8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b:8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b:5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187:a06a23d982d81ab883aae230adbc368a6a9977f003cebb00d4c2e4018490191a84d3a282fdbfb2fc88046e62de43e15fb575336b3c8b77d19ce6a009ce51f50c5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187: +550a41c013f79bab8f06e43ad1836d51312736a9713806fafe6645219eaa1f9daf6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0:af6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0:8bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27:16dc1e2b9fa909eefdc277ba16ebe207b8da5e91143cde78c5047a89f681c33c4e4e3428d5c928095903a811ec002d52a39ed7f8b3fe1927200c6dd0b9ab3e048bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27: +19ac3e272438c72ddf7b881964867cb3b31ff4c793bb7ea154613c1db068cb7ef85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f:f85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f:95872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645:ea855d781cbea4682e350173cb89e8619ccfddb97cdce16f9a2f6f6892f46dbe68e04b12b8d88689a7a31670cdff409af98a93b49a34537b6aa009d2eb8b470195872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645: +ca267de96c93c238fafb1279812059ab93ac03059657fd994f8fa5a09239c821017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26:017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26:e05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531:ac957f82335aa7141e96b59d63e3ccee95c3a2c47d026540c2af42dc9533d5fd81827d1679ad187aeaf37834915e75b147a9286806c8017516ba43dd051a5e0ce05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531: +3dff5e899475e7e91dd261322fab09980c52970de1da6e2e201660cc4fce7032f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b:f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b:938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382:5efe7a92ff9623089b3e3b78f352115366e26ba3fb1a416209bc029e9cadccd9f4affa333555a8f3a35a9d0f7c34b292cae77ec96fa3adfcaadee2d9ced8f805938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382: +9a6b847864e70cfe8ba6ab22fa0ca308c0cc8bec7141fbcaa3b81f5d1e1cfcfc34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930:34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930:838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da:2ab255169c489c54c732232e37c87349d486b1eba20509dbabe7fed329ef08fd75ba1cd145e67b2ea26cb5cc51cab343eeb085fe1fd7b0ec4c6afcd9b979f905838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da: +575be07afca5d063c238cd9b8028772cc49cda34471432a2e166e096e2219efc94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0:94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0:33e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e:58271d44236f3b98c58fd7ae0d2f49ef2b6e3affdb225aa3ba555f0e11cc53c23ad19baf24346590d05d7d5390582082cf94d39cad6530ab93d13efb3927950633e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e: +15ffb45514d43444d61fcb105e30e135fd268523dda20b82758b1794231104411772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8:1772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8:da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e:6828cd7624e793b8a4ceb96d3c2a975bf773e5ff6645f353614058621e58835289e7f31f42dfe6af6d736f2644511e320c0fa698582a79778d18730ed3e8cb08da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e: +fe0568642943b2e1afbfd1f10fe8df87a4236bea40dce742072cb21886eec1fa299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61:299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61:c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d:d59e6dfcc6d7e3e2c58dec81e985d245e681acf6594a23c59214f7bed8015d813c7682b60b3583440311e72a8665ba2c96dec23ce826e160127e18132b030404c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d: +5ecb16c2df27c8cf58e436a9d3affbd58e9538a92659a0f97c4c4f994635a8cada768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d:da768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d:56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9:1c723a20c6772426a670e4d5c4a97c6ebe9147f71bb0a415631e44406e290322e4ca977d348fe7856a8edc235d0fe95f7ed91aefddf28a77e2c7dbfd8f552f0a56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9: +d599d637b3c30a82a9984e2f758497d144de6f06b9fba04dd40fd949039d7c846791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f:6791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f:a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e:ebf10d9ac7c96108140e7def6fe9533d727646ff5b3af273c1df95762a66f32b65a09634d013f54b5dd6011f91bc336ca8b355ce33f8cfbec2535a4c427f8205a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e: +30ab8232fa7018f0ce6c39bd8f782fe2e159758bb0f2f4386c7f28cfd2c85898ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37:ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37:63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc:9af885344cc7239498f712df80bc01b80638291ed4a1d28baa5545017a72e2f65649ccf9603da6eb5bfab9f5543a6ca4a7af3866153c76bf66bf95def615b00c63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc: +0ddcdc872c7b748d40efe96c2881ae189d87f56148ed8af3ebbbc80324e38bdd588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85:588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85:65641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12:c179c09456e235fe24105afa6e8ec04637f8f943817cd098ba95387f9653b2add181a31447d92d1a1ddf1ceb0db62118de9dffb7dcd2424057cbdff5d41d040365641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12: +89f0d68299ba0a5a83f248ae0c169f8e3849a9b47bd4549884305c9912b46603aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832:aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832:4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05:2c691fa8d487ce20d5d2fa41559116e0bbf4397cf5240e152556183541d66cf753582401a4388d390339dbef4d384743caa346f55f8daba68ba7b9131a8a6e0b4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05: +0a3c1844e2db070fb24e3c95cb1cc6714ef84e2ccd2b9dd2f1460ebf7ecf13b172e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01:72e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01:4c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957:87f7fdf46095201e877a588fe3e5aaf476bd63138d8a878b89d6ac60631b3458b9d41a3c61a588e1db8d29a5968981b018776c588780922f5aa732ba6379dd054c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957: +c8d7a8818b98dfdb20839c871cb5c48e9e9470ca3ad35ba2613a5d3199c8ab2390d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f:90d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f:783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff:fa2e994421aef1d5856674813d05cbd2cf84ef5eb424af6ecd0dc6fdbdc2fe605fe985883312ecf34f59bfb2f1c9149e5b9cc9ecda05b2731130f3ed28ddae0b783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff: +b482703612d0c586f76cfcb21cfd2103c957251504a8c0ac4c86c9c6f3e429fffd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad:fd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad:29d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b:58832bdeb26feafc31b46277cf3fb5d7a17dfb7ccd9b1f58ecbe6feb979666828f239ba4d75219260ecac0acf40f0e5e2590f4caa16bbbcd8a155d347967a60729d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b: +84e50dd9a0f197e3893c38dbd91fafc344c1776d3a400e2f0f0ee7aa829eb8a22c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea:2c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea:f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123:69e6a4491a63837316e86a5f4ba7cd0d731ecc58f1d0a264c67c89befdd8d3829d8de13b33cc0bf513931715c7809657e2bfb960e5c764c971d733746093e500f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123: +b322d46577a2a991a4d1698287832a39c487ef776b4bff037a05c7f1812bdeeceb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f:eb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f:19f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5:c7b55137317ca21e33489ff6a9bfab97c855dc6f85684a70a9125a261b56d5e6f149c5774d734f2d8debfc77b721896a8267c23768e9badb910eef83ec25880219f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5: +960cab5034b9838d098d2dcbf4364bec16d388f6376d73a6273b70f82bbc98c05e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a:5e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a:f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308:27d4c3a1811ef9d4360b3bdd133c2ccc30d02c2f248215776cb07ee4177f9b13fc42dd70a6c2fed8f225c7663c7f182e7ee8eccff20dc7b0e1d5834ec5b1ea01f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308: +eb77b2638f23eebc82efe45ee9e5a0326637401e663ed029699b21e6443fb48e9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc:9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc:99e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab:18dc56d7bd9acd4f4daa78540b4ac8ff7aa9815f45a0bba370731a14eaabe96df8b5f37dbf8eae4cb15a64b244651e59d6a3d6761d9e3c50f2d0cbb09c05ec0699e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab: +b625aa89d3f7308715427b6c39bbac58effd3a0fb7316f7a22b99ee5922f2dc965a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e:65a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e:e07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a:01bb901d83b8b682d3614af46a807ba2691358feb775325d3423f549ff0aa5757e4e1a74e9c70f9721d8f354b319d4f4a1d91445c870fd0ffb94fed64664730de07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a: +b1c9f8bd03fe82e78f5c0fb06450f27dacdf716434db268275df3e1dc177af427fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf:7fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf:331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2:4b229951ef262f16978f7914bc672e7226c5f8379d2778c5a2dc0a2650869f7acfbd0bcd30fdb0619bb44fc1ae5939b87cc318133009c20395b6c7eb98107701331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2: +6d8cdb2e075f3a2f86137214cb236ceb89a6728bb4a200806bf3557fb78fac6957a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda:57a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda:7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf:a6cbc947f9c87d1455cf1a708528c090f11ecee4855d1dbaadf47454a4de55fa4ce84b36d73a5b5f8f59298ccf21992df492ef34163d87753b7e9d32f2c3660b7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf: +47adc6d6bf571ee9570ca0f75b604ac43e303e4ab339ca9b53cacc5be45b2ccba3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be:a3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be:ce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739:4e8c318343c306adbba60c92b75cb0569b9219d8a86e5d57752ed235fc109a43c2cf4e942cacf297279fbb28675347e08027722a4eb7395e00a17495d32edf0bce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739: +3c19b50b0fe47961719c381d0d8da9b9869d312f13e3298b97fb22f0af29cbbe0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612:0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612:8ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f:efbd41f26a5d62685516f882b6ec74e0d5a71830d203c231248f26e99a9c6578ec900d68cdb8fa7216ad0d24f9ecbc9ffa655351666582f626645395a31fa7048ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f: +34e1e9d539107eb86b393a5ccea1496d35bc7d5e9a8c5159d957e4e5852b3eb00ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76:0ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76:a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0:32d22904d3e7012d6f5a441b0b4228064a5cf95b723a66b048a087ecd55920c31c204c3f2006891a85dd1932e3f1d614cfd633b5e63291c6d8166f3011431e09a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0: +49dd473ede6aa3c866824a40ada4996c239a20d84c9365e4f0a4554f8031b9cf788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501:788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501:3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c:d2fde02791e720852507faa7c3789040d9ef86646321f313ac557f4002491542dd67d05c6990cdb0d495501fbc5d5188bfbb84dc1bf6098bee0603a47fc2690f3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c: +331c64da482b6b551373c36481a02d8136ecadbb01ab114b4470bf41607ac57152a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521:52a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521:20e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3:22c99aa946ead39ac7997562810c01c20b46bd610645bd2d56dcdcbaacc5452c74fbf4b8b1813b0e94c30d808ce5498e61d4f7ccbb4cc5f04dfc6140825a960020e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3: +5c0b96f2af8712122cf743c8f8dc77b6cd5570a7de13297bb3dde1886213cce20510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1:0510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1:54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575:06e5d8436ac7705b3a90f1631cdd38ec1a3fa49778a9b9f2fa5ebea4e7d560ada7dd26ff42fafa8ba420323742761aca6904940dc21bbef63ff72daab45d430b54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575: +bf5ba5d6a49dd5ef7b4d5d7d3e4ecc505c01f6ccee4c54b5ef7b40af6a4541401be034f813017b900d8990af45fad5b5214b573bd303ef7a75ef4b8c5c5b9842:1be034f813017b900d8990af45fad5b5214b573bd303ef7a75ef4b8c5c5b9842:16152c2e037b1c0d3219ced8e0674aee6b57834b55106c5344625322da638ecea2fc9a424a05ee9512d48fcf75dd8bd4691b3c10c28ec98ee1afa5b863d1c36795ed18105db3a9aabd9d2b4c1747adbaf1a56ffcc0c533c1c0faef331cdb79d961fa39f880a1b8b1164741822efb15a7259a465bef212855751fab66a897bfa211abe0ea2f2e1cd8a11d80e142cde1263eec267a3138ae1fcf4099db0ab53d64f336f4bcd7a363f6db112c0a2453051a0006f813aaf4ae948a2090619374fa58052409c28ef76225687df3cb2d1b0bfb43b09f47f1232f790e6d8dea759e57942099f4c4bd3390f28afc2098244961465c643fc8b29766af2bcbc5440b86e83608cfc937be98bb4827fd5e6b689adc2e26513db531076a6564396255a09975b7034dac06461b255642e3a7ed75fa9fc265011f5f6250382a84ac268d63ba64:279cace6fdaf3945e3837df474b28646143747632bede93e7a66f5ca291d2c24978512ca0cb8827c8c322685bd605503a5ec94dbae61bbdcae1e49650602bc0716152c2e037b1c0d3219ced8e0674aee6b57834b55106c5344625322da638ecea2fc9a424a05ee9512d48fcf75dd8bd4691b3c10c28ec98ee1afa5b863d1c36795ed18105db3a9aabd9d2b4c1747adbaf1a56ffcc0c533c1c0faef331cdb79d961fa39f880a1b8b1164741822efb15a7259a465bef212855751fab66a897bfa211abe0ea2f2e1cd8a11d80e142cde1263eec267a3138ae1fcf4099db0ab53d64f336f4bcd7a363f6db112c0a2453051a0006f813aaf4ae948a2090619374fa58052409c28ef76225687df3cb2d1b0bfb43b09f47f1232f790e6d8dea759e57942099f4c4bd3390f28afc2098244961465c643fc8b29766af2bcbc5440b86e83608cfc937be98bb4827fd5e6b689adc2e26513db531076a6564396255a09975b7034dac06461b255642e3a7ed75fa9fc265011f5f6250382a84ac268d63ba64: +65de297b70cbe80980500af0561a24db50001000125f4490366d8300d3128592ba8e2ad929bdcea538741042b57f2067d3153707a453770db9f3c4ca75504d24:ba8e2ad929bdcea538741042b57f2067d3153707a453770db9f3c4ca75504d24:131d8f4c2c94b153565b86592e770c987a443461b39aa2408b29e213ab057affc598b583739d6603a83fef0afc514721db0e76f9bd1b72b98c565cc8881af5747c0ba6f58c53dd2377da6c0d3aa805620cc4e75d52aabcba1f9b2849e08bd1b6b92e6f06615b814519606a02dc65a8609f5b29e9c2af5a894f7116ef28cfd1e7b76b64061732f7a5a3f8aa4c2e569e627a3f9749aa597be49d6b94436c352dd5fa7b83c92d2610faa32095ca302152d91a3c9776750e758ee8e9e402c6f5385eaa5df23850e54beb1be437a416c7115ed6aa6de13b55482532787e0bee34b83f3084406765635497c931b62a0518f1fbc2b891dc7262c7c6b67eda594fa530d74c9329bad5be94c287fbcde53aa80272b83322613d9368e5904076fdbcc88b2c0e59c10b02c448e00d1b3e7a9c9640feffb9523a8a60e1d83f04a4b8df69153b:7a9b736b01cc92a3349f1a3c32dbd91959825394ff443c567405e899c8185ce8fad9500e1fce89d95a6253c00477435acf04bff993de1b00495def0834ee1f07131d8f4c2c94b153565b86592e770c987a443461b39aa2408b29e213ab057affc598b583739d6603a83fef0afc514721db0e76f9bd1b72b98c565cc8881af5747c0ba6f58c53dd2377da6c0d3aa805620cc4e75d52aabcba1f9b2849e08bd1b6b92e6f06615b814519606a02dc65a8609f5b29e9c2af5a894f7116ef28cfd1e7b76b64061732f7a5a3f8aa4c2e569e627a3f9749aa597be49d6b94436c352dd5fa7b83c92d2610faa32095ca302152d91a3c9776750e758ee8e9e402c6f5385eaa5df23850e54beb1be437a416c7115ed6aa6de13b55482532787e0bee34b83f3084406765635497c931b62a0518f1fbc2b891dc7262c7c6b67eda594fa530d74c9329bad5be94c287fbcde53aa80272b83322613d9368e5904076fdbcc88b2c0e59c10b02c448e00d1b3e7a9c9640feffb9523a8a60e1d83f04a4b8df69153b: +0826e7333324e7ec8c764292f6015d4670e9b8d7c4a89e8d909e8ef435d18d15ffb2348ca8a018058be71d1512f376f91e8b0d552581254e107602217395e662:ffb2348ca8a018058be71d1512f376f91e8b0d552581254e107602217395e662:7f9e3e2f03c9df3d21b990f5a4af8295734afe783accc34fb1e9b8e95a0fd837af7e05c13cda0de8fadac9205265a0792b52563bdc2fee766348befcc56b88bbb95f154414fb186ec436aa62ea6fcabb11c017a9d2d15f67e595980e04c9313bc94fbc8c1134c2f40332bc7e311ac1ce11b505f8572ada7fbe196fba822d9a914492fa7185e9f3bea4687200a524c673a1cdf87eb3a140dcdb6a8875613488a2b00adf7175341c1c257635fa1a53a3e21d60c228399eea0991f112c60f653d7148e2c5ceb98f940831f070db1084d79156cc82c46bc9b8e884f3fa81be2da4cdda46bcaa24cc461f76ee647bb0f0f8c15ac5daa795b945e6f85bb310362e48d8095c782c61c52b481b4b002ad06ea74b8d306eff71abf21db710a8913cbe48332be0a0b3f31e0c7a6eba85ce33f357c7aeccd30bfb1a6574408b66fe404d31c3c5:4bac7fabec8724d81ab09ae130874d70b5213492104372f601ae5abb10532799373c4dad215876441f474e2c006be37c3c8f5f6f017d0870414fd276a8f428087f9e3e2f03c9df3d21b990f5a4af8295734afe783accc34fb1e9b8e95a0fd837af7e05c13cda0de8fadac9205265a0792b52563bdc2fee766348befcc56b88bbb95f154414fb186ec436aa62ea6fcabb11c017a9d2d15f67e595980e04c9313bc94fbc8c1134c2f40332bc7e311ac1ce11b505f8572ada7fbe196fba822d9a914492fa7185e9f3bea4687200a524c673a1cdf87eb3a140dcdb6a8875613488a2b00adf7175341c1c257635fa1a53a3e21d60c228399eea0991f112c60f653d7148e2c5ceb98f940831f070db1084d79156cc82c46bc9b8e884f3fa81be2da4cdda46bcaa24cc461f76ee647bb0f0f8c15ac5daa795b945e6f85bb310362e48d8095c782c61c52b481b4b002ad06ea74b8d306eff71abf21db710a8913cbe48332be0a0b3f31e0c7a6eba85ce33f357c7aeccd30bfb1a6574408b66fe404d31c3c5: +00ad6227977b5f38ccda994d928bba9086d2daeb013f8690db986648b90c1d4591a4ea005752b92cbebf99a8a5cbecd240ae3f016c44ad141b2e57ddc773dc8e:91a4ea005752b92cbebf99a8a5cbecd240ae3f016c44ad141b2e57ddc773dc8e:cb5bc5b98b2efce43543e91df041e0dbb53ed8f67bf0f197c52b2211e7a45e2e1ec818c1a80e10abf6a43535f5b79d974d8ae28a2295c0a6521763b607d5103c6aef3b2786bd5afd7563695660684337bc3090739fb1cd53a9d644139b6d4caec75bda7f2521fbfe676ab45b98cb317aa7ca79fc54a3d7c578466a6aa64e434e923465a7f211aa0c61681bb8486e90206a25250d3fdae6fb03299721e99e2a914910d91760089b5d281e131e6c836bc2de08f7e02c48d323c647e9536c00ec1039201c0362618c7d47aa8e7b9715ffc439987ae1d31154a6198c5aa11c128f4082f556c99baf103ecadc3b2f3b2ec5b469623bc03a53caf3814b16300aedbda538d676d1f607102639db2a62c446707ce6469bd873a0468225be88b0aef5d4020459b94b32fe2b0133e92e7ba54dd2a5397ed85f966ab39ed0730cca8e7dacb8a336:dc501db79fd782bc88cae792557d5d273f9ba560c7d90037fe84ac879d684f612a77452c4443e95c07b8be192c35769b17bbdfca42280de796d92119d833670dcb5bc5b98b2efce43543e91df041e0dbb53ed8f67bf0f197c52b2211e7a45e2e1ec818c1a80e10abf6a43535f5b79d974d8ae28a2295c0a6521763b607d5103c6aef3b2786bd5afd7563695660684337bc3090739fb1cd53a9d644139b6d4caec75bda7f2521fbfe676ab45b98cb317aa7ca79fc54a3d7c578466a6aa64e434e923465a7f211aa0c61681bb8486e90206a25250d3fdae6fb03299721e99e2a914910d91760089b5d281e131e6c836bc2de08f7e02c48d323c647e9536c00ec1039201c0362618c7d47aa8e7b9715ffc439987ae1d31154a6198c5aa11c128f4082f556c99baf103ecadc3b2f3b2ec5b469623bc03a53caf3814b16300aedbda538d676d1f607102639db2a62c446707ce6469bd873a0468225be88b0aef5d4020459b94b32fe2b0133e92e7ba54dd2a5397ed85f966ab39ed0730cca8e7dacb8a336: +1521c6dbd6f724de73eaf7b56264f01035c04e01c1f3eb3cbe83efd26c439ada2f61a26ffb68ba4f6e141529dc2617e8531c7151404808093b4fa7fedaea255d:2f61a26ffb68ba4f6e141529dc2617e8531c7151404808093b4fa7fedaea255d:3e3c7c490788e4b1d42f5cbcae3a9930bf617ebdff447f7be2ac2ba7cd5bcfc015760963e6fe5b956fb7cdb35bd5a17f5429ca664f437f08753a741c2bc8692b71a9115c582a25b2f74d329854d60b7817c079b3523aaff8793c2f72fff8cd10592c54e738df1d6452fb72da131c6731ea5c953c62ea177ac1f4735e5154477387109afae15f3ed6eeb08606e28c81d4386f03b9376924b6ef8d221ee29547f82a7ede48e1dc17723e3d42171eeaf96ac84bedc2a01dd86f4d085734fd69f91b5263e439083ff0318536adff4147308e3aafd1b58bb74f6fb0214a46fdcd3524f18df5a719ce57319e791b4ea606b499bfa57a60e707f94e18f1fed22f91bc79e6364a843f9cbf93825c465e9cae9072bc9d3ec4471f21ab2f7e99a633f587aac3db78ae9666a89a18008dd61d60218554411a65740ffd1ae3adc06595e3b7876407b6:a817ed23ec398a128601c1832dc6af7643bf3a5f517bcc579450fdb4759028f4966164125f6ebd0d6bf86ff298a39c766d0c21fdb0cbfdf81cd0eb1f03cd8a083e3c7c490788e4b1d42f5cbcae3a9930bf617ebdff447f7be2ac2ba7cd5bcfc015760963e6fe5b956fb7cdb35bd5a17f5429ca664f437f08753a741c2bc8692b71a9115c582a25b2f74d329854d60b7817c079b3523aaff8793c2f72fff8cd10592c54e738df1d6452fb72da131c6731ea5c953c62ea177ac1f4735e5154477387109afae15f3ed6eeb08606e28c81d4386f03b9376924b6ef8d221ee29547f82a7ede48e1dc17723e3d42171eeaf96ac84bedc2a01dd86f4d085734fd69f91b5263e439083ff0318536adff4147308e3aafd1b58bb74f6fb0214a46fdcd3524f18df5a719ce57319e791b4ea606b499bfa57a60e707f94e18f1fed22f91bc79e6364a843f9cbf93825c465e9cae9072bc9d3ec4471f21ab2f7e99a633f587aac3db78ae9666a89a18008dd61d60218554411a65740ffd1ae3adc06595e3b7876407b6: +17e5f0a8f34751babc5c723ecf339306992f39ea065ac140fcbc397d2dd32c4b4f1e23cc0f2f69c88ef9162ab5f8c59fb3b8ab2096b77e782c63c07c8c4f2b60:4f1e23cc0f2f69c88ef9162ab5f8c59fb3b8ab2096b77e782c63c07c8c4f2b60:c0fad790024019bd6fc08a7a92f5f2ac35cf6432e2eaa53d482f6e1204935336cb3ae65a63c24d0ec6539a10ee18760f2f520537774cdec6e96b55536011daa8f8bcb9cdaf6df5b34648448ac7d7cb7c6bd80d67fbf330f8765297766046a925ab52411d1604c3ed6a85173040125658a32cf4c854ef2813df2be6f3830e5eee5a6163a83ca8849f612991a31e9f88028e50bf8535e11755fad029d94cf25959f6695d09c1ba4315d40f7cf51b3f8166d02faba7511ecd8b1dded5f10cd6843455cff707ed225396c61d0820d20ada70d0c3619ff679422061c9f7c76e97d5a37af61fd62212d2dafc647ebbb979e61d9070ec03609a07f5fc57d119ae64b7a6ef92a5afae660a30ed48d702cc3128c633b4f19060a0578101729ee979f790f45bdbb5fe1a8a62f01a61a31d61af07030450fa0417323e9407bc76e73130e7c69d62e6a7:efe2cb63fe7b4fc98946dc82fb6998e741ed9ce6b9c1a93bb45bc0a7d8396d7405282b43fe363ba5b23589f8e1fae130e157ce888cd72d053d0cc19d257a4300c0fad790024019bd6fc08a7a92f5f2ac35cf6432e2eaa53d482f6e1204935336cb3ae65a63c24d0ec6539a10ee18760f2f520537774cdec6e96b55536011daa8f8bcb9cdaf6df5b34648448ac7d7cb7c6bd80d67fbf330f8765297766046a925ab52411d1604c3ed6a85173040125658a32cf4c854ef2813df2be6f3830e5eee5a6163a83ca8849f612991a31e9f88028e50bf8535e11755fad029d94cf25959f6695d09c1ba4315d40f7cf51b3f8166d02faba7511ecd8b1dded5f10cd6843455cff707ed225396c61d0820d20ada70d0c3619ff679422061c9f7c76e97d5a37af61fd62212d2dafc647ebbb979e61d9070ec03609a07f5fc57d119ae64b7a6ef92a5afae660a30ed48d702cc3128c633b4f19060a0578101729ee979f790f45bdbb5fe1a8a62f01a61a31d61af07030450fa0417323e9407bc76e73130e7c69d62e6a7: +0cd7aa7d605e44d5ffb97966b2cb93c189e4c5a85db87fad7ab8d62463c59b594889855fe4116b4913927f47f2273bf559c3b394a983631a25ae597033185e46:4889855fe4116b4913927f47f2273bf559c3b394a983631a25ae597033185e46:28a55dda6cd0844b6577c9d6da073a4dc35cbc98ac158ab54cf88fd20cc87e83c4bba2d74d82ce0f4854ec4db513de400465aaa5eee790bc84f16337072d3a91cde40d6e0df1ba0cc0645f5d5cbbb642381d7b9e211d25267a8acf77d1edb69c3a630f5b133d24f046a81bf22ff03b31d8447e12c3f7b77114a70cbd20bbd08b0b3827a6bbcf90409e344447a7fbc59bdd97d729071f8d71dcc33e6ef2cbab1d411edf13734db1dd9703276f5eb2d6aa2cb8952dd6712bfae809ce08c3aa502b8135713fac0a9c25b1d45b6a5831e02421bba65b81a596efa24b0576bd1dc7fdfb49be762875e81bd540722bc06140b9aa2ef7b84a801e41ded68d4546ac4873d9e7ced649b64fadaf0b5c4b6eb8d036315233f4326ca01e03393050cd027c24f67303fb846bd2c6b3dba06bed0d59a36289d24bd648f7db0b3a81346612593e3ddd18c557:bf9115fd3d02706e398d4bf3b02a82674ff3041508fd39d29f867e501634b9261f516a794f98738d7c7013a3f2f858ffdd08047fb6bf3dddfb4b4f4cbeef300328a55dda6cd0844b6577c9d6da073a4dc35cbc98ac158ab54cf88fd20cc87e83c4bba2d74d82ce0f4854ec4db513de400465aaa5eee790bc84f16337072d3a91cde40d6e0df1ba0cc0645f5d5cbbb642381d7b9e211d25267a8acf77d1edb69c3a630f5b133d24f046a81bf22ff03b31d8447e12c3f7b77114a70cbd20bbd08b0b3827a6bbcf90409e344447a7fbc59bdd97d729071f8d71dcc33e6ef2cbab1d411edf13734db1dd9703276f5eb2d6aa2cb8952dd6712bfae809ce08c3aa502b8135713fac0a9c25b1d45b6a5831e02421bba65b81a596efa24b0576bd1dc7fdfb49be762875e81bd540722bc06140b9aa2ef7b84a801e41ded68d4546ac4873d9e7ced649b64fadaf0b5c4b6eb8d036315233f4326ca01e03393050cd027c24f67303fb846bd2c6b3dba06bed0d59a36289d24bd648f7db0b3a81346612593e3ddd18c557: +33371d9e892f9875052ac8e325ba505e7477c1ace24ba7822643d43d0acef3de35929bded27c249c87d8b8d82f59260a575327b546c3a167c69f5992d5b8e006:35929bded27c249c87d8b8d82f59260a575327b546c3a167c69f5992d5b8e006:27a32efba28204be59b7ff5fe488ca158a91d5986091ecc4458b49e090dd37cbfede7c0f46186fabcbdff78d2844155808efffd873ed9c9261526e04e4f7050b8d7bd267a0fe3d5a449378d54a4febbd2f26824338e2aaaf35a32ff0f62504bda5c2e44abc63159f336cf25e6bb40ddb7d8825dff18fd51fc01951eaedcd33707007e1203ca58b4f7d242f8166a907e099932c001bfb1ec9a61e0ef2da4e8446af208201315d69681710d425d2400c387d7b9df321a4aec602b9c656c3e2310bff8756d18b802134b15604f4edc111149a9879e31241dd34f702f4c349617b13529769a772f5e52a89c098e0dca5920667893a250061b17991626eb9319298685be46b6a8b68422444fa5a36bcf3a687e2eccb9322c87dc80165da898930850b98fc863cada1aa99c6d61c451b9ccf4874c7f0e75b0a0c602f044812c71765adaf02025395b0:985ca446ddc007827cc8f2852cbd8115ef8c5975e9d7ce96d74dfed859aa14a4c15254006bea5e08359efe2625d715e0897ee5a16f151203be5010418637de0527a32efba28204be59b7ff5fe488ca158a91d5986091ecc4458b49e090dd37cbfede7c0f46186fabcbdff78d2844155808efffd873ed9c9261526e04e4f7050b8d7bd267a0fe3d5a449378d54a4febbd2f26824338e2aaaf35a32ff0f62504bda5c2e44abc63159f336cf25e6bb40ddb7d8825dff18fd51fc01951eaedcd33707007e1203ca58b4f7d242f8166a907e099932c001bfb1ec9a61e0ef2da4e8446af208201315d69681710d425d2400c387d7b9df321a4aec602b9c656c3e2310bff8756d18b802134b15604f4edc111149a9879e31241dd34f702f4c349617b13529769a772f5e52a89c098e0dca5920667893a250061b17991626eb9319298685be46b6a8b68422444fa5a36bcf3a687e2eccb9322c87dc80165da898930850b98fc863cada1aa99c6d61c451b9ccf4874c7f0e75b0a0c602f044812c71765adaf02025395b0: +beedb8073df58f8c1bffbdbd77ec7decb2c82a9babecefc0331507bdc2c2a7e7b27e908b805e296fc30d2e474b060cd50c0f6f520b3671712183bd89d4e733e9:b27e908b805e296fc30d2e474b060cd50c0f6f520b3671712183bd89d4e733e9:35ca57f0f915e5209d54ea4b871ffb585354df1b4a4a1796fbe4d6227d3e1aba5171ed0391a79e83e24d82fdafd15c17b28bf6c94d618c74d65264e58faaacd2902872fdd0efa22e8d2d7ce8e3b8197f0c3615b0a385235fa9fd8e4564ee6e6b1650b4cfb94d872c805c32d4f3a18f966461d3adbb605fa525884f8eb197627396ba4d995d78ac02948a0eaabb58519b9a8e2e7985cd1de2c71d8918d96a0168660ce17cddf364e3ec0d4bd90f2104751a1927ee1d23f3e7a69840ed040b00e5f6e4866ec58813149cc382aebf6162608c79574d553f47230e924a0ef1ebf55d8e1a52abb62a2d7ac86027c7c03cc83fa1949da29e2f3037ab986fd2fffe650e3149babae5a50b1ee9696f3babec72e29697c82422814d272085500fd837fe3c7a973ef4c169af12dd7f02700620bb045bdbf84623f326350570b3cadbc9aea4200b28287e17ab:8c890cccadc7760e1e82e43c44b3dc0b685a48b479ae13cc0a6b0557d0fb1cbabba63d2a96843412ea8d36c50acbf52b92cfb2dce49dc48af6ddcf8ee47a860835ca57f0f915e5209d54ea4b871ffb585354df1b4a4a1796fbe4d6227d3e1aba5171ed0391a79e83e24d82fdafd15c17b28bf6c94d618c74d65264e58faaacd2902872fdd0efa22e8d2d7ce8e3b8197f0c3615b0a385235fa9fd8e4564ee6e6b1650b4cfb94d872c805c32d4f3a18f966461d3adbb605fa525884f8eb197627396ba4d995d78ac02948a0eaabb58519b9a8e2e7985cd1de2c71d8918d96a0168660ce17cddf364e3ec0d4bd90f2104751a1927ee1d23f3e7a69840ed040b00e5f6e4866ec58813149cc382aebf6162608c79574d553f47230e924a0ef1ebf55d8e1a52abb62a2d7ac86027c7c03cc83fa1949da29e2f3037ab986fd2fffe650e3149babae5a50b1ee9696f3babec72e29697c82422814d272085500fd837fe3c7a973ef4c169af12dd7f02700620bb045bdbf84623f326350570b3cadbc9aea4200b28287e17ab: +9184ef618816832592bc8eb35f4ffd4ff98dfbf7776c90f2aad212ce7e03351e687b7726010d9bde2c90e573cd2a2a702ff28c4a2af70afc7315c94d575601e5:687b7726010d9bde2c90e573cd2a2a702ff28c4a2af70afc7315c94d575601e5:729eb7e54a9d00c58617af18c345b8dc6e5b4e0f57de2f3c02e54a2ec8f1425ec2e240775b5ab0c10f84ac8bafda4584f7e21c655faecd8030a98906bd68398f26b5d58d92b6cf045e9bd9743c74c9a342ec61ce57f37b981eac4d8bf034608866e985bb68686a68b4a2af88b992a2a6d2dc8ce88bfb0a36cf28bbab7024abfa2bea53313b66c906f4f7cf66970f540095bd0104aa4924dd82e15413c22679f847e48cd0c7ec1f677e005fec0177fbd5c559fc39add613991fbaeae4d24d39d309ef74647f8192cc4c62d0642028c76a1b951f6bc9639deb91ecc08be6043f2109705a42c7eae712649d91d96ccbbfb63d8d0dd6dd112160f61361ecdc6793929ca9aef9ab56944a6fa4a7df1e279eaf58ce8323a9cf62c94279fff7440fbc936baa61489c999330badcb9fc0e184bc5093f330cbb242f71fb378738fea10511dd438364d7f76bcc:b3c24e75132c563475422d5ea412b5c1e8e6e5ea1c08ead1393c412da134c9a1638284ea7e2ca032fe3d3e32a9066a8c8839903f6ef46e966bb5e492d8c2aa00729eb7e54a9d00c58617af18c345b8dc6e5b4e0f57de2f3c02e54a2ec8f1425ec2e240775b5ab0c10f84ac8bafda4584f7e21c655faecd8030a98906bd68398f26b5d58d92b6cf045e9bd9743c74c9a342ec61ce57f37b981eac4d8bf034608866e985bb68686a68b4a2af88b992a2a6d2dc8ce88bfb0a36cf28bbab7024abfa2bea53313b66c906f4f7cf66970f540095bd0104aa4924dd82e15413c22679f847e48cd0c7ec1f677e005fec0177fbd5c559fc39add613991fbaeae4d24d39d309ef74647f8192cc4c62d0642028c76a1b951f6bc9639deb91ecc08be6043f2109705a42c7eae712649d91d96ccbbfb63d8d0dd6dd112160f61361ecdc6793929ca9aef9ab56944a6fa4a7df1e279eaf58ce8323a9cf62c94279fff7440fbc936baa61489c999330badcb9fc0e184bc5093f330cbb242f71fb378738fea10511dd438364d7f76bcc: +354e13152ee1fe748a1252204c6527bdc1b1eb2eb53678150e6359924708d812d45ff6c5fb83e7bb9669aa8960deb7dbc665c988439b6c9ef672c6811dc8bcf6:d45ff6c5fb83e7bb9669aa8960deb7dbc665c988439b6c9ef672c6811dc8bcf6:8e5fccf66b1ba6169cb685733d9d0e0190361c90bcab95c163285a97fe356d2bdcde3c9380268805a384d063da09ccd9969cc3ff7431e60a8e9f869cd62faa0e356151b280bc526e577c2c538c9a724dc48bf88b70321d7e1eeedb3c4af706748c942e67bdabdb41bec2977b1523069e31e29b76300288f88a51b384b80cc2526f1679340ddec3881f5cd28b0378d9cd0a812b68dd3f68f7a23e1b54bee7466ac765cf38df04d67441dfa498c4bffc52045fa6d2dbcdbfa33dfaa77644ffccef0decdb6790c70a0d734ec287cc338cb5a909c0055189301169c4f7702c05c0911a27b16ef9ed934fa6a0ca7b13e413523422535647968030edc40cd73e7d6b345b7581f438316d68e3cd292b846d3f4f7c4862bc7e6b3fb89a27f6f60cd7db2e34ec9aae1013fe37acff8ad888cb9a593ef5e621eae5186c58b31dcfde22870e336d33f440f6b8d49a:de2b46e65f3decef34332e500f2e11306fbdcf1be85a1c1ee68ba3045dcec2c7be608d22927da1f44c0e2083ae622cf3c29d893887994efcfa2ca594f5051f038e5fccf66b1ba6169cb685733d9d0e0190361c90bcab95c163285a97fe356d2bdcde3c9380268805a384d063da09ccd9969cc3ff7431e60a8e9f869cd62faa0e356151b280bc526e577c2c538c9a724dc48bf88b70321d7e1eeedb3c4af706748c942e67bdabdb41bec2977b1523069e31e29b76300288f88a51b384b80cc2526f1679340ddec3881f5cd28b0378d9cd0a812b68dd3f68f7a23e1b54bee7466ac765cf38df04d67441dfa498c4bffc52045fa6d2dbcdbfa33dfaa77644ffccef0decdb6790c70a0d734ec287cc338cb5a909c0055189301169c4f7702c05c0911a27b16ef9ed934fa6a0ca7b13e413523422535647968030edc40cd73e7d6b345b7581f438316d68e3cd292b846d3f4f7c4862bc7e6b3fb89a27f6f60cd7db2e34ec9aae1013fe37acff8ad888cb9a593ef5e621eae5186c58b31dcfde22870e336d33f440f6b8d49a: +7ff62d4b3c4d99d342d4bb401d726b21e99f4ef592149fc311b68761f5567ff67fdfdb9eca29d3f01d9486d7e112ce03aa37b91326a4283b9c03999c5eda099a:7fdfdb9eca29d3f01d9486d7e112ce03aa37b91326a4283b9c03999c5eda099a:99c44c796572a4823fc6c3807730839173774c05dbfc1492ed0d00509a95a1de37274b3135ed0456a1718e576597dc13f2a2ab37a45c06cbb4a2d22afad4d5f3d90ab3d8da4dcdaa06d44f2219088401c5dceee26055c4782f78d7d63a380608e1bef89eeef338c2f0897da106fafce2fb2ebc5db669c7c172c9cfe77d3109d239fe5d005c8ee751511b5a88317c729b0d8b70b52f6bd3cda2fe865c77f36e4f1b635f336e036bd718bec90ee78a802811510c4058c1ba364017253aa842922e1dd7d7a0f0fc9c69e43fc4eaeffaaf1ae5fa5d2d73b43079617baba030923fe5b13d2c1c4fe6fac3f2db74e2020a734b6121a0302fce820ba0580ce6135348fdf0632e0008df03ee112168f5cfa0037a26a1f69b1f1317edf2a3ab367455a77e00691215d7aa3133c2159d3da2b134cf04f0defbf07a6064011e64dd14d4f8f064356655428804c2771a:058f79927fbf6178724815c7b11c63baaa90bcc15d7272be082f8a9141861c816433055f6cf6491424853f9ec78bb91ace913a93411b4e5ed58bc4ba5715c60a99c44c796572a4823fc6c3807730839173774c05dbfc1492ed0d00509a95a1de37274b3135ed0456a1718e576597dc13f2a2ab37a45c06cbb4a2d22afad4d5f3d90ab3d8da4dcdaa06d44f2219088401c5dceee26055c4782f78d7d63a380608e1bef89eeef338c2f0897da106fafce2fb2ebc5db669c7c172c9cfe77d3109d239fe5d005c8ee751511b5a88317c729b0d8b70b52f6bd3cda2fe865c77f36e4f1b635f336e036bd718bec90ee78a802811510c4058c1ba364017253aa842922e1dd7d7a0f0fc9c69e43fc4eaeffaaf1ae5fa5d2d73b43079617baba030923fe5b13d2c1c4fe6fac3f2db74e2020a734b6121a0302fce820ba0580ce6135348fdf0632e0008df03ee112168f5cfa0037a26a1f69b1f1317edf2a3ab367455a77e00691215d7aa3133c2159d3da2b134cf04f0defbf07a6064011e64dd14d4f8f064356655428804c2771a: +6cabadd03f8a2e6ebab96a74f80e18164e4d1b6baa678f5a82e25604af989aaf2a4a3179564194e00100c18bc35351d8b135bbae5b32b28fce1d7b6766ca4b32:2a4a3179564194e00100c18bc35351d8b135bbae5b32b28fce1d7b6766ca4b32:279f78cf3b9ccfc6e1b01e1a82f50ed172e9a8e1e702bb15661dd7dc3a456ff7a7a7fdfb081db3867079630c7f70fd753292ec60ecbf50632e9aa45b996505c66e6dc3c6ae892e21b6a8705e4bbae8f16a3378554b31fdb0139dcd15c96a8a7e4b88756a86d18db5dc74fd7691197dd88e2c7d5df52b049344cdc477c9cd7e89eda99ccfb1d00814d0152b9654df3279372ca5f18b1c946f2894a76b079ddb1c3cd61fbb969aeec9193a6b88fb7d136c07f9821e5c1074b4e93bcaf6fa14d0d1d7e1707589d77ec1337206e53a1f06cc26672ff95c13d5ff444766931ba30a0afdcdadd2098e9c41fd87a3f23cd16dbb0efbf8092ce33e327f42610990e1cee6cb8e54951aa081e69765ae4009aeed758e768de50c23d9a22b4a06dc4d19fc8cbd0cdef4c983461755d0a3b5d6a9c12253e09568339ff7e5f78c5fdf7ec89f9186a621a8c0eed11b67022e:4e65c6c1d493045e8a9250e397c1d1d30ffed24db66a8961aa458f8f0fcb760c39fe8657d7ab8f84000b96d519717cff71f926522c1efec7f8b2624eae55f60c279f78cf3b9ccfc6e1b01e1a82f50ed172e9a8e1e702bb15661dd7dc3a456ff7a7a7fdfb081db3867079630c7f70fd753292ec60ecbf50632e9aa45b996505c66e6dc3c6ae892e21b6a8705e4bbae8f16a3378554b31fdb0139dcd15c96a8a7e4b88756a86d18db5dc74fd7691197dd88e2c7d5df52b049344cdc477c9cd7e89eda99ccfb1d00814d0152b9654df3279372ca5f18b1c946f2894a76b079ddb1c3cd61fbb969aeec9193a6b88fb7d136c07f9821e5c1074b4e93bcaf6fa14d0d1d7e1707589d77ec1337206e53a1f06cc26672ff95c13d5ff444766931ba30a0afdcdadd2098e9c41fd87a3f23cd16dbb0efbf8092ce33e327f42610990e1cee6cb8e54951aa081e69765ae4009aeed758e768de50c23d9a22b4a06dc4d19fc8cbd0cdef4c983461755d0a3b5d6a9c12253e09568339ff7e5f78c5fdf7ec89f9186a621a8c0eed11b67022e: +0fa0c32c3ae34be51b92f91945405981a8e202488558a8e220c288c7d6a5532dd6aee62bd91fc9453635ffcc02b2f38dcab13285140380580ccdff0865df0492:d6aee62bd91fc9453635ffcc02b2f38dcab13285140380580ccdff0865df0492:53f44be0e5997ff07264cb64ba1359e2801def8755e64a2362bddaf597e672d021d34fface6d97e0f2b1f6ae625fd33d3c4f6e9ff7d0c73f1da8defb23f324975e921bb2473258177a16612567edf7d5760f3f3e3a6d26aaabc5fde4e2043f73fa70f128020933b1ba3b6bd69498e9503ea670f1ed880d3651f2e4c59e79cabc86e9b703394294112d5d8e213c317423b525a6df70106a9d658a262028b5f45100cb77d1150d8fe461eed434f241015f3276ad7b09a291b4a7f35e3c30051cbf13b1d4a7fa0c81a50f939e7c49673afdc87883c9e3e61f5a1df03755470fda74bf23ea88676b258a97a280d5f90b52b714b596035bae08c8d0fe6d94f8949559b1f27d7116cf59dd3cfbf18202a09c13f5c4fbc8d97225492887d32870c2297e34debd9876d6d01ac27a16b088b079079f2b20feb02537cda314c43cb2dca371b9df37ed11ec97e1a7a6993a:7e9ab85ee94fe4b35dcb545329a0ef25923de5c9dc23e7df1a7e77ab0dcfb89e03f4e785ca6429cb2b0df50da6230f733f00f33a45c4e576cd40bdb84f1ae00153f44be0e5997ff07264cb64ba1359e2801def8755e64a2362bddaf597e672d021d34fface6d97e0f2b1f6ae625fd33d3c4f6e9ff7d0c73f1da8defb23f324975e921bb2473258177a16612567edf7d5760f3f3e3a6d26aaabc5fde4e2043f73fa70f128020933b1ba3b6bd69498e9503ea670f1ed880d3651f2e4c59e79cabc86e9b703394294112d5d8e213c317423b525a6df70106a9d658a262028b5f45100cb77d1150d8fe461eed434f241015f3276ad7b09a291b4a7f35e3c30051cbf13b1d4a7fa0c81a50f939e7c49673afdc87883c9e3e61f5a1df03755470fda74bf23ea88676b258a97a280d5f90b52b714b596035bae08c8d0fe6d94f8949559b1f27d7116cf59dd3cfbf18202a09c13f5c4fbc8d97225492887d32870c2297e34debd9876d6d01ac27a16b088b079079f2b20feb02537cda314c43cb2dca371b9df37ed11ec97e1a7a6993a: +7b06f88026fa86f39fce2426f67cc5996bedd0cfc4b5ebb1b5e3edbb47e080aa3f1469ee6a2e7867e2e9012d402cf5a4861497c01df879a1deb1c539830b58de:3f1469ee6a2e7867e2e9012d402cf5a4861497c01df879a1deb1c539830b58de:71175d4e21721297d9176d817f4e785d9600d923f987fe0b26fd79d33a5ea5d1e818b71f0f92b8c73afddabdcc27f6d16e26aafa874cfd77a00e06c36b041487582bb933760f88b419127345776ea418f83522254fed33819bc5c95f8f8404cc144ebf1486c88515409d3433aaf519d9920f5256e629419e9a95580a35b069b8d25533dfcbc98ad36404a951808e01378c03266326d120046975fde07daef3266caacd821c1403499d7fdf17c033c8d8c3f28f162b5f09dfdaca06285f00c6cb986dfdf5151aa6639608b5b13e78d65a4368585b16138754fbd113835a686cd066c2b89bb0953c24d50e77bf0fc457c1e0fcf5d44da8db9a88f062be3b688d5cdcff1d1c00e81ec9d413882295b341fee8fa427dc109adeb5f284eec202f1bef115bf96b1782d3ccdeb682b69bf92d170c007d5df80e1ed962f677dc24a145a1e4e829e8dec0104e5f78365944:42f133e34e3eb7032a133ed781537ec62e44a5ce8381e5e0bf9e13a914a4b2c757811d6d3b1e86672424ea4230d10f7c610abb7069e61e319b4066a2bd7bc90071175d4e21721297d9176d817f4e785d9600d923f987fe0b26fd79d33a5ea5d1e818b71f0f92b8c73afddabdcc27f6d16e26aafa874cfd77a00e06c36b041487582bb933760f88b419127345776ea418f83522254fed33819bc5c95f8f8404cc144ebf1486c88515409d3433aaf519d9920f5256e629419e9a95580a35b069b8d25533dfcbc98ad36404a951808e01378c03266326d120046975fde07daef3266caacd821c1403499d7fdf17c033c8d8c3f28f162b5f09dfdaca06285f00c6cb986dfdf5151aa6639608b5b13e78d65a4368585b16138754fbd113835a686cd066c2b89bb0953c24d50e77bf0fc457c1e0fcf5d44da8db9a88f062be3b688d5cdcff1d1c00e81ec9d413882295b341fee8fa427dc109adeb5f284eec202f1bef115bf96b1782d3ccdeb682b69bf92d170c007d5df80e1ed962f677dc24a145a1e4e829e8dec0104e5f78365944: +c3f5e149968a24f4de9119531975f443015ccca305d7119ed4749e8bf6d94fc739aaccdb948a4038538a4588322f806bb129b5876c4bec51271afe4f49690045:39aaccdb948a4038538a4588322f806bb129b5876c4bec51271afe4f49690045:c46370e37f2e0cadcf93402f1f0cb048f52881ba750b7a43f56ab11ce348732fb57e7f9aaf8dfcbe455e14e983c248d026a27e7f148d5db5a53f94635702b895127771047a876d14107386c5e0ff8933345bbd7a936d990d33efa28c2ec4e4864ffd2ff576f7c88f954cfc1c459e883bb712dae3cdf6632066f1f4d13a509615b3360cadc5a307f23e52a51b40a6feebe0b18d0e9ee4e348f33cd81a8def222f6a59b12861d335bd9af85cc004be46f1d3a424f4870ae9dc587e5a4ade136b9370649348c33ac3bf1febeebffea37085ed59cac9d9e696470b234609e9a10a9d431ff91e69cb5135fd117ff58a36539744ebe70cea6973c00c7a4d57b62f4a7136d731b8e46ff18ec0ed69070031905075d8541d568cfce6eeb76242b7819a7b6a93552111bb88f165527cfa6966d39fcbe0a7dea008e39c7a3e577ab307cd1d0ea326833d52654e172955f3fcd4:5fa2b531677b00b85b0a313cbd479f55f4ab3ec5cfce5e454d2b74176ccc3399c899f9d6b51ed4c1e76185ac9fe730c4b4014044f7041185bc3c85722eb2ea02c46370e37f2e0cadcf93402f1f0cb048f52881ba750b7a43f56ab11ce348732fb57e7f9aaf8dfcbe455e14e983c248d026a27e7f148d5db5a53f94635702b895127771047a876d14107386c5e0ff8933345bbd7a936d990d33efa28c2ec4e4864ffd2ff576f7c88f954cfc1c459e883bb712dae3cdf6632066f1f4d13a509615b3360cadc5a307f23e52a51b40a6feebe0b18d0e9ee4e348f33cd81a8def222f6a59b12861d335bd9af85cc004be46f1d3a424f4870ae9dc587e5a4ade136b9370649348c33ac3bf1febeebffea37085ed59cac9d9e696470b234609e9a10a9d431ff91e69cb5135fd117ff58a36539744ebe70cea6973c00c7a4d57b62f4a7136d731b8e46ff18ec0ed69070031905075d8541d568cfce6eeb76242b7819a7b6a93552111bb88f165527cfa6966d39fcbe0a7dea008e39c7a3e577ab307cd1d0ea326833d52654e172955f3fcd4: +42305c9302f45ea6f87e26e2208fd94b3c4ad037b1b6c83cf6677aa1096a013c3b97b1f11ce45ba46ffbb25b76bfc5ad7b77f90cc69ed76115dea4029469d587:3b97b1f11ce45ba46ffbb25b76bfc5ad7b77f90cc69ed76115dea4029469d587:d110828d449198d675e74e8e39439fd15e75bf2cc1f430abfb245836885bafc420f754b89d2fbbf6dd3490792e7a4f766073cfe3b302d089831ace869e2730fde45c2121ec3ef217aa9c43fa7cc7e9ed0a01ad9f1d2fc3613638ca9fc193c98b37455bf5dbf8f38b64708dfdca6c21f0975f1017c5da5f6434bda9f033cec2a631ab50318e017b170b240bf01eb8b36c7e1cb59e7736ac34444208132a8f59e4f313d65d849c6a4fdf13e20ecaee3823e589a171b39b2489497b06e6ff58c2c9f1dc5d3aa3bd10e6443e22d42d07b783f79fd43a46e1cde314b663a95f7246dea131fcd46d1dc333c5454f86b2c4e2e424dea405cc2230d4dcd39a2eab2f92845cf6a7994192063f1202749ef52dcb96f2b79ed6a98118ca0b99ba2285490860eb4c61ab78b9ddc6acc7ad883fa5e96f9d029171223abf7573e36230e0a81f6c1311151473ee264f4b842e923dcb3b:18d05e5d01668e83f40fa3bbee28b388acf318d1b0b5ad668c672f345c8eda14c2f884cd2a9039459ce0810bc5b580fe70d3964a43edb49e73a6ff914bbf040cd110828d449198d675e74e8e39439fd15e75bf2cc1f430abfb245836885bafc420f754b89d2fbbf6dd3490792e7a4f766073cfe3b302d089831ace869e2730fde45c2121ec3ef217aa9c43fa7cc7e9ed0a01ad9f1d2fc3613638ca9fc193c98b37455bf5dbf8f38b64708dfdca6c21f0975f1017c5da5f6434bda9f033cec2a631ab50318e017b170b240bf01eb8b36c7e1cb59e7736ac34444208132a8f59e4f313d65d849c6a4fdf13e20ecaee3823e589a171b39b2489497b06e6ff58c2c9f1dc5d3aa3bd10e6443e22d42d07b783f79fd43a46e1cde314b663a95f7246dea131fcd46d1dc333c5454f86b2c4e2e424dea405cc2230d4dcd39a2eab2f92845cf6a7994192063f1202749ef52dcb96f2b79ed6a98118ca0b99ba2285490860eb4c61ab78b9ddc6acc7ad883fa5e96f9d029171223abf7573e36230e0a81f6c1311151473ee264f4b842e923dcb3b: +c57a43dcd7bab8516009546918d71ad459b7345efdca8d4f19929875c839d7222083b444236b9ab31d4e00c89d55c6260fee71ac1a47c4b5ba227404d382b82d:2083b444236b9ab31d4e00c89d55c6260fee71ac1a47c4b5ba227404d382b82d:a4f6d9c281cf81a28a0b9e77499aa24bde96cc1264374491c008294ee0af6f6e4bbb686396f59068d358e30fe9992db0c6f16680a1c71e27a4a907ac607d39bdc3258c7956482fb37996f4beb3e5051b8148019a1c256e2ee999ebc8ce64c54e07fedb4fbd8953ebd93b7d69ce5a0082edd6209d12d3619b4fd2eae916461f72a4ce727157251a19209bbff9fbdbd289436f3fcacc6b4e1318521a47839cba4b14f7d7a21e7b5d6b6a753d5804afcd2b1eb7779b92abab8afa8aa4fa51caec0b85dcd0fc2a0676036d3f56630a831ffeb502861dd89161c708a9c006c73c930ce5b94756426ff18aa112fb4eb9a68500b48d4eedbd4167b6ffd0a11d49443a173ce9d949436748fc0634f06bb08b8f3423f4463dba7b4d199b64df578117f0a2645f0b2a1e2ada27d286f76733f25b82ed1d48a5c3898d4ad621e50ed9060daad40a39532e4d1bf162ce36804d5d4e2d:1edef9bc036971f1fa88edf45393c802e6c1a1631c8a06871a09a320821dce40beca97e53a0361a955a4c6d60b8ca8e400c81340911ccb4f56284041cdbb1804a4f6d9c281cf81a28a0b9e77499aa24bde96cc1264374491c008294ee0af6f6e4bbb686396f59068d358e30fe9992db0c6f16680a1c71e27a4a907ac607d39bdc3258c7956482fb37996f4beb3e5051b8148019a1c256e2ee999ebc8ce64c54e07fedb4fbd8953ebd93b7d69ce5a0082edd6209d12d3619b4fd2eae916461f72a4ce727157251a19209bbff9fbdbd289436f3fcacc6b4e1318521a47839cba4b14f7d7a21e7b5d6b6a753d5804afcd2b1eb7779b92abab8afa8aa4fa51caec0b85dcd0fc2a0676036d3f56630a831ffeb502861dd89161c708a9c006c73c930ce5b94756426ff18aa112fb4eb9a68500b48d4eedbd4167b6ffd0a11d49443a173ce9d949436748fc0634f06bb08b8f3423f4463dba7b4d199b64df578117f0a2645f0b2a1e2ada27d286f76733f25b82ed1d48a5c3898d4ad621e50ed9060daad40a39532e4d1bf162ce36804d5d4e2d: +2dddb6b8fd04fa90ece1a709f8418f2e5d0c9c43afe7cfce19e6ad15a73476f78059de6a7c4776489ecc2e7d707ffce30285bf30a23f78d72db49cfd6ed0d492:8059de6a7c4776489ecc2e7d707ffce30285bf30a23f78d72db49cfd6ed0d492:474baa590a4cd72d5424e51d8257b3d44325bc4c5063a0033c86ebbe99ed7212184c19944d082a115379dd4cece973faa0bca6485bd25f3744a719e70aa0291e1b5a96e637c140616a98263357c76b6eb0083fe51414e386870d0fdc7dd9abe4ff6fb5bbf1e7b15dac3e08e2615f655c3104ceb32a4cc2c9e9c43cf282d346ac253ccc46b635ae040973b49735720ffb890469a567c5824e0c00d7ccd5509a718092a906461c4d6163eaf422418f5fc6e009fc3f529ac61a2f89bb8e0ed45d940c4c2331ff8d8e1d6d58d417d8fc2656a02e8701aee75aed918724eebe4a2cf4744c5c401e217023df68a6f6a0228bd05a679a697d8de7036b9ed269090d3c65486afb91e27954eb15b964665ede7ad008f12fb3a9d0e69c13b4254f43819e0818a4195f68b8a38ae81f3fcb1879c95ab4cd0ffc38e381089260cca967ace5a085b457ab5eb363852101377570f9ac9e38:c634ea7bf72e895a2e796e2834201415b8b45e05e045559284eb9052c0e84f62a5a9f0c9764f7576788c7228b19ef517c195497325a48a9344b147c12fd75509474baa590a4cd72d5424e51d8257b3d44325bc4c5063a0033c86ebbe99ed7212184c19944d082a115379dd4cece973faa0bca6485bd25f3744a719e70aa0291e1b5a96e637c140616a98263357c76b6eb0083fe51414e386870d0fdc7dd9abe4ff6fb5bbf1e7b15dac3e08e2615f655c3104ceb32a4cc2c9e9c43cf282d346ac253ccc46b635ae040973b49735720ffb890469a567c5824e0c00d7ccd5509a718092a906461c4d6163eaf422418f5fc6e009fc3f529ac61a2f89bb8e0ed45d940c4c2331ff8d8e1d6d58d417d8fc2656a02e8701aee75aed918724eebe4a2cf4744c5c401e217023df68a6f6a0228bd05a679a697d8de7036b9ed269090d3c65486afb91e27954eb15b964665ede7ad008f12fb3a9d0e69c13b4254f43819e0818a4195f68b8a38ae81f3fcb1879c95ab4cd0ffc38e381089260cca967ace5a085b457ab5eb363852101377570f9ac9e38: +5547f1004baedfce5cfc0850b05302374aad24f6163994ecd751df3af3c106207ce620787385ee1951ac49a77352ee0d6f8c5cd47df74e9e3216a6324fc7cf7f:7ce620787385ee1951ac49a77352ee0d6f8c5cd47df74e9e3216a6324fc7cf7f:a6c17eeb5b8066c2cd9a89667317a945a0c7c96996e77ae854c509c6cd0631e922ad04503af87a3c4628adafed7600d071c078a22e7f64bda08a362b38b26ca15006d38acf532d0dedea4177a2d33f06956d80e963848ec791b2762fa99449b4f1a1ed9b3f2580be3ac7d7f52fb14421d6222ba76f807750c6cbb0b16f0895fc73d9dfc587e1a9e5d1e58375fbab705b8f0c1fd7df8b3ad446f2f08459e7ed1af59556fbc966dc249c1cf604f3e677c8a09d4363608774bf3811bef0642748c55c516c7a580fa3499050acb30eed870d0d91174cb623e98c3ad121cf81f04e57d49b008424a98a31eeaaf5f38e000f903d48d215ed52f862d636a5a73607de85760167267efe30f8a26ebc5aa0c09f5b258d3361ca69d1d7ee07b59648179ab2170ec50c07f6616f216872529421a6334a4a1ed3d2671ef47bc9a92afb58314e832db8a9003408a0487503fe4f67770dd4b6:29df3ad589009c667baa5e72dabb4e53cb7876de4e7efe5cc21ead7fa878db57f97c1103ddb39a861eb88653c1d4ec3b4306e4584b47b8bc90423119e7e4af00a6c17eeb5b8066c2cd9a89667317a945a0c7c96996e77ae854c509c6cd0631e922ad04503af87a3c4628adafed7600d071c078a22e7f64bda08a362b38b26ca15006d38acf532d0dedea4177a2d33f06956d80e963848ec791b2762fa99449b4f1a1ed9b3f2580be3ac7d7f52fb14421d6222ba76f807750c6cbb0b16f0895fc73d9dfc587e1a9e5d1e58375fbab705b8f0c1fd7df8b3ad446f2f08459e7ed1af59556fbc966dc249c1cf604f3e677c8a09d4363608774bf3811bef0642748c55c516c7a580fa3499050acb30eed870d0d91174cb623e98c3ad121cf81f04e57d49b008424a98a31eeaaf5f38e000f903d48d215ed52f862d636a5a73607de85760167267efe30f8a26ebc5aa0c09f5b258d3361ca69d1d7ee07b59648179ab2170ec50c07f6616f216872529421a6334a4a1ed3d2671ef47bc9a92afb58314e832db8a9003408a0487503fe4f67770dd4b6: +3dd7203c237aefe9e38a201ff341490179905f9f100828da18fcbe58768b5760f067d7b2ff3a957e8373a7d42ef0832bcda84ebf287249a184a212a94c99ea5b:f067d7b2ff3a957e8373a7d42ef0832bcda84ebf287249a184a212a94c99ea5b:db28ed31ac04b0c2decee7a6b24fc9a082cc262ca7ccf2a247d6372ec3e9120ecedb4542ea593fea30335c5ab9dd318a3b4fd5834299cf3f53d9ef46137b273c390ec3c26a0b4470d0d94b77d82cae4b24587837b167bb7f8166710baeb3ee70af797316cb7d05fa57e468ae3f0bd449404d8528808b41fcca62f5e0a2aa5d8f3acab008cc5f6e5ab02777bdcde87f0a10ef06a4bb37fe02c94815cf76bfb8f5cdd865cc26dcb5cf492edfd547b535e2e6a6d8540956dcba62cfea19a9474406e934337e454270e01036ac45793b6b8aceda187a08d56a2ce4e98f42ea375b101a6b9fcb4231d171aa463eeb43586a4b82a387bcddaf71a80fd5c1f7292efc2bd8e70c11eaa817106061b6c461c4883d613cc06c7e2a03f73d90fc55cdc07265eefd36be72270383d6c676cae37c93691f1ae3d927b3a1cd963e4229757ae5231eea73a9f71515628305410ac2593b325cc631:4c036935a96abc0d050d907bedbe9946fb97439f039c742e051ccf09add7df44d17da98c2ca01bdc2424da1e4debf347f8fff48ac8030d2cc07f9575c044be04db28ed31ac04b0c2decee7a6b24fc9a082cc262ca7ccf2a247d6372ec3e9120ecedb4542ea593fea30335c5ab9dd318a3b4fd5834299cf3f53d9ef46137b273c390ec3c26a0b4470d0d94b77d82cae4b24587837b167bb7f8166710baeb3ee70af797316cb7d05fa57e468ae3f0bd449404d8528808b41fcca62f5e0a2aa5d8f3acab008cc5f6e5ab02777bdcde87f0a10ef06a4bb37fe02c94815cf76bfb8f5cdd865cc26dcb5cf492edfd547b535e2e6a6d8540956dcba62cfea19a9474406e934337e454270e01036ac45793b6b8aceda187a08d56a2ce4e98f42ea375b101a6b9fcb4231d171aa463eeb43586a4b82a387bcddaf71a80fd5c1f7292efc2bd8e70c11eaa817106061b6c461c4883d613cc06c7e2a03f73d90fc55cdc07265eefd36be72270383d6c676cae37c93691f1ae3d927b3a1cd963e4229757ae5231eea73a9f71515628305410ac2593b325cc631: +282775df9ebbd7c5a65f3a2b096e36ee64a8f8ea719da77758739e4e7476111da2b49646033a13937cad6b0e914e3cec54989c252ca5643d076555d8c55e56e0:a2b49646033a13937cad6b0e914e3cec54989c252ca5643d076555d8c55e56e0:14cc50c2973ea9d0187a73f71cb9f1ce07e739e049ec2b27e6613c10c26b73a2a966e01ac3be8b505aeaad1485c1c2a3c6c2b00f81b9e5f927b73bfd498601a7622e8544837aad02e72bf72196dc246902e58af253ad7e025e3666d3bfc46b5b02f0eb4a37c9554992abc8651de12fd813177379bb0ce172cd8aaf937f979642bc2ed7c7a430cb14c3cd3101b9f6b91ee3f542acdf017f8c2116297f4564768f4db95dad8a9bcdc8da4d8fb13ef6e2da0b1316d3c8c2f3ed836b35fe2fd33effb409e3bc1b0f85225d2a1de3bfc2d20563946475c4d7ca9fddbaf59ad8f8961d287ae7dd803e7af1fa612329b1bdc04e225600ae731bc01ae0925aed62ac50d46086f3646cf47b072f0d3b044b36f85cec729a8bb2b92883ca4dfb34a8ee8a0273b31af50982bb6131bfa11d55504b1f6f1a0a00438ca26d8ab4f48bcddc9d5a38851abede4151d5b70d720732a00abea2c8b979:15763973859402907d8dcb86adc24a2a168ba3abf2246173d6348afed51ef60b0c0edeff4e10bcef4c6e5778c8bc1f5e9ee0237373445b455155d23de127a20214cc50c2973ea9d0187a73f71cb9f1ce07e739e049ec2b27e6613c10c26b73a2a966e01ac3be8b505aeaad1485c1c2a3c6c2b00f81b9e5f927b73bfd498601a7622e8544837aad02e72bf72196dc246902e58af253ad7e025e3666d3bfc46b5b02f0eb4a37c9554992abc8651de12fd813177379bb0ce172cd8aaf937f979642bc2ed7c7a430cb14c3cd3101b9f6b91ee3f542acdf017f8c2116297f4564768f4db95dad8a9bcdc8da4d8fb13ef6e2da0b1316d3c8c2f3ed836b35fe2fd33effb409e3bc1b0f85225d2a1de3bfc2d20563946475c4d7ca9fddbaf59ad8f8961d287ae7dd803e7af1fa612329b1bdc04e225600ae731bc01ae0925aed62ac50d46086f3646cf47b072f0d3b044b36f85cec729a8bb2b92883ca4dfb34a8ee8a0273b31af50982bb6131bfa11d55504b1f6f1a0a00438ca26d8ab4f48bcddc9d5a38851abede4151d5b70d720732a00abea2c8b979: +4730a5cf9772d7d6665ba787bea4c95252e6ecd63ec62390547bf100c0a46375f9f094f7cc1d40f1926b5b22dce465784468b20ab349bc6d4fdf78d0042bbc5b:f9f094f7cc1d40f1926b5b22dce465784468b20ab349bc6d4fdf78d0042bbc5b:e7476d2e668420e1b0fadfbaa54286fa7fa890a87b8280e26078152295e1e6e55d1241435cc430a8693bb10cde4643f59cbfcc256f45f5090c909a14c7fc49d37bfc25af11e8f4c83f4c32d4aabf43b20fa382bb6622a1848f8ffc4dff3408bb4ec7c67a35b4cdaee5e279c0fc0a66093a9f36a60fdd65e6334a804e845c8530b6fda363b5640337d027243ccfb3c177f43e717896e46ead7f72ca06aa0ff1e77247121baf48be9a445f729ca1390fc46151cbd33fcbd7373f27a6ba55c92cbf6945b09b44b9a4e5800d403070ae66048997b2197f02181a097e563f9b9acc841139258a258bc610d3bd891637356b2edc8c184c35c65af91aaf7b1c16d74a5f5f862548139254ecf550631d5f8849afdb5b64cf366ff2633a93f3a18c39b5150245fb5f33c9e4e2d94af6963a70b88f9e7e519f8fa2a0f2e3749de883d0e6f052a949d0fc7153a8693f6d801d7352eb2f7a465c0e:552c7347bdfe131646ce0932d82a36d2c1b76d7c30ee890e0592e19f9d18b9a56f48d7a9b68c017da6b550c943af4a907baf317e419fbbc96f6cf4bfad42de00e7476d2e668420e1b0fadfbaa54286fa7fa890a87b8280e26078152295e1e6e55d1241435cc430a8693bb10cde4643f59cbfcc256f45f5090c909a14c7fc49d37bfc25af11e8f4c83f4c32d4aabf43b20fa382bb6622a1848f8ffc4dff3408bb4ec7c67a35b4cdaee5e279c0fc0a66093a9f36a60fdd65e6334a804e845c8530b6fda363b5640337d027243ccfb3c177f43e717896e46ead7f72ca06aa0ff1e77247121baf48be9a445f729ca1390fc46151cbd33fcbd7373f27a6ba55c92cbf6945b09b44b9a4e5800d403070ae66048997b2197f02181a097e563f9b9acc841139258a258bc610d3bd891637356b2edc8c184c35c65af91aaf7b1c16d74a5f5f862548139254ecf550631d5f8849afdb5b64cf366ff2633a93f3a18c39b5150245fb5f33c9e4e2d94af6963a70b88f9e7e519f8fa2a0f2e3749de883d0e6f052a949d0fc7153a8693f6d801d7352eb2f7a465c0e: +2770aadd1d123e9547832dfb2a837eba089179ef4f23abc4a53f2a714e423ee23c5fbb07530dd3a20ff35a500e3708926310fed8a899690232b42c15bd86e5dc:3c5fbb07530dd3a20ff35a500e3708926310fed8a899690232b42c15bd86e5dc:a5cc2055eba3cf6f0c6332c1f2ab5854870913b03ff7093bc94f335add44332231d9869f027d82efd5f1227144ab56e3222dc3ddccf062d9c1b0c1024d9b416dfa3ee8a7027923003465e0ffaefb75b9f29dc6bcf213adc5e318fd8ba93a7aa5bfb495de9d7c5e1a196cd3a2d7721f8ba785aa9052a1811c7fcc8f93932765059cab9c9b718945895ef26f3ac048d4cabf91a9e6aa83ac14d43156827837914eb763a23cba53f60f150f4b70203ec1833ff105849457a8da7327661fb23a554164e05fcf0146b10674964be6f6aa0acc94c41ad57180e5180d199bd9102f55d740e81789b15671bbd0670e6de5d97e1ae626d8a0ebc32c8fd9d24737274e47d2dd5941a272e72a598928ad109cde937bf248d57f5d2942983c51e2a89f8f054d5c48dfad8fcf1ffa97f7de6a3a43ca15fc6720efaec69f0836d84223f9776d111ec2bbc69b2dfd58be8ca12c072164b718cd7c246d64:f267715e9a84c7314f2d5869ef4ab8d2149a13f7e8e1c728c423906293b49ce6283454dd1c7b04741df2eabedc4d6ab1397dc95a679df04d2c17d66c79bb7601a5cc2055eba3cf6f0c6332c1f2ab5854870913b03ff7093bc94f335add44332231d9869f027d82efd5f1227144ab56e3222dc3ddccf062d9c1b0c1024d9b416dfa3ee8a7027923003465e0ffaefb75b9f29dc6bcf213adc5e318fd8ba93a7aa5bfb495de9d7c5e1a196cd3a2d7721f8ba785aa9052a1811c7fcc8f93932765059cab9c9b718945895ef26f3ac048d4cabf91a9e6aa83ac14d43156827837914eb763a23cba53f60f150f4b70203ec1833ff105849457a8da7327661fb23a554164e05fcf0146b10674964be6f6aa0acc94c41ad57180e5180d199bd9102f55d740e81789b15671bbd0670e6de5d97e1ae626d8a0ebc32c8fd9d24737274e47d2dd5941a272e72a598928ad109cde937bf248d57f5d2942983c51e2a89f8f054d5c48dfad8fcf1ffa97f7de6a3a43ca15fc6720efaec69f0836d84223f9776d111ec2bbc69b2dfd58be8ca12c072164b718cd7c246d64: +4fdab7c1600e70114b11f533242376af7614b4d5da046ac4bedea21d8a361598a25c9a94d6e4ecd95a4bd6805f762eb1c457a8d45d243238b1839cbba8f441cc:a25c9a94d6e4ecd95a4bd6805f762eb1c457a8d45d243238b1839cbba8f441cc:da405890d11a872c119dab5efcbff61e931f38eccca457edc626d3ea29ed4fe3154fafec1444da74343c06ad90ac9d17b511bcb73bb49d90bafb7c7ea800bd58411df1275c3cae71b700a5dab491a4261678587956aa4a219e1ac6dd3fb2cb8c46197218e726dc7ed234526a6b01c0d72cb93ab3f4f38a08e5940b3f61a72ad2789a0532000fac1d2d2e3ad632ac8b62bb3ff5b99d53597bf4d44b19674924df9b3db3d0253f74627ccab30031c85e291c58b5fa9167522a46746fc307036745d4f9817786e5d300e6c5d503125fea01dec3e3fedbf3861ca2627a0518fb2b24e5a7a014178719e9b345f7b249ce3a413280c8deb674f59a25be92a8ab6400c7c52b0728ae34e22b2ec200c1cbaba2ccd8af29249d17af60c36007a722fc80258a7bebab1cdaad7462a8b7588c2f7e27c6d07afcf60117fed11bd6859e75e3b4fcee3981881e95dd116827dd4b369af069d3c8f2676f8a:5075c090cfbeb6b01802af7f4da5aa4f434d5ee2f3530eebb75c85e08621f83edc08aa96693894a4277633ba81e19e9e55af5c495daa5e1a6f8cbb79c01c7207da405890d11a872c119dab5efcbff61e931f38eccca457edc626d3ea29ed4fe3154fafec1444da74343c06ad90ac9d17b511bcb73bb49d90bafb7c7ea800bd58411df1275c3cae71b700a5dab491a4261678587956aa4a219e1ac6dd3fb2cb8c46197218e726dc7ed234526a6b01c0d72cb93ab3f4f38a08e5940b3f61a72ad2789a0532000fac1d2d2e3ad632ac8b62bb3ff5b99d53597bf4d44b19674924df9b3db3d0253f74627ccab30031c85e291c58b5fa9167522a46746fc307036745d4f9817786e5d300e6c5d503125fea01dec3e3fedbf3861ca2627a0518fb2b24e5a7a014178719e9b345f7b249ce3a413280c8deb674f59a25be92a8ab6400c7c52b0728ae34e22b2ec200c1cbaba2ccd8af29249d17af60c36007a722fc80258a7bebab1cdaad7462a8b7588c2f7e27c6d07afcf60117fed11bd6859e75e3b4fcee3981881e95dd116827dd4b369af069d3c8f2676f8a: +264504604e70d72dc4474dbb34913e9c0f806dfe18c7879a41762a9e4390ec61eb2b518ce7dc71c91f3665581651fd03af84c46bf1fed2433222353bc7ec511d:eb2b518ce7dc71c91f3665581651fd03af84c46bf1fed2433222353bc7ec511d:901d70e67ed242f2ec1dda813d4c052cfb31fd00cfe5446bf3b93fdb950f952d94ef9c99d1c264a6b13c3554a264beb97ed20e6b5d66ad84db5d8f1de35c496f947a23270954051f8e4dbe0d3ef9ab3003dd47b859356cecb81c50affa68c15dadb5f864d5e1bb4d3bada6f3aba1c83c438d79a94bfb50b43879e9cef08a2bfb22fad943dbf7683779746e31c486f01fd644905048b112ee258042153f46d1c7772a0624bcd6941e9062cfda75dc8712533f4057335c298038cbca29ebdb560a295a88339692808eb3481fd9735ea414f620c143b2133f57bb64e44778a8ca70918202d157426102e1dfc0a8f7b1ae487b74f02792633154dfe74caa1b7088fda22fa8b9bc354c585f1567706e2955493870f54169e0d7691159df43897961d24a852ea970c514948f3b48f71ee586e72ec78db820f253e08db84f6f312c4333bd0b732fe75883507783e9a1fd4fbab8e5870f9bf7ad58aa:eea439a00f7e459b402b835150a779eed171ab971bd1b58dcc7f9386dadd583de8dc69e267121dde41f0f9493d450b16219cdf3c22f09482ce402fe17ca49e08901d70e67ed242f2ec1dda813d4c052cfb31fd00cfe5446bf3b93fdb950f952d94ef9c99d1c264a6b13c3554a264beb97ed20e6b5d66ad84db5d8f1de35c496f947a23270954051f8e4dbe0d3ef9ab3003dd47b859356cecb81c50affa68c15dadb5f864d5e1bb4d3bada6f3aba1c83c438d79a94bfb50b43879e9cef08a2bfb22fad943dbf7683779746e31c486f01fd644905048b112ee258042153f46d1c7772a0624bcd6941e9062cfda75dc8712533f4057335c298038cbca29ebdb560a295a88339692808eb3481fd9735ea414f620c143b2133f57bb64e44778a8ca70918202d157426102e1dfc0a8f7b1ae487b74f02792633154dfe74caa1b7088fda22fa8b9bc354c585f1567706e2955493870f54169e0d7691159df43897961d24a852ea970c514948f3b48f71ee586e72ec78db820f253e08db84f6f312c4333bd0b732fe75883507783e9a1fd4fbab8e5870f9bf7ad58aa: +2ca7447a3668b748b1fd3d52d2080d30e34d397bb2846caf8f659ac168788ca5ab331cd40a31d0173c0c8c1c17002532807bf89e3edb6d34c2dd8294632b9fbc:ab331cd40a31d0173c0c8c1c17002532807bf89e3edb6d34c2dd8294632b9fbc:a82bcd9424bffda0f2f5e9eae17835dbe468f61b785aab82934737a91c5f602cb7c617cdffe87cad726a4972e15a7b8ee147f062d2a5a4d89706b571fa8aa2b95981c78abeaaae86203fa2c0e07297406ea8c27111a86dbe1d5a7c3b7ae930904d9890f6d4abebd1412a73ad5feea64acf065d3e63b5cbe20cf20bbd2d8b94f9053ed5f66633482530124446605918de66455e8cf4b101a127233c4e27d5d55bf95bd3195d0340d43531fc75faf8dded5275bf89750de838fd10c31745be4ca41fa871cb0f9b016706a1a7e3c44bb90ac7a8ad51e272389292fd6c98ad7a069e76e3f5f3e0cc770b9e9b35a765d0d93712d7cdabd17e5d01dd8183af4ad9365db0a0fa41381fce60a081df1c5ab0f8c18f95a7a8b582dfff7f149ea579df0623b33b7508f0c663f01e3a2dcd9dfbee51cc615220fdaffdab51bdae42cb9f7fa9e3b7c69cc8ada5ccd642529ba514fdc54fcf2720b8f5d08b95:f93ada15ae9cd2b54f26f86f0c28392aed5eb6b6b44d01a4e33a54e7da37c38e8d53366f73fd85be642e4ec81236d163f0d025e76c8bbdd65d43df49f09c1f01a82bcd9424bffda0f2f5e9eae17835dbe468f61b785aab82934737a91c5f602cb7c617cdffe87cad726a4972e15a7b8ee147f062d2a5a4d89706b571fa8aa2b95981c78abeaaae86203fa2c0e07297406ea8c27111a86dbe1d5a7c3b7ae930904d9890f6d4abebd1412a73ad5feea64acf065d3e63b5cbe20cf20bbd2d8b94f9053ed5f66633482530124446605918de66455e8cf4b101a127233c4e27d5d55bf95bd3195d0340d43531fc75faf8dded5275bf89750de838fd10c31745be4ca41fa871cb0f9b016706a1a7e3c44bb90ac7a8ad51e272389292fd6c98ad7a069e76e3f5f3e0cc770b9e9b35a765d0d93712d7cdabd17e5d01dd8183af4ad9365db0a0fa41381fce60a081df1c5ab0f8c18f95a7a8b582dfff7f149ea579df0623b33b7508f0c663f01e3a2dcd9dfbee51cc615220fdaffdab51bdae42cb9f7fa9e3b7c69cc8ada5ccd642529ba514fdc54fcf2720b8f5d08b95: +494ea9bcce26885b7d17d1fc114448f239f0ce46e5f247b4c999fa86296924726901e5efae57536ba5fdd96b59657359065f25d391a1aa8cdc0d38bb5d53c139:6901e5efae57536ba5fdd96b59657359065f25d391a1aa8cdc0d38bb5d53c139:3badbfa5f5a8aa2cce0a60e686cdce654d24452f98fd54872e7395b39464380a0e185557ea134d095730864f4254d3dd946970c10c804fcc0899dfa024205be0f80b1c75449523324fe6a0751e47b4ff4822b8c33e9eaf1d1d96e0de3d4acd89696b7fcc03d49f92f82b9725700b350db1a87615369545561b8599f5ea920a310a8bafc0e8d7468cbf6f3820e943594afdd5166e4e3309dddd7694ef67e694f34fc62724ff96ac3364176f34e8a02b4cf569db5b8f77d58512aedabf0bcd1c2df12db3a9473f948c5c3243309aae46c49efd088b60f31a8a72ad7e5a35acc5d89fa66807eb5d3ba9cdf08d4753cb85089ee36f5c96b432b6928352afad58012225d6157f9e3611426df921b6d1d8374628a63031e9ffb90e42ffbba021f174f68503155430152c9155dc98ffa26c4fab065e1f8e4622c2f28a8cb043110b617441140f8e20adc16f799d1d5096b1f50532be5042d21b81ea46c7:548a093a680361b7dc56f14503b55eeec3b3f4fd4ca99d6aedce0830f7f4ae2f7328539b34c48fc9760922333dae9c7c017e7db73b8faa6c06be05e347992b063badbfa5f5a8aa2cce0a60e686cdce654d24452f98fd54872e7395b39464380a0e185557ea134d095730864f4254d3dd946970c10c804fcc0899dfa024205be0f80b1c75449523324fe6a0751e47b4ff4822b8c33e9eaf1d1d96e0de3d4acd89696b7fcc03d49f92f82b9725700b350db1a87615369545561b8599f5ea920a310a8bafc0e8d7468cbf6f3820e943594afdd5166e4e3309dddd7694ef67e694f34fc62724ff96ac3364176f34e8a02b4cf569db5b8f77d58512aedabf0bcd1c2df12db3a9473f948c5c3243309aae46c49efd088b60f31a8a72ad7e5a35acc5d89fa66807eb5d3ba9cdf08d4753cb85089ee36f5c96b432b6928352afad58012225d6157f9e3611426df921b6d1d8374628a63031e9ffb90e42ffbba021f174f68503155430152c9155dc98ffa26c4fab065e1f8e4622c2f28a8cb043110b617441140f8e20adc16f799d1d5096b1f50532be5042d21b81ea46c7: +00d735ebaee75dd579a40dfd82508274d01a1572df99b811d5b01190d82192e4ba02517c0fdd3e2614b3f7bf99ed9b492b80edf0495d230f881730ea45bc17c4:ba02517c0fdd3e2614b3f7bf99ed9b492b80edf0495d230f881730ea45bc17c4:59c0b69af95d074c88fdc8f063bfdc31b5f4a9bc9cecdffa8128e01e7c1937dde5eb0570b51b7b5d0a67a3555b4cdce2bca7a31a4fe8e1d03ab32b4035e6dadbf1532059ee01d3d9a7633a0e706a1154cab22a07cd74c06a3cb601244cf3cf35a35c3100ba47f31372a2da65dcff0d7a80a1055d8aa99212e899aad7f02e949e6fee4d3c9cefa85069eaff1f6ad06fc300c871ab82b2bedb934d20875c2a263242cdb7f9be192a8710b24c7ea98d43daec8baa5553c678a38f0e0adf7d3ff2dcc799a1dbad6eab1c3d9458a9db922f02e75cfab9d65c7336dae71895d5bb15cac203f2b38b9996c410f8655ad22d3c091c20b7f926d45e780128f19747462abc5c58932fbb9e0bc62d53868802f1b083f183b8a1f9434986d5cf97c04e2f3e145730cba98779c7fed0cab1c05d5e4653c6c3f6736260bc78ee4372862ffe9e90371d762c7432781f35ced884a4baca05653ef25f25a6f3d5628308:dcdc54611937d2bd06cacd9818b3be15ce7425427a75f50d197a337a3b8ba6714ef48866f243bd5ac7415e914517a2c1c5a953f432b99db0e620d64f74eb850559c0b69af95d074c88fdc8f063bfdc31b5f4a9bc9cecdffa8128e01e7c1937dde5eb0570b51b7b5d0a67a3555b4cdce2bca7a31a4fe8e1d03ab32b4035e6dadbf1532059ee01d3d9a7633a0e706a1154cab22a07cd74c06a3cb601244cf3cf35a35c3100ba47f31372a2da65dcff0d7a80a1055d8aa99212e899aad7f02e949e6fee4d3c9cefa85069eaff1f6ad06fc300c871ab82b2bedb934d20875c2a263242cdb7f9be192a8710b24c7ea98d43daec8baa5553c678a38f0e0adf7d3ff2dcc799a1dbad6eab1c3d9458a9db922f02e75cfab9d65c7336dae71895d5bb15cac203f2b38b9996c410f8655ad22d3c091c20b7f926d45e780128f19747462abc5c58932fbb9e0bc62d53868802f1b083f183b8a1f9434986d5cf97c04e2f3e145730cba98779c7fed0cab1c05d5e4653c6c3f6736260bc78ee4372862ffe9e90371d762c7432781f35ced884a4baca05653ef25f25a6f3d5628308: +8c34b905440b61911d1d8137c53d46a1a76d4609af973e18eb4c5709295627bbb69a8b2fdf5c20e734c2ffb294bc8ae1011d664f11afe7fbc471925cf72fa99d:b69a8b2fdf5c20e734c2ffb294bc8ae1011d664f11afe7fbc471925cf72fa99d:30b57a389b48a0beb1a48432bff6b314bded79c4a1763a5acb57cea1bfb4c6d016cf090f5bd05bbd114e33ae7c17782dfa264f46c45f8c599c603016fe9ff05b6b5a99e92fe713a4cd5c41b292ed2bb2e9cf33a440542e821ec82cbf665c3f02e3dc337d7fdb58e31b27cb2954541468814698510df18c85c81fad12db11ec6b966f4930da5646b991db97445097da30dab61cda53a41083cb96add19de6c5eec323bca9d3530e38c00b35af7360077601be6ac97f3030f930a27b90fe8b6911bae389065adc15e1882300e2a003274d23182d5efd5ba4b9130c07bd5c65fecb8b5cb7eb38836b318befdfd77de4d6ca0181f77ae5740891683225f549dd8426145c97c5818c319f7ab2d868e1a41ceab64c085116069897bf2ca3667652406155ed0646431b6de1ccc03b4279ae4d326679265dce82048e7298e1f87fcec0768ac0f5d8ff84f7210be54d411af8edea7217f4e59413121e148c60da:3e0b72073dc9375eedcca6c4fc1cd315938a050c92716bd2284f4629a962beec0b7d7cf16ab923d58f5b90d3901a8e5c75c8f17dab9998e007d8c49511973d0e30b57a389b48a0beb1a48432bff6b314bded79c4a1763a5acb57cea1bfb4c6d016cf090f5bd05bbd114e33ae7c17782dfa264f46c45f8c599c603016fe9ff05b6b5a99e92fe713a4cd5c41b292ed2bb2e9cf33a440542e821ec82cbf665c3f02e3dc337d7fdb58e31b27cb2954541468814698510df18c85c81fad12db11ec6b966f4930da5646b991db97445097da30dab61cda53a41083cb96add19de6c5eec323bca9d3530e38c00b35af7360077601be6ac97f3030f930a27b90fe8b6911bae389065adc15e1882300e2a003274d23182d5efd5ba4b9130c07bd5c65fecb8b5cb7eb38836b318befdfd77de4d6ca0181f77ae5740891683225f549dd8426145c97c5818c319f7ab2d868e1a41ceab64c085116069897bf2ca3667652406155ed0646431b6de1ccc03b4279ae4d326679265dce82048e7298e1f87fcec0768ac0f5d8ff84f7210be54d411af8edea7217f4e59413121e148c60da: +77a83e18c9f000eeff7deeac959ecba2206c0aa39d2f0e2aed5729482a7a022962b1b316135596bfbca6037ed847c61fb7f09fa36ce90abb7789b86f768b59dd:62b1b316135596bfbca6037ed847c61fb7f09fa36ce90abb7789b86f768b59dd:f3d5fa2acaefd858f1df26e03059cdcbc2468ad74afc993d0db9c4cde4113f8d55c7da71d38ba06520531c61fddb5f33d5f0353be2376e580711be45c0a30b1fa01b55e228c6fa35e3f95b67909fc7df3fd464d93d661a926f9d11f7550c17fbcc3496526e8f10e0c8916677b2be5b319b688f21e81aaa9482e5c93e64ce8c437b9c1e14fefed70a3fee568811dc31cadab3d5b220254465336dc4d97a3bd096b5e065e0cfbe82849e2c1905aca486533f0da7a61f1e9a55b8e2a83262deeb59f2b13d3a8aef5700845b83b25ae2183c0ddac0ce42f8d25674cb0d0d220a6de7c1858bb07d59a3372344d944602aa451d2b937db0fe6feca0beba81721fc361ea7509e2b6d397e1c191b56f54ab436d0d27ab4c061bd661ad1a4452387e8735754d07fa7ef4d4548b172582425b299046e6301b5ba6b914418f149cf722e10bde2e0d41700f12c8429fc897b7819da92292240cd45565458c9a7b29c12:1eaad8420ac12c99ac1ff4476678e3cbbe94da6a797f174664d5ee0f641433fb1e7cb2f5613e10805df8654cd8e0d45d96230932bc7f20b04eae836435134309f3d5fa2acaefd858f1df26e03059cdcbc2468ad74afc993d0db9c4cde4113f8d55c7da71d38ba06520531c61fddb5f33d5f0353be2376e580711be45c0a30b1fa01b55e228c6fa35e3f95b67909fc7df3fd464d93d661a926f9d11f7550c17fbcc3496526e8f10e0c8916677b2be5b319b688f21e81aaa9482e5c93e64ce8c437b9c1e14fefed70a3fee568811dc31cadab3d5b220254465336dc4d97a3bd096b5e065e0cfbe82849e2c1905aca486533f0da7a61f1e9a55b8e2a83262deeb59f2b13d3a8aef5700845b83b25ae2183c0ddac0ce42f8d25674cb0d0d220a6de7c1858bb07d59a3372344d944602aa451d2b937db0fe6feca0beba81721fc361ea7509e2b6d397e1c191b56f54ab436d0d27ab4c061bd661ad1a4452387e8735754d07fa7ef4d4548b172582425b299046e6301b5ba6b914418f149cf722e10bde2e0d41700f12c8429fc897b7819da92292240cd45565458c9a7b29c12: +73b03373ef1fd849005ecd6270dd9906f19f4439e40376cdbc520902bc976812663719e08ba3ba1666f6069a3f54991866b18cc6be41991b02eb3026ff9e155f:663719e08ba3ba1666f6069a3f54991866b18cc6be41991b02eb3026ff9e155f:d5c2deaba795c30aba321bc7de6996f0d90e4d05c747fb4dae8f3451895def6e16e72f38eace756f36635f8fb0b72a3a0c1f54663817a94d4fd346f835ab0e657f001a6f2cecb86d0825bd02639254f7f7f38ca99dbb86c64a633f73baf933aae3563281f4005e2d0e7cec9fbde8e588a957e211068be65b3d3d35bf4e8d5bb3478333df9ced9b2abaf48697994a145e9321499fc5ee560f4fbb6849e1ae8eb3d1de0083a21a03f6a6b28176f0130d3895e50e75e3d7d0947a7bc2c5b9ff69895d27791442ba8d0f2180712b567f712ea912f3b0d92c19342e0106ff1d87b46ad33af300b90855ba9769d366e79425d98e4de19905a04577707cbe625b84691781cd26bf62260b4a8bd605f77af6f970e1b3a112e8918344bd0d8d2e41dfd2ce9895b0246e50887aa3a577ff73be4b6ae60feb0ca36f6a5f8171ed209e5c566529c0940d9b4bd744ccee56e54a9a0c6e4da520dd315c2872b02db563703e:a40abe98fc69da8a1ff9ff5c2cca93632e975980ee8b82c3c376022d6524ab736d01b072f2b681b5f1cd3ea067012ed6d074e949c42327a366caa9e4750a3c08d5c2deaba795c30aba321bc7de6996f0d90e4d05c747fb4dae8f3451895def6e16e72f38eace756f36635f8fb0b72a3a0c1f54663817a94d4fd346f835ab0e657f001a6f2cecb86d0825bd02639254f7f7f38ca99dbb86c64a633f73baf933aae3563281f4005e2d0e7cec9fbde8e588a957e211068be65b3d3d35bf4e8d5bb3478333df9ced9b2abaf48697994a145e9321499fc5ee560f4fbb6849e1ae8eb3d1de0083a21a03f6a6b28176f0130d3895e50e75e3d7d0947a7bc2c5b9ff69895d27791442ba8d0f2180712b567f712ea912f3b0d92c19342e0106ff1d87b46ad33af300b90855ba9769d366e79425d98e4de19905a04577707cbe625b84691781cd26bf62260b4a8bd605f77af6f970e1b3a112e8918344bd0d8d2e41dfd2ce9895b0246e50887aa3a577ff73be4b6ae60feb0ca36f6a5f8171ed209e5c566529c0940d9b4bd744ccee56e54a9a0c6e4da520dd315c2872b02db563703e: +eab179e41ed5c889ffe6aabdc054faf1307c395e46e313e17a14fe01023ffa3086f34746d3f7a01ddbe322f1aca56d22856d38733a3a6900bb08e776450ec803:86f34746d3f7a01ddbe322f1aca56d22856d38733a3a6900bb08e776450ec803:971095cebe5031530224387c5c31966e389b8566390054cf45264b44e18964b7be52c33c4ffb259af16283438fa15dd66bc7791b7533ef10cb0beab524a6437626f4cc74512851adcc2fb129055a482c61107383fb7c5241831d5551634eef0dc0b8f9053a00971aa8fa1ae0898e4b481b6707e97c0f942040b339d92fc17bbade74675af243d8b2dafb15b1db55d12415b85f3037291930ab61600ba3431f8eb425be4491614728af101e81c091f348bc5ffd1bde6ae6cad5c15b3aa7358078cc4effb54a86e7f0e0c55e4cfe0a54605ed443fdf2aaba016585da617e77341d52889d75dd540d39fe8b7993ed705cfddea0cb0d5a731d6bfcdb816afaff47e963eedebdf241af5593353d6d401a34f029a8cdeb1904cc2caa4f9635cc2ba6b7b1a29da625ffc383be2f5a8f1fa4f39b2d4b4f4c2d8838ce258a04d4a120493fdf07f68c0ffd1c16b768a35c55fea2cac696b5c20efc10865cde8a64627dcd:143cb28027c2f82e375e5f340e7fe6e60ce7bd51000b49c74168af85e26ed2ed630ed2672090164cc54b052da694ebdd21a21b3053f4dcfd7895ea5f6c8aa80d971095cebe5031530224387c5c31966e389b8566390054cf45264b44e18964b7be52c33c4ffb259af16283438fa15dd66bc7791b7533ef10cb0beab524a6437626f4cc74512851adcc2fb129055a482c61107383fb7c5241831d5551634eef0dc0b8f9053a00971aa8fa1ae0898e4b481b6707e97c0f942040b339d92fc17bbade74675af243d8b2dafb15b1db55d12415b85f3037291930ab61600ba3431f8eb425be4491614728af101e81c091f348bc5ffd1bde6ae6cad5c15b3aa7358078cc4effb54a86e7f0e0c55e4cfe0a54605ed443fdf2aaba016585da617e77341d52889d75dd540d39fe8b7993ed705cfddea0cb0d5a731d6bfcdb816afaff47e963eedebdf241af5593353d6d401a34f029a8cdeb1904cc2caa4f9635cc2ba6b7b1a29da625ffc383be2f5a8f1fa4f39b2d4b4f4c2d8838ce258a04d4a120493fdf07f68c0ffd1c16b768a35c55fea2cac696b5c20efc10865cde8a64627dcd: +fbf146ebd51075570ec51ac410ae9f391db75b610ada6362b4dbd949656cfb66be7c2f5b21d746c8ea3245ce6f268e9da74e00fa85c9c475260c68fa1af6361f:be7c2f5b21d746c8ea3245ce6f268e9da74e00fa85c9c475260c68fa1af6361f:cd7ad4f17fcff73acc402dc102d09079b29aaf2a0f4b27cf6beeb1e2b23d19ab47deb3ae1becd68861ea279c46691738f4fff47c43047c4f8b56b6bbcc3fde0723d44120dcd307a6310dc4f366b8f3cd52db19b8266a487f7872391c45fe0d3248a7abf2c20022d3769547f683067dcc363cd22fd7cda3cadc15804056f0e2aa2b795008c598be7a961805e6df291ba3041c47ff5640275f46e6ae82092d21abcbcfba11e730216008822de3ce462400596da79f7ae5d1df8389112ad98868fa94fb0546bfe6a67aa8d28c4d32072d2eadd6256255f18c2382e662dfa922a680e06a43622c4871d27d1807f7b2703070c83db8dd929c06038b2183cb8e2b9ec4c778d7ecf9e9ffac77fa7737b055feac2e7982aeeec0b72f1bbca2424e1a844bbac79cb2e7400f81dc449d0560b521a7c16bb4167e6696586058a9b8ed2e5116690b77f2a17e5c0b16a83dcbd2e24552293e258b32ba7f844944379342698627:6768006fe0f201b217dd10eb05d4b82adcfeb2ecfc8373c3308f4150394811eb60491881a2e53d1289d96478e18a64c34b2a19832cdccfd96a2e4a0c469fdc0bcd7ad4f17fcff73acc402dc102d09079b29aaf2a0f4b27cf6beeb1e2b23d19ab47deb3ae1becd68861ea279c46691738f4fff47c43047c4f8b56b6bbcc3fde0723d44120dcd307a6310dc4f366b8f3cd52db19b8266a487f7872391c45fe0d3248a7abf2c20022d3769547f683067dcc363cd22fd7cda3cadc15804056f0e2aa2b795008c598be7a961805e6df291ba3041c47ff5640275f46e6ae82092d21abcbcfba11e730216008822de3ce462400596da79f7ae5d1df8389112ad98868fa94fb0546bfe6a67aa8d28c4d32072d2eadd6256255f18c2382e662dfa922a680e06a43622c4871d27d1807f7b2703070c83db8dd929c06038b2183cb8e2b9ec4c778d7ecf9e9ffac77fa7737b055feac2e7982aeeec0b72f1bbca2424e1a844bbac79cb2e7400f81dc449d0560b521a7c16bb4167e6696586058a9b8ed2e5116690b77f2a17e5c0b16a83dcbd2e24552293e258b32ba7f844944379342698627: +dff0eb6b426dea2fd33c1d3fc24df9b31b486facb7edb8502954a3e8da99d9fdc245085ece69fb9aa560d0c27fdb634f7a840d41d8463660fbe82483b0f3cc3a:c245085ece69fb9aa560d0c27fdb634f7a840d41d8463660fbe82483b0f3cc3a:e7c9e313d86160f4c74aa0ae07369ee22b27f81b3f69097affae28dae48483fb52a5c062306b59610f5cdbff6332b1960cd6f2b8f7b41578c20f0bc9637a0fdfc739d61f699a573f1c1a0b49294506cf4487965e5bb07bbf81803cb3d5cb3829c66c4bee7fc800ede216150934d277dea50edb097b992f11bb669fdf140bf6ae9fec46c3ea32f888fde9d154ea84f01c51265a7d3fef6eefc1ccdbffd1e2c897f05546a3b1ca11d9517cd667c660ec3960f7a8e5e80202a78d3a388b92f5c1dee14ae6acf8e17c841c9557c35a2eeced6e6af6372148e483ccd06c8fe344924e1019fb91cbf7941b9a176a073415867210670410c5dbd0ac4a50e6c0a509ddfdc555f60d696d41c77db8e6c84d5181f872755e64a721b061fcd68c463db4d32c9e01ea501267de22879d7fc12c8ca0379edb45abaa6e64dda2af6d40ccf24fbebad7b5a8d3e52007945ecd3ddc1e3efeb522581ac80e98c863ba0c590a3ed95cd1:6b48b10f545ddb7a89cd5829f4e5b20146cf6bc96e550d06f65de8bdae7ccdded26cd630f86c9266bccf88e924033e04f83a54f8290d7f734cf8673cca8f9703e7c9e313d86160f4c74aa0ae07369ee22b27f81b3f69097affae28dae48483fb52a5c062306b59610f5cdbff6332b1960cd6f2b8f7b41578c20f0bc9637a0fdfc739d61f699a573f1c1a0b49294506cf4487965e5bb07bbf81803cb3d5cb3829c66c4bee7fc800ede216150934d277dea50edb097b992f11bb669fdf140bf6ae9fec46c3ea32f888fde9d154ea84f01c51265a7d3fef6eefc1ccdbffd1e2c897f05546a3b1ca11d9517cd667c660ec3960f7a8e5e80202a78d3a388b92f5c1dee14ae6acf8e17c841c9557c35a2eeced6e6af6372148e483ccd06c8fe344924e1019fb91cbf7941b9a176a073415867210670410c5dbd0ac4a50e6c0a509ddfdc555f60d696d41c77db8e6c84d5181f872755e64a721b061fcd68c463db4d32c9e01ea501267de22879d7fc12c8ca0379edb45abaa6e64dda2af6d40ccf24fbebad7b5a8d3e52007945ecd3ddc1e3efeb522581ac80e98c863ba0c590a3ed95cd1: +9f32958c7679b90fd5036056a75ec2eb2f56ec1effc7c012461dc89a3a1674201d7269dcb6d1f584e662d4ce251de0aba290ef78b97d448afb1e5333f1976d26:1d7269dcb6d1f584e662d4ce251de0aba290ef78b97d448afb1e5333f1976d26:a56ba86c71360504087e745c41627092ad6b49a71e9daa5640e1044bf04d4f071ad728779e95d1e2460584e6f0773545da82d4814c9189a120f12f3e3819813e5b240d0f26436f70ee353b4d20cea54a1460b5b8f1008d6f95f3aa2d8f1e908fced50d624e3a096938b9353854b96da463a2798a5a312ec790842c10c446e3350c764bf5c972593b9987bf23256daa8894d47f22e85b97607e66fc08a12c789c4746080368d321bb9015a1155b65523ad8e99bb989b44eac756b0734acd7c6357c70b59743246d1652d91b0f9896965141345b9945cf34980452f3502974edb76b9c785fb0f4395266b055f3b5db8aab68e9d7102a1cd9ee3d142504f0e88b282e603a738e051d98de05d1fcc65b5f7e99c4111cc0aec489abd0ecad311bfc13e7d1653b9c31e81c998037f959d5cd980835aa0e0b09bcbed634391151da02bc01a36c9a5800afb984163a7bb815edbc0226eda0595c724ca9b3f8a71178f0d20a5a:9881a5763bdb259a3fefbba3d957162d6c70b804fa94ab613406a6ec42505b8789465ca1a9a33e1895988842270c55e5bdd5483f6b17b31781b593507a6c1808a56ba86c71360504087e745c41627092ad6b49a71e9daa5640e1044bf04d4f071ad728779e95d1e2460584e6f0773545da82d4814c9189a120f12f3e3819813e5b240d0f26436f70ee353b4d20cea54a1460b5b8f1008d6f95f3aa2d8f1e908fced50d624e3a096938b9353854b96da463a2798a5a312ec790842c10c446e3350c764bf5c972593b9987bf23256daa8894d47f22e85b97607e66fc08a12c789c4746080368d321bb9015a1155b65523ad8e99bb989b44eac756b0734acd7c6357c70b59743246d1652d91b0f9896965141345b9945cf34980452f3502974edb76b9c785fb0f4395266b055f3b5db8aab68e9d7102a1cd9ee3d142504f0e88b282e603a738e051d98de05d1fcc65b5f7e99c4111cc0aec489abd0ecad311bfc13e7d1653b9c31e81c998037f959d5cd980835aa0e0b09bcbed634391151da02bc01a36c9a5800afb984163a7bb815edbc0226eda0595c724ca9b3f8a71178f0d20a5a: +f86d6f766f88b00717b7d6327eb26cf3ceeba5385184426f9cfd8295e2421ff2cb1d250504754183704dbe21c323d66f9f9011758f6d8dab6f597b199662145b:cb1d250504754183704dbe21c323d66f9f9011758f6d8dab6f597b199662145b:da8423a6b7a18f20aa1f90ed2331b17b24067c40175bc25d8109e21d87ac00528eb3b2f66a2b52dc7ef2f8cecb75c76099cfa23db8da897043ba1cce31e2dfea46075f5e073203eaeb3d62c84c107b6dab33a14eaf149aa61850c15f5a58d88a15aba9196f9e495e8dbecbcf7e8444f5dd72a08a099d7f6209990b562974ea829ef11d29a920e3a799d0d92cb50d50f817631ab09de97c31e9a05f4d78d649fcd93a83752078ab3bb0e16c564d4fb07ca923c0374ba5bf1eea7e73668e135031feafcbb47cbc2ae30ec16a39b9c337e0a62eecdd80c0b7a04924ac3972da4fa9299c14b5a53d37b08bf02268b3bac9ea9355090eeb04ad87bee0593ba4e4443dda38a97afbf2db9952df63f178f3b4c52bcc132be8d9e26881213abdeb7e1c44c4061548909f0520f0dd7520fc408ea28c2cebc0f53063a2d30570e05350e52b390dd9b67662984847be9ad9b4cd50b069ffd29dd9c62ef14701f8d012a4a70c8431cc:ec61c0b292203a8f1d87235ede92b74723c8d23408423773ae50b1e9bc4464e03e446da9dce4c39f6dd159bea26c009ed00120bc36d4a247dc0d24bcefcc110cda8423a6b7a18f20aa1f90ed2331b17b24067c40175bc25d8109e21d87ac00528eb3b2f66a2b52dc7ef2f8cecb75c76099cfa23db8da897043ba1cce31e2dfea46075f5e073203eaeb3d62c84c107b6dab33a14eaf149aa61850c15f5a58d88a15aba9196f9e495e8dbecbcf7e8444f5dd72a08a099d7f6209990b562974ea829ef11d29a920e3a799d0d92cb50d50f817631ab09de97c31e9a05f4d78d649fcd93a83752078ab3bb0e16c564d4fb07ca923c0374ba5bf1eea7e73668e135031feafcbb47cbc2ae30ec16a39b9c337e0a62eecdd80c0b7a04924ac3972da4fa9299c14b5a53d37b08bf02268b3bac9ea9355090eeb04ad87bee0593ba4e4443dda38a97afbf2db9952df63f178f3b4c52bcc132be8d9e26881213abdeb7e1c44c4061548909f0520f0dd7520fc408ea28c2cebc0f53063a2d30570e05350e52b390dd9b67662984847be9ad9b4cd50b069ffd29dd9c62ef14701f8d012a4a70c8431cc: +a5b34cefab9479df8389d7e6f6c146aa8affb0bec837f78af64624a145cc344e7b0f4f24d9972bc6fe83826c52716ad1e0d7d19f123858cb3e99fa636ac9631a:7b0f4f24d9972bc6fe83826c52716ad1e0d7d19f123858cb3e99fa636ac9631a:e21e98af6c2bac70557eb0e864da2c2b4d6c0a39a059d3477251f6178a39676f4749e7fbea623f148a43a8b0fe0610506fa658abd2f5fa39198f2636b724db22d1aebc2ab07b2b6dbffdee8cece81e1af1493ec1964e16bf86ab258ca0feb77e3c8717e44038abe152c14be15660bf93b2d48d92c4ed7074d2494210621bcf204fba88c654d5ffe01e1a53d08f70bb237089dc807216ff6a85dbec3102237d42590778acf6c1dc566d5a2bb9a63bc21c329c272e5965baeeb0fe891de3cc8cbfa8e541a8881df68942e7ff8dc656bd08575f6aaf924a176d663b1a1f43574d11768c701b269561e55438dbebfd443d2115cb933d1cde4a915b54c325c27f499ef02bd012ff1f9a36390922887600fe712bcdc23eb5974a305372ad52951f83f0e58cc49e289841621917f1fcb0235147240dae4cf3b99b6ac6d8de94efe7c4436714508bcd0114c56068ff1b7c16d51bd906437874d6549ab5d8087896872ec8a09d7412:2fbd899d72b6d39e4f45b8b62cbbd5f3c0acb1ad8540913fa585877e91ccfef7bee50a4b0f9fedf5cc1e0d1953ad399c8389a93391e1b7c929af6d6f3b796c08e21e98af6c2bac70557eb0e864da2c2b4d6c0a39a059d3477251f6178a39676f4749e7fbea623f148a43a8b0fe0610506fa658abd2f5fa39198f2636b724db22d1aebc2ab07b2b6dbffdee8cece81e1af1493ec1964e16bf86ab258ca0feb77e3c8717e44038abe152c14be15660bf93b2d48d92c4ed7074d2494210621bcf204fba88c654d5ffe01e1a53d08f70bb237089dc807216ff6a85dbec3102237d42590778acf6c1dc566d5a2bb9a63bc21c329c272e5965baeeb0fe891de3cc8cbfa8e541a8881df68942e7ff8dc656bd08575f6aaf924a176d663b1a1f43574d11768c701b269561e55438dbebfd443d2115cb933d1cde4a915b54c325c27f499ef02bd012ff1f9a36390922887600fe712bcdc23eb5974a305372ad52951f83f0e58cc49e289841621917f1fcb0235147240dae4cf3b99b6ac6d8de94efe7c4436714508bcd0114c56068ff1b7c16d51bd906437874d6549ab5d8087896872ec8a09d7412: +ad75c9ce299c4d59393367d77a4c9f8df8dcec765c6dbd25b527fb7669913604b9910548fe6312a119c9993eebcfb9dc90030ffb0e4de2b7ccd23cbeb4fef71b:b9910548fe6312a119c9993eebcfb9dc90030ffb0e4de2b7ccd23cbeb4fef71b:62fc5ab67deb1fee9ab6cca3b88a1df1e589f0fd4a88f4aa7738948761fe84372c5b18e4655220c1d84d52acad32e229a5c756c20fc62fe4b4b4e5fd7077ae4ed5397aa796f2307ceedb6505b39297856f4aeb5e70938e36ee24a0ac7d9868306f6b53910623b7dc89a6672ad738576ed5d88831dd338321c8902bc2061f65e94d452fdfa0dc665cefb92308e52301bd4627006b363d06b775a395914d8c863e95a00d6893f3376134c429f56478145e4456f7a12d65bb2b8965d728cb2ddbb708f7125c237095a92195d92fa727a372f3545ae701f3808fee802c8967a76e8a940e55fb2d810bfb47ada156f0eda1829b159cf05c7f36cf3847d7b21de84c3dc0fe658347f79396a01139a508b60022db1c0e5aeef47e445e66f783e62c96597bdb16f209c08a9132c7573136170ee3ebf24261265a89fb4f10333375e20b33ab7403464f5249461c6853c5fddb9f58af816892910393a7077b799fdc3489720998feea86:6b7ef27bcfbf2b714985033764fccff555e3f5bc44610d6c8c62117cb3831a07f4a8bddb0eaed1d46b0289b15de1aa4dcc17d71be96a09e66ba4dc4627c7870562fc5ab67deb1fee9ab6cca3b88a1df1e589f0fd4a88f4aa7738948761fe84372c5b18e4655220c1d84d52acad32e229a5c756c20fc62fe4b4b4e5fd7077ae4ed5397aa796f2307ceedb6505b39297856f4aeb5e70938e36ee24a0ac7d9868306f6b53910623b7dc89a6672ad738576ed5d88831dd338321c8902bc2061f65e94d452fdfa0dc665cefb92308e52301bd4627006b363d06b775a395914d8c863e95a00d6893f3376134c429f56478145e4456f7a12d65bb2b8965d728cb2ddbb708f7125c237095a92195d92fa727a372f3545ae701f3808fee802c8967a76e8a940e55fb2d810bfb47ada156f0eda1829b159cf05c7f36cf3847d7b21de84c3dc0fe658347f79396a01139a508b60022db1c0e5aeef47e445e66f783e62c96597bdb16f209c08a9132c7573136170ee3ebf24261265a89fb4f10333375e20b33ab7403464f5249461c6853c5fddb9f58af816892910393a7077b799fdc3489720998feea86: +1ced574529b9b416977e92eb39448a8717cac2934a243a5c44fb44b73ccc16da85e167d5f062fee82014f3c8b1beaed8eefb2c22d8649c424b86b21b11eb8bda:85e167d5f062fee82014f3c8b1beaed8eefb2c22d8649c424b86b21b11eb8bda:1b3b953cce6d15303c61ca707609f70e7250f6c0deba56a8ce522b5986689651cdb848b842b2229661b8eeabfb8570749ed6c2b10a8fbf515053b5ea7d7a9228349e4646f9505e198029fec9ce0f38e4e0ca73625842d64caf8ced070a6e29c743586aa3db6d82993ac71fd38b783162d8fe04ffd0fa5cbc381d0e219c91937df6c973912fc02fda5377312468274c4bee6dca7f79c8b544861ed5babcf5c50e1473491be01708ac7c9ff58f1e40f855497ce9d7cc47b9410f2edd00f6496740243b8d03b2f5fa742b9c630867f77ac42f2b62c14e5ebddc7b647a05fff43670745f2851eff4909f5d27d57ae87f61e965ee60fdf97724c59267f2610b7ad5de919856d64d7c212659ce8656149b6a6d29d8f92b312be50b6e2a431d36ae022b00a6fe360e3af65432899c43be0427e36d21cfec81f21aa53b33db5ed2c37da8f96ac3e7dc67a1de37546cf7de1008c7e1adbe0f34fa7eb2434d94e6a13f4cf86a98d497622f:e0303aefe08a77738dcc657afbb9b835ed279613a53c73fdc5ddbfb350e5cff4d6c9bb43dc07c95bf4e23b64c40f8804c7169952e3c8d59a7197241bfed0740f1b3b953cce6d15303c61ca707609f70e7250f6c0deba56a8ce522b5986689651cdb848b842b2229661b8eeabfb8570749ed6c2b10a8fbf515053b5ea7d7a9228349e4646f9505e198029fec9ce0f38e4e0ca73625842d64caf8ced070a6e29c743586aa3db6d82993ac71fd38b783162d8fe04ffd0fa5cbc381d0e219c91937df6c973912fc02fda5377312468274c4bee6dca7f79c8b544861ed5babcf5c50e1473491be01708ac7c9ff58f1e40f855497ce9d7cc47b9410f2edd00f6496740243b8d03b2f5fa742b9c630867f77ac42f2b62c14e5ebddc7b647a05fff43670745f2851eff4909f5d27d57ae87f61e965ee60fdf97724c59267f2610b7ad5de919856d64d7c212659ce8656149b6a6d29d8f92b312be50b6e2a431d36ae022b00a6fe360e3af65432899c43be0427e36d21cfec81f21aa53b33db5ed2c37da8f96ac3e7dc67a1de37546cf7de1008c7e1adbe0f34fa7eb2434d94e6a13f4cf86a98d497622f: +f0790d93e2d3b84f61ef4c807147aba410e415e72b71b0d61d01026fed99da3defdf649fb033cf328e0b287796f8a25e9c6e2e871b33c2c21a4028a8a25a4b28:efdf649fb033cf328e0b287796f8a25e9c6e2e871b33c2c21a4028a8a25a4b28:7973e9f32d74805992eb65da0d637335e50eff0ce68ea2d1f3a02de704492b9cfbe7e7ba96fdb42bb821a513d73fc60402e92c855deaed73ffeaf70952029062c833e14ec1b14f144e2207f6a0e727e5a7e3cbab27d5972970f69518a15b093e740cc0ce11bf5248f0826b8a98bde8bf2c7082c97aff158d08371118c89021cc3974ae8f76d86673c3f824b62c79c4b41f40eaa8943738f03300f68cbe175468eb235a9ff0e6537f8714e97e8f08ca444e41191063b5fabd156e85dcf66606b81dad4a95065584b3e0658c20a706eaf4a0777da4d2e0cd2a0fca60109c2b4403db3f03cd4781c1fbb0272202bcb11687808c50cb98f64b7f3fd3d43333bb5a061b9e377090abb1e0a885cb26b73c163e63ff6451ff2f4ec8249c7e152bd03973a1e964e2b5b235281a938399a112a24529e383a560dc50bb1b622ad74ef35658dcb10ffe022568ac3ffae5b465a8ed7643e8561b352ee9944a35d882c712b187788a0abae5a22f:08773a6a78762cbb1e25fcbb29139941bdf16f4e09a1fa08fc701f32f933edd74c0ae983c12a0a5b020b6bcf44bb719dde8ed0781a8298265640e1608c98b3017973e9f32d74805992eb65da0d637335e50eff0ce68ea2d1f3a02de704492b9cfbe7e7ba96fdb42bb821a513d73fc60402e92c855deaed73ffeaf70952029062c833e14ec1b14f144e2207f6a0e727e5a7e3cbab27d5972970f69518a15b093e740cc0ce11bf5248f0826b8a98bde8bf2c7082c97aff158d08371118c89021cc3974ae8f76d86673c3f824b62c79c4b41f40eaa8943738f03300f68cbe175468eb235a9ff0e6537f8714e97e8f08ca444e41191063b5fabd156e85dcf66606b81dad4a95065584b3e0658c20a706eaf4a0777da4d2e0cd2a0fca60109c2b4403db3f03cd4781c1fbb0272202bcb11687808c50cb98f64b7f3fd3d43333bb5a061b9e377090abb1e0a885cb26b73c163e63ff6451ff2f4ec8249c7e152bd03973a1e964e2b5b235281a938399a112a24529e383a560dc50bb1b622ad74ef35658dcb10ffe022568ac3ffae5b465a8ed7643e8561b352ee9944a35d882c712b187788a0abae5a22f: +4cb9df7ce6fae9d62ba09e8eb70e4c969bdeafcb5ec7d7024326e6603b0621bf018069dd0eb44055a35cd8c77c37ca9fb1ad2417271385e134b2f4e81f52033c:018069dd0eb44055a35cd8c77c37ca9fb1ad2417271385e134b2f4e81f52033c:14627d6ea0e7895460759476dc74c42800ceef994327518151490d9df23067914e44788a12768ccb25471b9c3ba9d14fb436dcba38429b3a0456877763c49175d0e082683e07a9058f3685c6279307b2303d1221b9c29793d8a4877f6df51587384dadf751c5f7bfbd207d519622c37b51ceeee2c20d8269f8cb88d3fe43d6d434d5bbd0e203c1532d97ba552147227496c87f67b50bb76193add0144df1c176657585408362ca2ed04ad62acf1c25e341dfd1498d85b4b1349a8b0b9b02c43523c55853419bfed37d5a2cdf17dfbf1a3bd7759d6ae180f9d27dcd9a8933e29a7c0a30771eea7c2e0fa242925d2336dce585629057d844323964f6d3d11ff0b3f829a3be8c9f0468a6823d8e70ab5a2da21e15fa8b041a29812222e9c30b2bd9a12d1fdee6f87876e8ce81009637a8bb2236129a47ca74289ee4aad429ffe29f47430241ca8cc3848b7200fd6e1470651a9a0a6f72c9033e831df051408a6260f65cbaf6e012b18e:e33c07836c537d6bfbd0f4592d6e35b163499ba78dc7ffcec565d04f9a7db781943e29e6ce76763e9baddf57437fd9c6b03239a6e6850e4502a356c2e12c370514627d6ea0e7895460759476dc74c42800ceef994327518151490d9df23067914e44788a12768ccb25471b9c3ba9d14fb436dcba38429b3a0456877763c49175d0e082683e07a9058f3685c6279307b2303d1221b9c29793d8a4877f6df51587384dadf751c5f7bfbd207d519622c37b51ceeee2c20d8269f8cb88d3fe43d6d434d5bbd0e203c1532d97ba552147227496c87f67b50bb76193add0144df1c176657585408362ca2ed04ad62acf1c25e341dfd1498d85b4b1349a8b0b9b02c43523c55853419bfed37d5a2cdf17dfbf1a3bd7759d6ae180f9d27dcd9a8933e29a7c0a30771eea7c2e0fa242925d2336dce585629057d844323964f6d3d11ff0b3f829a3be8c9f0468a6823d8e70ab5a2da21e15fa8b041a29812222e9c30b2bd9a12d1fdee6f87876e8ce81009637a8bb2236129a47ca74289ee4aad429ffe29f47430241ca8cc3848b7200fd6e1470651a9a0a6f72c9033e831df051408a6260f65cbaf6e012b18e: +a136e009d53e5ef59d0946bc175663a86bc0fcd29eadd95cfc9d266037b1e4fb9c1806ec0454f58314eb8397d64287dee386640d8491aba364607688841715a0:9c1806ec0454f58314eb8397d64287dee386640d8491aba364607688841715a0:a49d1c3d49e13c2eda56868a8824aa9f8d2bf72f21955ebafd07b3bdc8e924de20936cee513d8a64a47173a3bd659eff1accff8244b26aae1a0c27fa891bf4d85e8fb1b76a6cab1e7f74c89ee07bb40d714326f09b3fd40632fad208ea816f9072028c14b5b54ecc1c5b7fc809e7e0786e2f11495e76017eb62aa4563f3d00ee84348d9838cd17649f6929a6d206f60e6fc82e0c3464b27e0e6abd22f4469bdfd4cb54f77e329b80f71bf42129ec13c9dfe192adfaa42ee3ddeeda385816fbad5f411938c63b560f4ecd94534be7d98725cd94c99ce492f0f069ba0ec08f877a7812ef27ae19d7a77be63f66bcf8d6cf3a1a61fc9cfef104c7462a21ca7f03afb5bb1ac8c75124b554e8d044b810d95ff8c9dd09a34484d8c4b6c95f95c3c22823f52ce844293724d5259191f1ba0929e2acdbb8b9a7a8adf0c52e78acdfdf057b0985881afbed4dbebdebbdae0a2b63bd4e90f96afdcbbd78f506309f9bdb650013cb73faed73904e:bc094ba91c115dee15d753361a75f3f03d6af45c92157e95dbe8d32194b6c5ce72b9dc66f73df12dca0b639f3e791d478616a1f8d7359a42c8eae0dda16b1606a49d1c3d49e13c2eda56868a8824aa9f8d2bf72f21955ebafd07b3bdc8e924de20936cee513d8a64a47173a3bd659eff1accff8244b26aae1a0c27fa891bf4d85e8fb1b76a6cab1e7f74c89ee07bb40d714326f09b3fd40632fad208ea816f9072028c14b5b54ecc1c5b7fc809e7e0786e2f11495e76017eb62aa4563f3d00ee84348d9838cd17649f6929a6d206f60e6fc82e0c3464b27e0e6abd22f4469bdfd4cb54f77e329b80f71bf42129ec13c9dfe192adfaa42ee3ddeeda385816fbad5f411938c63b560f4ecd94534be7d98725cd94c99ce492f0f069ba0ec08f877a7812ef27ae19d7a77be63f66bcf8d6cf3a1a61fc9cfef104c7462a21ca7f03afb5bb1ac8c75124b554e8d044b810d95ff8c9dd09a34484d8c4b6c95f95c3c22823f52ce844293724d5259191f1ba0929e2acdbb8b9a7a8adf0c52e78acdfdf057b0985881afbed4dbebdebbdae0a2b63bd4e90f96afdcbbd78f506309f9bdb650013cb73faed73904e: +ff0f1c57dd884fbeea6e2917282b79ba67f8a6851267b9f4636dafda33bd2b5bfef6378ad12a7c252fa6eb742b05064b41530ff019dc680ab544c027ea2836e7:fef6378ad12a7c252fa6eb742b05064b41530ff019dc680ab544c027ea2836e7:522a5e5eff5b5e98fad6878a9d72df6eb318622610a1e1a48183f5590ecef5a6df671b28be91c88cdf7ae2881147fe6c37c28b43f64cf981c455c59e765ce94e1b6491631deaeef6d1da9ebca88643c77f83eae2cfdd2d97f604fe45081d1be5c4ae2d875996b8b6fecd707d3fa219a93ba0488e55247b405e330cfb97d31a1361c9b2084bdb13fb0c058925db8c3c649c9a3e937b533cc6310fa3b16126fb3cc9bb2b35c5c8300015488a30fadca3c8871fa70dfdc7055bf8e631f20c9b2528311e324a7c4edd5462079f3441c9ecf55fa999e731372344fdc0d413e417aaa001a1b2d3d9bc000fec1b02bd7a88a812d9d8a66f9464764c070c93041eefb17ce74eff6d4aff75f0cbf6a789a9ecde74abe33130fca0da853aa7c3313ada3f0ae2f595c6796a93685e729dd18a669d6381825ab3f36a391e7525b2a807a52fa5ec2a030a8cf3b77337ac41fceb580e845eed655a48b547238c2e8137c92f8c27e585caad3106eee3814a:d5008486726cce330a29dd7e4d7474d735798201afd1206feb869a112e5b43523c06976761be3cf9b2716378273c94f93572a7d2b8982634e0755c632b449008522a5e5eff5b5e98fad6878a9d72df6eb318622610a1e1a48183f5590ecef5a6df671b28be91c88cdf7ae2881147fe6c37c28b43f64cf981c455c59e765ce94e1b6491631deaeef6d1da9ebca88643c77f83eae2cfdd2d97f604fe45081d1be5c4ae2d875996b8b6fecd707d3fa219a93ba0488e55247b405e330cfb97d31a1361c9b2084bdb13fb0c058925db8c3c649c9a3e937b533cc6310fa3b16126fb3cc9bb2b35c5c8300015488a30fadca3c8871fa70dfdc7055bf8e631f20c9b2528311e324a7c4edd5462079f3441c9ecf55fa999e731372344fdc0d413e417aaa001a1b2d3d9bc000fec1b02bd7a88a812d9d8a66f9464764c070c93041eefb17ce74eff6d4aff75f0cbf6a789a9ecde74abe33130fca0da853aa7c3313ada3f0ae2f595c6796a93685e729dd18a669d6381825ab3f36a391e7525b2a807a52fa5ec2a030a8cf3b77337ac41fceb580e845eed655a48b547238c2e8137c92f8c27e585caad3106eee3814a: +0bc6af64de5709d3dbc28f7ef6d3fe28b6de529f08f5857ccb910695de454f56fb491fc900237bdc7e9a119f27150cd911935cd3628749ff40ef41f3955bc8ac:fb491fc900237bdc7e9a119f27150cd911935cd3628749ff40ef41f3955bc8ac:ac7886e4f4172a22c95e8eea37437b375d72accedcee6cc6e816763301a2d8ef4d6f31a2c1d635818b7026a395ce0dafd71c5180893af76b7ea056c972d680eca01dcbdbae6b26f1c5f33fc988b824fbbe00cacc316469a3bae07aa7c8885af7f65f42e75cef94dbb9aab4825143c85070e7716b7612f64ef0b0166011d23eb5654aa098b02d8d71e57c8fa17bff2fe97dc8193177eadc09fb192d80aa92afa98720d4614817ff3c39d3acce18906fa3de09618931d0d7a60c4429cbfa20cf165c947929ac293ae6c06e7e8f25f1264291e3e1c98f5d93e6ecc2389bc60dbbf4a621b132c552a99c95d26d8d1af61138b570a0de4b497ebe8051c7273a98e6e7876d0b327503af3cb2cc4091ce1925cb2f2957f4ec56ee90f8a09dd57d6e83067a356a4cfe65b1b7a4465da2ab133b0efb5e7d4dbb811bcbbde712afbf0f7dd3f326222284b8c74eac7ad6257fa8c632b7da2559a6266e91e0ef90dbb0aa968f75376b693fcaa5da342221:dbc7134d1cd6b0813b53352714b6df939498e91cf37c324337d9c088a1b998347d26185b430900412929e4f63e910379fc42e355a4e98f6fee27dafad1957206ac7886e4f4172a22c95e8eea37437b375d72accedcee6cc6e816763301a2d8ef4d6f31a2c1d635818b7026a395ce0dafd71c5180893af76b7ea056c972d680eca01dcbdbae6b26f1c5f33fc988b824fbbe00cacc316469a3bae07aa7c8885af7f65f42e75cef94dbb9aab4825143c85070e7716b7612f64ef0b0166011d23eb5654aa098b02d8d71e57c8fa17bff2fe97dc8193177eadc09fb192d80aa92afa98720d4614817ff3c39d3acce18906fa3de09618931d0d7a60c4429cbfa20cf165c947929ac293ae6c06e7e8f25f1264291e3e1c98f5d93e6ecc2389bc60dbbf4a621b132c552a99c95d26d8d1af61138b570a0de4b497ebe8051c7273a98e6e7876d0b327503af3cb2cc4091ce1925cb2f2957f4ec56ee90f8a09dd57d6e83067a356a4cfe65b1b7a4465da2ab133b0efb5e7d4dbb811bcbbde712afbf0f7dd3f326222284b8c74eac7ad6257fa8c632b7da2559a6266e91e0ef90dbb0aa968f75376b693fcaa5da342221: +2f5e83bd5b412e71ae3e9084cd369efcc79bf6037c4b174dfd6a11fb0f5da218a22a6da29a5ef6240c49d8896e3a0f1a4281a266c77d383ee6f9d25ffacbb872:a22a6da29a5ef6240c49d8896e3a0f1a4281a266c77d383ee6f9d25ffacbb872:b766273f060ef3b2ae3340454a391b426bc2e97264f8674553eb00dd6ecfdd59b611d8d662929fec710d0e462020e12cdbf9c1ec8858e85671acf8b7b14424ce92079d7d801e2ad9acac036bc8d2dfaa72aa839bff30c0aa7e414a882c00b645ff9d31bcf5a54382def4d0142efa4f06e823257ff132ee968cdc6738c53f53b84c8df76e9f78dd5056cf3d4d5a80a8f84e3edec48520f2cb4583e708539355ef7aa86fb5a0e87a94dcf14f30a2cca568f139d9ce59eaf459a5c5916cc8f20b26aaf6c7c029379aedb05a07fe585ccac60307c1f58ca9f859157d06d06baa394aace79d51b8cb38cfa2598141e245624e5ab9b9d68731173348905315bf1a5ad61d1e8adaeb810e4e8a86d7c13537b0be860ab2ed35b73399b8808aa91d750f77943f8a8b7e89fdb50728aa3dbbd8a41a6e00756f438c9b9e9d55872df5a9068add8a972b7e43edad9ced2237ca1367be4b7cdb66a54ea12eef129471158610eaf28f99f7f686557dcdf644ea:9f80922bc8db32d0cc43f9936affebe7b2bc35a5d82277cd187b5d50dc7fc4c4832fffa34e9543806b485c04548e7c75429425e14d55d91fc1052efd8667430bb766273f060ef3b2ae3340454a391b426bc2e97264f8674553eb00dd6ecfdd59b611d8d662929fec710d0e462020e12cdbf9c1ec8858e85671acf8b7b14424ce92079d7d801e2ad9acac036bc8d2dfaa72aa839bff30c0aa7e414a882c00b645ff9d31bcf5a54382def4d0142efa4f06e823257ff132ee968cdc6738c53f53b84c8df76e9f78dd5056cf3d4d5a80a8f84e3edec48520f2cb4583e708539355ef7aa86fb5a0e87a94dcf14f30a2cca568f139d9ce59eaf459a5c5916cc8f20b26aaf6c7c029379aedb05a07fe585ccac60307c1f58ca9f859157d06d06baa394aace79d51b8cb38cfa2598141e245624e5ab9b9d68731173348905315bf1a5ad61d1e8adaeb810e4e8a86d7c13537b0be860ab2ed35b73399b8808aa91d750f77943f8a8b7e89fdb50728aa3dbbd8a41a6e00756f438c9b9e9d55872df5a9068add8a972b7e43edad9ced2237ca1367be4b7cdb66a54ea12eef129471158610eaf28f99f7f686557dcdf644ea: +722a2da50e42c11a61c9afac7be1a2fed2267d650f8f7d8e5bc706b807c1b91dfd0b964562f823721e649c3fedb432a76f91e0aead7c61d35f95ed7726d78589:fd0b964562f823721e649c3fedb432a76f91e0aead7c61d35f95ed7726d78589:173e8bb885e1f9081404acac999041d2ecfcb73f945e0db36e631d7cd1ab999eb717f34bf07874bf3d34e2530eb6085f4a9f88ae1b0f7d80f221456a8e9a8890b91a50192deaaacc0a1a615a87841e2c5a9e057957af6e48e78cc86198e32e7aa24dcf6cffa329bc72606d65b11682c8ba736cce22a05785df1146331e41609cf9ca711cf464958297138b58a9073f3bbf06ad8a85d135de66652104d88b49d27ad41e59bcc44c7fab68f53f0502e293ffcabaaf755927dfdffbfde3b35c080b5de4c8b785f4da64ef357bc0d1466a6a96560c3c4f3e3c0b563a003f5f95f237171bce1a001771a04ede7cdd9b8ca770fd36ef90e9fe0000a8d7685fd153cc7282de95920a8f8f0898d00bf0c6c933fe5bb9653ff146c4e2acd1a2e0c23c1244844dacf8652716302c2032f9c114679ed26b3ee3ab4a7b18bc4e3071f0977db57cd0ac68c0727a09b4f125fb64af2850b26c8a484263334e2da902d744737044e79ab1cf5b2f93a022b63d40cd:c2695a57172aaa31bd0890f231ca8eeec0287a87172669a899ad0891cea4c47579b50420e791cdec8c182c8a0e8dde21b2480b0cfd8111e28e5603347a352d04173e8bb885e1f9081404acac999041d2ecfcb73f945e0db36e631d7cd1ab999eb717f34bf07874bf3d34e2530eb6085f4a9f88ae1b0f7d80f221456a8e9a8890b91a50192deaaacc0a1a615a87841e2c5a9e057957af6e48e78cc86198e32e7aa24dcf6cffa329bc72606d65b11682c8ba736cce22a05785df1146331e41609cf9ca711cf464958297138b58a9073f3bbf06ad8a85d135de66652104d88b49d27ad41e59bcc44c7fab68f53f0502e293ffcabaaf755927dfdffbfde3b35c080b5de4c8b785f4da64ef357bc0d1466a6a96560c3c4f3e3c0b563a003f5f95f237171bce1a001771a04ede7cdd9b8ca770fd36ef90e9fe0000a8d7685fd153cc7282de95920a8f8f0898d00bf0c6c933fe5bb9653ff146c4e2acd1a2e0c23c1244844dacf8652716302c2032f9c114679ed26b3ee3ab4a7b18bc4e3071f0977db57cd0ac68c0727a09b4f125fb64af2850b26c8a484263334e2da902d744737044e79ab1cf5b2f93a022b63d40cd: +5fe9c3960ed5bd374cc94d42357e6a24dc7e3060788f726365defacf13cd12da0ce7b155c8b20ebdaacdc2aa23627e34b1f9ace980650a2530c7607d04814eb4:0ce7b155c8b20ebdaacdc2aa23627e34b1f9ace980650a2530c7607d04814eb4:c9490d83d9c3a9370f06c91af001685a02fe49b5ca667733fff189eee853ec1667a6c1b6c787e9244812d2d532866ab74dfc870d6f14033b6bcd39852a3900f8f08cd95a74cb8cbe02b8b8b51e993a06adfebd7fc9854ae5d29f4df9642871d0c5e470d903cfbcbd5adb3275628f28a80bf8c0f0376687dae673bf7a8547e80d4a9855ae2572fc2b205dc8a198016ddc9b50995f5b39f368f540504a551803d6dd5f874828e5541ded052894d9e2dc5e6aa351087e790c0dd5d9c4decb217e4db81c98a184b264e6daeac0f11e074cae2bfc899f54b419c65dcc22664a915fbfffac35cee0f286eb7b144933db933e16c4bcb650d537722489de236373fd8d65fc86118b6def37ca4608bc6ce927b65436ffda7f02bfbf88b045ae7d2c2b45a0b30c8f2a04df953221088c555fe9a5df260982a3d64df194ee952fa9a98c31b96493db6180d13d67c36716f95f8c0bd7a039ad990667ca34a83ac1a18c37dd7c7736aa6b9b6fc2b1ac0ce119ef77:379f9c54c413af0d192e9bc736b29da9d521e7ba7841d309f9bcc1e742ec4308fe9f7ba51e0b22aed487cb4aa3913b9bebfb3aacd38f4039f9bbbebe1ad80002c9490d83d9c3a9370f06c91af001685a02fe49b5ca667733fff189eee853ec1667a6c1b6c787e9244812d2d532866ab74dfc870d6f14033b6bcd39852a3900f8f08cd95a74cb8cbe02b8b8b51e993a06adfebd7fc9854ae5d29f4df9642871d0c5e470d903cfbcbd5adb3275628f28a80bf8c0f0376687dae673bf7a8547e80d4a9855ae2572fc2b205dc8a198016ddc9b50995f5b39f368f540504a551803d6dd5f874828e5541ded052894d9e2dc5e6aa351087e790c0dd5d9c4decb217e4db81c98a184b264e6daeac0f11e074cae2bfc899f54b419c65dcc22664a915fbfffac35cee0f286eb7b144933db933e16c4bcb650d537722489de236373fd8d65fc86118b6def37ca4608bc6ce927b65436ffda7f02bfbf88b045ae7d2c2b45a0b30c8f2a04df953221088c555fe9a5df260982a3d64df194ee952fa9a98c31b96493db6180d13d67c36716f95f8c0bd7a039ad990667ca34a83ac1a18c37dd7c7736aa6b9b6fc2b1ac0ce119ef77: +ec2fa541ac14b414149c3825eaa7001b795aa1957d4040dda92573904afa7ee471b363b2408404d7beecdef1e1f511bb6084658b532f7ea63d4e3f5f01c61d31:71b363b2408404d7beecdef1e1f511bb6084658b532f7ea63d4e3f5f01c61d31:2749fc7c4a729e0e0ad71b5b74eb9f9c534ebd02ffc9df4374d813bdd1ae4eb87f1350d5fdc563934515771763e6c33b50e64e0cd114573031d2186b6eca4fc802cddc7cc51d92a61345a17f6ac38cc74d84707a5156be9202dee3444652e79bae7f0d31bd17567961f65dd01a8e4bee38331938ce4b2b550691b99a4bc3c072d186df4b3344a5c8fbfbb9fd2f355f6107e410c3d0c798b68d3fb9c6f7ab5fe27e70871e86767698fe35b77ead4e435a9402cc9ed6a2657b059be0a21003c048bbf5e0ebd93cbb2e71e923cf5c728d1758cd817ad74b454a887126d653b95a7f25e5293b768c9fc5a9c35a2372e3741bc90fd66301427b10824bb4b1e9110bfba84c21a40eb8fed4497e91dc3ffd0438c514c0a8cb4cac6ad0256bf11d5aa7a9c7c00b669b015b0bf81425a21413e2ffb6edc0bd78e385c44fd74558e511c2c25fee1fec18d3990b8690300fa711e93d9854668f0187065e76e7113ae763c30ddd86720b5546a6c3c6f1c43bc67b14:84d18d56f964e3776759bba92c510c2b6d574555c3cddade212da90374554991e7d77e278d63e34693e1958078cc3685f8c41c1f5342e351899638ef612114012749fc7c4a729e0e0ad71b5b74eb9f9c534ebd02ffc9df4374d813bdd1ae4eb87f1350d5fdc563934515771763e6c33b50e64e0cd114573031d2186b6eca4fc802cddc7cc51d92a61345a17f6ac38cc74d84707a5156be9202dee3444652e79bae7f0d31bd17567961f65dd01a8e4bee38331938ce4b2b550691b99a4bc3c072d186df4b3344a5c8fbfbb9fd2f355f6107e410c3d0c798b68d3fb9c6f7ab5fe27e70871e86767698fe35b77ead4e435a9402cc9ed6a2657b059be0a21003c048bbf5e0ebd93cbb2e71e923cf5c728d1758cd817ad74b454a887126d653b95a7f25e5293b768c9fc5a9c35a2372e3741bc90fd66301427b10824bb4b1e9110bfba84c21a40eb8fed4497e91dc3ffd0438c514c0a8cb4cac6ad0256bf11d5aa7a9c7c00b669b015b0bf81425a21413e2ffb6edc0bd78e385c44fd74558e511c2c25fee1fec18d3990b8690300fa711e93d9854668f0187065e76e7113ae763c30ddd86720b5546a6c3c6f1c43bc67b14: +6132692a5ef27bf476b1e991e6c431a8c764f1aebd470282db3321bb7cb09c207a2d166184f9e5f73bea454486b041ceb5fc2314a7bd59cb718e79f0ec989d84:7a2d166184f9e5f73bea454486b041ceb5fc2314a7bd59cb718e79f0ec989d84:a9c0861665d8c2de06f9301da70afb27b3024b744c6b38b24259294c97b1d1cb4f0dcf7575a8ed454e2f0980f50313a77363415183fe9677a9eb1e06cb6d34a467cb7b0758d6f55c564b5ba15603e202b18856d89e72a23ab07d8853ff77da7aff1caebd7959f2c710ef31f5078a9f2cdae92641a1cc5f74d0c143ec42afbaa5f378a9e10d5bf74587fa5f49c156233247dafd3929acde888dc684337e40cdc5932e7eb73ffcc90b85c0ad460416691aefbd7efd07b657c350946a0e366b37a6c8089aba5c5fe3bbca064afbe9d47fbc83914af1cb43c2b2efa98e0a43be32ba823202001def36817251b65f9b0506cef6683642a46ed612f8ca81ee97bb04d317b517343ade2b77126d1f02a87b7604c8653b6748cf5488fa6d43df809faa19e69292d38c5d397dd8e20c7af7c5334ec977f5010a0f7cb5b89479ca06db4d12627f067d6c42186a6b1f8742f36ae709ba720e3cd898116666d81b190b9b9d2a72202cb690a03f3310429a71dc048cde:eb677f3347e1a1ea929efdf62bf9105a6c8f4993033b4f6d03cb0dbf9c742b270704e383ab7c0676bdb1ad0ce9b16673083c9602ec10ae1dd98e8748b336440ba9c0861665d8c2de06f9301da70afb27b3024b744c6b38b24259294c97b1d1cb4f0dcf7575a8ed454e2f0980f50313a77363415183fe9677a9eb1e06cb6d34a467cb7b0758d6f55c564b5ba15603e202b18856d89e72a23ab07d8853ff77da7aff1caebd7959f2c710ef31f5078a9f2cdae92641a1cc5f74d0c143ec42afbaa5f378a9e10d5bf74587fa5f49c156233247dafd3929acde888dc684337e40cdc5932e7eb73ffcc90b85c0ad460416691aefbd7efd07b657c350946a0e366b37a6c8089aba5c5fe3bbca064afbe9d47fbc83914af1cb43c2b2efa98e0a43be32ba823202001def36817251b65f9b0506cef6683642a46ed612f8ca81ee97bb04d317b517343ade2b77126d1f02a87b7604c8653b6748cf5488fa6d43df809faa19e69292d38c5d397dd8e20c7af7c5334ec977f5010a0f7cb5b89479ca06db4d12627f067d6c42186a6b1f8742f36ae709ba720e3cd898116666d81b190b9b9d2a72202cb690a03f3310429a71dc048cde: +f219b2101164aa9723bde3a7346f68a35061c01f9782072580ba32df903ba891f66b920d5aa1a6085495a1480539beba01ffe60e6a6388d1b2e8eda23355810e:f66b920d5aa1a6085495a1480539beba01ffe60e6a6388d1b2e8eda23355810e:015577d3e4a0ec1ab25930106343ff35ab4f1e0a8a2d844aadbb70e5fc5348ccb679c2295c51d702aaae7f6273ce70297b26cb7a253a3db94332e86a15b4a64491232791f7a8b082ee2834af30400e804647a532e9c454d2a0a7320130ab6d4d860073a34667ac25b7e5e2747ba9f5c94594fb68377ae260369c40713b4e32f23195bf91d3d7f1a2719bf408aad8d8a347b112e84b118817cb06513344021763035272a7db728a0ccdaa949c61715d0764140b3e8c01d20ff1593c7f2d55c4e82a1c0cb1ea58442bf80a741bca91f58ab0581b498ee9fe3c92ca654148ef75313543d1aff382befe1a93b02190ce0102175158e2071d02bacad8dbe9fb940fcb610c105ad52c80feb1ec4e524f4c0ec7983e9ce696fa4fcf4bf0514b8f0432b17d5448fc426fea2b01ac7b26c2aed769927534da22576fc1bba726e9d65be01b59f60a648ace2fc3e5e275789fa637cbbd84be3d6ac24457a6292cd656c7b569a52ffea7916b8d04b4f4a75be7ac95142f:17f0127ca3bafa5f4ee959cd60f772be87a0034961517e39a0a1d0f4b9e26db1336e60c82b352c4cbacdbbd11771c3774f8cc5a1a795d6e4f4ebd51def36770b015577d3e4a0ec1ab25930106343ff35ab4f1e0a8a2d844aadbb70e5fc5348ccb679c2295c51d702aaae7f6273ce70297b26cb7a253a3db94332e86a15b4a64491232791f7a8b082ee2834af30400e804647a532e9c454d2a0a7320130ab6d4d860073a34667ac25b7e5e2747ba9f5c94594fb68377ae260369c40713b4e32f23195bf91d3d7f1a2719bf408aad8d8a347b112e84b118817cb06513344021763035272a7db728a0ccdaa949c61715d0764140b3e8c01d20ff1593c7f2d55c4e82a1c0cb1ea58442bf80a741bca91f58ab0581b498ee9fe3c92ca654148ef75313543d1aff382befe1a93b02190ce0102175158e2071d02bacad8dbe9fb940fcb610c105ad52c80feb1ec4e524f4c0ec7983e9ce696fa4fcf4bf0514b8f0432b17d5448fc426fea2b01ac7b26c2aed769927534da22576fc1bba726e9d65be01b59f60a648ace2fc3e5e275789fa637cbbd84be3d6ac24457a6292cd656c7b569a52ffea7916b8d04b4f4a75be7ac95142f: +fc180035aec0f5ede7bda93bf77ade7a81ed06de07ee2e3aa8576be81608610a4f215e948cae243ee3143b80282ad792c780d2a6b75060ca1d290ca1a8e3151f:4f215e948cae243ee3143b80282ad792c780d2a6b75060ca1d290ca1a8e3151f:b5e8b01625664b222339e0f05f93a990ba48b56ae65439a17520932df011721e284dbe36f98631c066510098a68d7b692a3863e99d58db76ca5667c8043cb10bd7abbaf506529fbb23a5166be038affdb9a234c4f4fcf43bddd6b8d2ce772dd653ed115c095e232b269dd4888d2368cb1c66be29dd383fca67f66765b296564e37555f0c0e484504c591f006ea8533a12583ad2e48318ff6f324ecaf804b1bae04aa896743e67ef61ca383d58e42acfc6410de30776e3ba262373b9e1441943955101a4e768231ad9c6529eff6118dde5df02f94b8d6df2d99f27863b517243a579e7aaff311ea3a0282e47ca876fabc2280fce7adc984dd0b30885b1650f1471dfcb0522d49fec7d042f32a93bc368f076006ea01ec1c7412bf66f62dc88de2c0b74701a5614e855e9fa728fb1f1171385f96afbde70dea02e9aa94dc21848c26302b50ae91f9693a1864e4e095ae03cdc22ad28a0eb7db596779246712fab5f5da327efec3e79612de0a6ccaa536759b8e:a43a71c3a19c35660dae6f31a254b8c0ea3593fc8fca74d13640012b9e9473d4afe070db01e7fb399bf4ca6070e062180011285a67dd6858b761e46c6bd32004b5e8b01625664b222339e0f05f93a990ba48b56ae65439a17520932df011721e284dbe36f98631c066510098a68d7b692a3863e99d58db76ca5667c8043cb10bd7abbaf506529fbb23a5166be038affdb9a234c4f4fcf43bddd6b8d2ce772dd653ed115c095e232b269dd4888d2368cb1c66be29dd383fca67f66765b296564e37555f0c0e484504c591f006ea8533a12583ad2e48318ff6f324ecaf804b1bae04aa896743e67ef61ca383d58e42acfc6410de30776e3ba262373b9e1441943955101a4e768231ad9c6529eff6118dde5df02f94b8d6df2d99f27863b517243a579e7aaff311ea3a0282e47ca876fabc2280fce7adc984dd0b30885b1650f1471dfcb0522d49fec7d042f32a93bc368f076006ea01ec1c7412bf66f62dc88de2c0b74701a5614e855e9fa728fb1f1171385f96afbde70dea02e9aa94dc21848c26302b50ae91f9693a1864e4e095ae03cdc22ad28a0eb7db596779246712fab5f5da327efec3e79612de0a6ccaa536759b8e: +a2836a65427912122d25dcdfc99d7046fe9b53d5c1bb23617f11890e94ca93ed8c12bda214c8abb2286acffbf8112425040aab9f4d8bb7870b98da0159e882f1:8c12bda214c8abb2286acffbf8112425040aab9f4d8bb7870b98da0159e882f1:813d6061c56eae0ff53041c0244aa5e29e13ec0f3fb428d4beb8a99e04bca8c41bddb0db945f487efe38f2fc14a628fafa2462f860e4e34250eb4e93f139ab1b74a2614519e41ee2403be427930ab8bc82ec89ceafb60905bd4ddbbd13bdb19654314fc92373140b962e2258e038d71b9ec66b84ef8319e03551cb707e747f6c40ad476fbefdce71f3a7b67a1af1869bc6440686e7e0855e4f369d1d88b8099fba54714678627bba1aff41e7707bc97eddf890b0c08dce3e9800d24c6f61092ce28d481b5dea5c096c55d72f8946009131fb968e2bc8a054d825adab76740dcf0d758c8bf54ff38659e71b32bfe2e615aaabb0f5293085649cf60b9847bc62011ce3878af628984a5840a4ad5dae3702db367da0f8a165fed0517eb5c442b0145330241b97eeca733ba6688b9c129a61cd1236aff0e27bcf98c28b0fbeea55a3d7c7193d644b2749f986bd46af8938e8faaeafbd9cec3612ab005bd7c3eeafe9a31279ca6102560666ba16136ff1452f850adb:e6a9a6b436559a4320c45c0c2c4a2aedecb90d416d52c82680ac7330d062aebef3e9ac9f2c5ffa455c9be113013a2b282e5600fd306435ada83b1e48ba2a3605813d6061c56eae0ff53041c0244aa5e29e13ec0f3fb428d4beb8a99e04bca8c41bddb0db945f487efe38f2fc14a628fafa2462f860e4e34250eb4e93f139ab1b74a2614519e41ee2403be427930ab8bc82ec89ceafb60905bd4ddbbd13bdb19654314fc92373140b962e2258e038d71b9ec66b84ef8319e03551cb707e747f6c40ad476fbefdce71f3a7b67a1af1869bc6440686e7e0855e4f369d1d88b8099fba54714678627bba1aff41e7707bc97eddf890b0c08dce3e9800d24c6f61092ce28d481b5dea5c096c55d72f8946009131fb968e2bc8a054d825adab76740dcf0d758c8bf54ff38659e71b32bfe2e615aaabb0f5293085649cf60b9847bc62011ce3878af628984a5840a4ad5dae3702db367da0f8a165fed0517eb5c442b0145330241b97eeca733ba6688b9c129a61cd1236aff0e27bcf98c28b0fbeea55a3d7c7193d644b2749f986bd46af8938e8faaeafbd9cec3612ab005bd7c3eeafe9a31279ca6102560666ba16136ff1452f850adb: +f051af426d0c3282fafc8bf912ade1c24211a95ad200e1eef549320e1cb1a252fa87955e0ea13dde49d83dc22e63a2bdf1076725c2cc7f93c76511f28e7944f2:fa87955e0ea13dde49d83dc22e63a2bdf1076725c2cc7f93c76511f28e7944f2:b48d9f84762b3bcc66e96d76a616fa8fe8e01695251f47cfc1b7b17d60dc9f90d576ef64ee7d388504e2c9079638165a889696471c989a876f8f13b63b58d531fea4dd1229fc631668a047bfae2da281feae1b6de3ebe280abe0a82ee00fbfdc22ce2d10e06a0492ff1404dfc094c40b203bf55721dd787ed4e91d5517aaf58d3bdd35d44a65ae6ba75619b339b650518cefcc17493de27a3b5d41788f87edbde72610f181bf06e208e0eb7cdfe881d91a2d6cc77aa19c0fcf330fedb44675d800eb8cff9505d8887544a503cbe373c4847b19e8f3995726efd6649858595c57ccaf0cbc9eb25de83ba046bc9f1838ac7b8953dd81b81ac0f68d0e9338cb55402552afb6bc16949351b926d151a82efc695e8d7da0dd55099366789718ccbf36030bd2c3c109399be26cdb8b9e2a155f3b2cb1bfa71ab69a23625a4ac118fe91cb2c19788cf52a71d730d576b421d96982a51a2991daec440cda7e6cc3282b8312714278b819bfe2387eb96aa91d40173034f428:b8f713578a64466719aceb432fce302a87cf066bf3e102a350616921a840964bfc7e685d8fd17455ac3eb4861edcb8979d35e3a4bd82a078cd707721d733400eb48d9f84762b3bcc66e96d76a616fa8fe8e01695251f47cfc1b7b17d60dc9f90d576ef64ee7d388504e2c9079638165a889696471c989a876f8f13b63b58d531fea4dd1229fc631668a047bfae2da281feae1b6de3ebe280abe0a82ee00fbfdc22ce2d10e06a0492ff1404dfc094c40b203bf55721dd787ed4e91d5517aaf58d3bdd35d44a65ae6ba75619b339b650518cefcc17493de27a3b5d41788f87edbde72610f181bf06e208e0eb7cdfe881d91a2d6cc77aa19c0fcf330fedb44675d800eb8cff9505d8887544a503cbe373c4847b19e8f3995726efd6649858595c57ccaf0cbc9eb25de83ba046bc9f1838ac7b8953dd81b81ac0f68d0e9338cb55402552afb6bc16949351b926d151a82efc695e8d7da0dd55099366789718ccbf36030bd2c3c109399be26cdb8b9e2a155f3b2cb1bfa71ab69a23625a4ac118fe91cb2c19788cf52a71d730d576b421d96982a51a2991daec440cda7e6cc3282b8312714278b819bfe2387eb96aa91d40173034f428: +a103e92672c65f81ea5da1fff1a4038788479e941d503a756f4a755201a57c1dee63a5b69641217acbaf3339da829ec071b9931e5987153514d30140837a7af4:ee63a5b69641217acbaf3339da829ec071b9931e5987153514d30140837a7af4:b1984e9eec085d524c1eb3b95c89c84ae085be5dc65c326e19025e1210a1d50edbbba5d1370cf15d68d687eb113233e0fba50f9433c7d358773950c67931db8296bbcbecec888e87e71a2f7579fad2fa162b85fb97473c456b9a5ce2956676969c7bf4c45679085b62f2c224fc7f458794273f6d12c5f3e0d06951824d1cca3e2f904559ed28e2868b366d79d94dc98667b9b5924268f3e39b1291e5abe4a758f77019dacbb22bd8196e0a83a5677658836e96ca5635055a1e63d65d036a68d87ac2fd283fdda390319909c5cc7680368848873d597f298e0c6172308030ffd452bb1363617b316ed7cd949a165dc8abb53f991aef3f3e9502c5dfe4756b7c6bfdfe89f5e00febdd6afb0402818f11cf8d1d5864fe9da1b86e39aa935831506cf2400ea7ed75bd9533b23e202fe875d7d9638c89d11cb2d6e6021ae6bd27c7754810d35cd3a61494f27b16fc794e2cd2f0d3453ada933865db78c579571f8fc5c5c6be8eaffce6a852e5b3b1c524c49313d427abcb:2aa2035c2ce5b5e6ae161e168f3ad0d6592bcf2c4a049d3ed342fceb56be9c7cb372027573ae0178e8878ebefca7b030327b8aad41857de58cb78e1a00cbac05b1984e9eec085d524c1eb3b95c89c84ae085be5dc65c326e19025e1210a1d50edbbba5d1370cf15d68d687eb113233e0fba50f9433c7d358773950c67931db8296bbcbecec888e87e71a2f7579fad2fa162b85fb97473c456b9a5ce2956676969c7bf4c45679085b62f2c224fc7f458794273f6d12c5f3e0d06951824d1cca3e2f904559ed28e2868b366d79d94dc98667b9b5924268f3e39b1291e5abe4a758f77019dacbb22bd8196e0a83a5677658836e96ca5635055a1e63d65d036a68d87ac2fd283fdda390319909c5cc7680368848873d597f298e0c6172308030ffd452bb1363617b316ed7cd949a165dc8abb53f991aef3f3e9502c5dfe4756b7c6bfdfe89f5e00febdd6afb0402818f11cf8d1d5864fe9da1b86e39aa935831506cf2400ea7ed75bd9533b23e202fe875d7d9638c89d11cb2d6e6021ae6bd27c7754810d35cd3a61494f27b16fc794e2cd2f0d3453ada933865db78c579571f8fc5c5c6be8eaffce6a852e5b3b1c524c49313d427abcb: +d47c1b4b9e50cbb71fd07d096d91d87213d44b024373044761c4822f9d9df880f4e1cb86c8ca2cfee43e58594a8778436d3ea519704e00c1bbe48bbb1c9454f8:f4e1cb86c8ca2cfee43e58594a8778436d3ea519704e00c1bbe48bbb1c9454f8:88d7009d51de3d337eef0f215ea66ab830ec5a9e6823761c3b92ad93ea341db92ece67f4ef4ceb84194ae6926c3d014b2d59781f02e0b32f9a611222cb9a5850c6957cb8079ae64e0832a1f05e5d1a3c572f9d08f1437f76bb3b83b52967c3d48c3576848891c9658d4959eb80656d26cdba0810037c8a18318ff122f8aa8985c773cb317efa2f557f1c3896bcb162df5d87681bb787e7813aa2dea3b0c564d646a92861f444ca1407efbac3d12432cbb70a1d0eaffb11741d3718fedee2b83036189a6fc45a52f74fa487c18fd264a7945f6c9e44b011f5d86613f1939b19f4f4fdf53234057be3f005ad64eebf3c8ffb58cb40956c4336df01d4424b706a0e561d601708d12485e21bcb6d799d8d1d044b400064ec0944501406e70253947006cabbdb2dd6bd8cee4497653d9113a44d4de9b68d4c526fca0b9b0c18fe50fb917fdd9a914fb816108a73a6b3fff9e654e69c9cfe02b05c6c1b9d15c4e65cf31018b8100d784633ee1888eee3572aafa6f189ea22d0:627e7ca7e34ed6331d62b9541c1ea9a9292be7b0a65d805e266b5122272a82db7d765acc7e2a290d685804922f91ed04a3c382c03ff21a1768f584413c4e5f0088d7009d51de3d337eef0f215ea66ab830ec5a9e6823761c3b92ad93ea341db92ece67f4ef4ceb84194ae6926c3d014b2d59781f02e0b32f9a611222cb9a5850c6957cb8079ae64e0832a1f05e5d1a3c572f9d08f1437f76bb3b83b52967c3d48c3576848891c9658d4959eb80656d26cdba0810037c8a18318ff122f8aa8985c773cb317efa2f557f1c3896bcb162df5d87681bb787e7813aa2dea3b0c564d646a92861f444ca1407efbac3d12432cbb70a1d0eaffb11741d3718fedee2b83036189a6fc45a52f74fa487c18fd264a7945f6c9e44b011f5d86613f1939b19f4f4fdf53234057be3f005ad64eebf3c8ffb58cb40956c4336df01d4424b706a0e561d601708d12485e21bcb6d799d8d1d044b400064ec0944501406e70253947006cabbdb2dd6bd8cee4497653d9113a44d4de9b68d4c526fca0b9b0c18fe50fb917fdd9a914fb816108a73a6b3fff9e654e69c9cfe02b05c6c1b9d15c4e65cf31018b8100d784633ee1888eee3572aafa6f189ea22d0: +fc0c32c5eb6c71ea08dc2b300cbcef18fdde3ea20f68f21733237b4ddaab900e47c37d8a080857eb8777a6c0a9a5c927303faf5c320953b5de48e462e12d0062:47c37d8a080857eb8777a6c0a9a5c927303faf5c320953b5de48e462e12d0062:a7b1e2db6bdd96b3d51475603537a76b42b04d7ebd24fe515a887658e4a352e22109335639a59e2534811f4753b70209d0e4698e9d926088826c14689681ea00fa3a2fcaa0047ced3ef287e6172502b215e56497614d86b4cb26bcd77a2e172509360ee58893d01c0d0fb4d4abfe4dbd8d2a2f54190fa2f731c1ceac6829c3ddc9bfb2ffd70c57ba0c2b22d2326fbfe7390db8809f73547ff47b86c36f2bf7454e678c4f1c0fa870bd0e30bbf3278ec8d0c5e9b64aff0af64babc19b70f4cf9a41cb8f95d3cde24f456ba3571c8f021d38e591dec05cb5d1ca7b48f9da4bd734b069a9fd106500c1f408ab7fe8e4a6e6f3ed64da0ed24b01e33df8475f95fa9ed71d04dd30b3cd823755a3401bf5afae10ee7e18ec6fe637c3793fd434b48d7145130447e00299101052558b506554ec9c399f62941c3f414cbc352caa345b930adecfaddac91ee53d1451a65e06201026325de07c931f69bba868a7c87ee23c604ec6794332917dfe2c5b69669b659706917f71eddf96:6887c6e2b98a82af5ee3dfa7ca2cb25d9c10745620a82956acba85cb57c8ec24279fa42f092359a1b6bbeafba050f14b6288209e6ef7bc1e0a2b872c1138f305a7b1e2db6bdd96b3d51475603537a76b42b04d7ebd24fe515a887658e4a352e22109335639a59e2534811f4753b70209d0e4698e9d926088826c14689681ea00fa3a2fcaa0047ced3ef287e6172502b215e56497614d86b4cb26bcd77a2e172509360ee58893d01c0d0fb4d4abfe4dbd8d2a2f54190fa2f731c1ceac6829c3ddc9bfb2ffd70c57ba0c2b22d2326fbfe7390db8809f73547ff47b86c36f2bf7454e678c4f1c0fa870bd0e30bbf3278ec8d0c5e9b64aff0af64babc19b70f4cf9a41cb8f95d3cde24f456ba3571c8f021d38e591dec05cb5d1ca7b48f9da4bd734b069a9fd106500c1f408ab7fe8e4a6e6f3ed64da0ed24b01e33df8475f95fa9ed71d04dd30b3cd823755a3401bf5afae10ee7e18ec6fe637c3793fd434b48d7145130447e00299101052558b506554ec9c399f62941c3f414cbc352caa345b930adecfaddac91ee53d1451a65e06201026325de07c931f69bba868a7c87ee23c604ec6794332917dfe2c5b69669b659706917f71eddf96: +a8d73d639a23cc6a967ef31bcabb5d063e53e1eab8fcc7cab9bc3a17fde9c2f88daa9f4c8b1a44691bf44521f2f7ca45dc7fc61f6a4ce6f98faa41c2a74977d1:8daa9f4c8b1a44691bf44521f2f7ca45dc7fc61f6a4ce6f98faa41c2a74977d1:fd1fac3d53313b11acd29f5a83ac11896dab2530fa47865b2295c0d99dd67c36ed8e5fa549150c794c5549efb5c1d69114d5d607b23285b7212afaab57846a54ae67b9e880e07b6586607cecf6d4eed516a3a75511fe367d88eb871e6d71b7d6aa1367a01421b1088fc2d75e44954b73625c52da8a3a183c60be9da6050f59a453caa53520593671728d431877bfaac913a765fb6a56b75290b2a8aaac34afb9217ba1b0d5850ba0fdabf80969def0feee794ceb60614e3368e63ef20e4c32d341ec9b0328ea9fe139207ed7a626ff08943b415233db7cfcc845c9b63121d4ed52ec3748ab6a1f36b2103c7dc7e9303acea4ba8af7a3e07184fb491e891ede84f0dc41cadc3973028e879acd2031afc29a16092868e2c7f539fc1b792edab195a25ab9830661346b39ef53915de4af52c421eaf172e9da76a08c283a52df907f705d7e8599c5baae0c2af380c1bb46f93484a03f28374324b278992b50b7afa02552cafa503f034f8d866e9b720271dd68ccb685a85fffd1:c4dcef1a2453939b364b340250c3129431431d5ba3f47670ab07ce680c69bf28b678627c76a6360fc40dc109aa7dea371b825e46134f624572182acf3957e70ffd1fac3d53313b11acd29f5a83ac11896dab2530fa47865b2295c0d99dd67c36ed8e5fa549150c794c5549efb5c1d69114d5d607b23285b7212afaab57846a54ae67b9e880e07b6586607cecf6d4eed516a3a75511fe367d88eb871e6d71b7d6aa1367a01421b1088fc2d75e44954b73625c52da8a3a183c60be9da6050f59a453caa53520593671728d431877bfaac913a765fb6a56b75290b2a8aaac34afb9217ba1b0d5850ba0fdabf80969def0feee794ceb60614e3368e63ef20e4c32d341ec9b0328ea9fe139207ed7a626ff08943b415233db7cfcc845c9b63121d4ed52ec3748ab6a1f36b2103c7dc7e9303acea4ba8af7a3e07184fb491e891ede84f0dc41cadc3973028e879acd2031afc29a16092868e2c7f539fc1b792edab195a25ab9830661346b39ef53915de4af52c421eaf172e9da76a08c283a52df907f705d7e8599c5baae0c2af380c1bb46f93484a03f28374324b278992b50b7afa02552cafa503f034f8d866e9b720271dd68ccb685a85fffd1: +79c7dcb7d59a8df6b2b2ba0413059d89680995c20e916da01b8f067dc60cdeb4298743c73918bd556b28f8d4824a09b814752a7aeae7ee04875c53f4d6b108d9:298743c73918bd556b28f8d4824a09b814752a7aeae7ee04875c53f4d6b108d9:5fe202f5b33b7788810d2508a13b3114d69b8596e6eacda05a04a2eb597fa3279c208b5a5b65daacb699f144e1d660e78e139b578331abec5c3c35334454f03e832c8d6e2984df5d450ecb5d33582a78808a9c78f26ebcd1244ef52e3fa6dca115c1f0cb56e38eae0e5b39f5fd863dffd0b2fb5b958f2d739db312fc667a17b031c4c9f8c5a2ad577984cc4146c437580efd2152173fe0d5782cc2ae9831a8d9a04177256018ff7631e0b0d8a99cb28f008b320421e27a74c31359188663456d85e098c1ebd281701097b6ae5a871e5ccc02058a501416cb91c12cef5be6f1914370e563f1a1b2aa41f4b8ee84cd32a1d509e529787d14a445438d807ecd620e2fa26de0da6426864784d4a28f54103e609283b99ee9b2b699c980bbb7882c3ea68ddc90802ac232f2c8e84291987bf3c5240921b59cfa214969317673d0be7f34b1ca0e15ea73c7175401ce550be106b49e62f8db68695e740e0f3a3556a19f3c8e6b91ac1cc23e863fcd0f0d9eb7047aa631e0d2eb9bcc6b:7b7cbe44c771e4371bae13b0722babcc1064155732962f407cba2acd35381d42210bece822f4681121fd4dab745a1f3077922fba1a78045b712902baccac660e5fe202f5b33b7788810d2508a13b3114d69b8596e6eacda05a04a2eb597fa3279c208b5a5b65daacb699f144e1d660e78e139b578331abec5c3c35334454f03e832c8d6e2984df5d450ecb5d33582a78808a9c78f26ebcd1244ef52e3fa6dca115c1f0cb56e38eae0e5b39f5fd863dffd0b2fb5b958f2d739db312fc667a17b031c4c9f8c5a2ad577984cc4146c437580efd2152173fe0d5782cc2ae9831a8d9a04177256018ff7631e0b0d8a99cb28f008b320421e27a74c31359188663456d85e098c1ebd281701097b6ae5a871e5ccc02058a501416cb91c12cef5be6f1914370e563f1a1b2aa41f4b8ee84cd32a1d509e529787d14a445438d807ecd620e2fa26de0da6426864784d4a28f54103e609283b99ee9b2b699c980bbb7882c3ea68ddc90802ac232f2c8e84291987bf3c5240921b59cfa214969317673d0be7f34b1ca0e15ea73c7175401ce550be106b49e62f8db68695e740e0f3a3556a19f3c8e6b91ac1cc23e863fcd0f0d9eb7047aa631e0d2eb9bcc6b: +b9ced0412593fefed95e94ac965e5b23ff9d4b0e797db02bf497994d3b793e60c1629a723189959337f5535201e5d395ba0a03ea8c17660d0f8b6f6e6404bb12:c1629a723189959337f5535201e5d395ba0a03ea8c17660d0f8b6f6e6404bb12:555bb39c1899d57cabe428064c2d925f5fc4cf7059b95fb89a8e9e3a7e426c6c922d9e4d76984ea2383cabb4f2befd89c1f20eaa8a00dbe787cfa70ae2ae6aa90331cbbe580fa5a02184ed05e6c8e89d576af28aeeaf7c4e2500f358a00971a0a75920e854849bf332142975404f598c32e96982043d992bcd1a4fe819bb5634ad03467afc4ce05073f88ba1ba4ae8653a04665cf3f71690fe13343885bc5ebc0e5e62d882f43b7c68900ac9438bf4a81ce90169ec129ee63e2c675a1a5a67e27cc798c48cc23f51078f463b3b7cc14e3bcfd2e9b82c75240934cbdc50c4308f282f193122995606f40135100a291c55afdf8934eb8b61d81421674124dec3b88f9a73110a9e616f5b826b9d343f3ac0e9d7bdf4fd8b648b40f0098b3897a3a1cd65a64570059b8bc5c6743883074c88623c1f5a88c58969e21c692aca236833d3470b3eb09815e1138e9d0650c390eee977422193b00918be8a97cc6199b451b05b5730d1d13358cf74610678f7ac7f7895cc2efc456e03873b:f1b797ded8a6942b12626848340fb719fcddafd98f33e2992d357bfdd35933c7ac561e5b2f939464338c5666854ca885c4d046eb2c54e48a1b5ed266ad34de05555bb39c1899d57cabe428064c2d925f5fc4cf7059b95fb89a8e9e3a7e426c6c922d9e4d76984ea2383cabb4f2befd89c1f20eaa8a00dbe787cfa70ae2ae6aa90331cbbe580fa5a02184ed05e6c8e89d576af28aeeaf7c4e2500f358a00971a0a75920e854849bf332142975404f598c32e96982043d992bcd1a4fe819bb5634ad03467afc4ce05073f88ba1ba4ae8653a04665cf3f71690fe13343885bc5ebc0e5e62d882f43b7c68900ac9438bf4a81ce90169ec129ee63e2c675a1a5a67e27cc798c48cc23f51078f463b3b7cc14e3bcfd2e9b82c75240934cbdc50c4308f282f193122995606f40135100a291c55afdf8934eb8b61d81421674124dec3b88f9a73110a9e616f5b826b9d343f3ac0e9d7bdf4fd8b648b40f0098b3897a3a1cd65a64570059b8bc5c6743883074c88623c1f5a88c58969e21c692aca236833d3470b3eb09815e1138e9d0650c390eee977422193b00918be8a97cc6199b451b05b5730d1d13358cf74610678f7ac7f7895cc2efc456e03873b: +81da168f02d46bb87cda845da43f8a6cba2c016878d6f49c6f061a60f155a04aaff86e98093ca4c71b1b804c5fe451cfdf868250dea30345fa4b89bb09b6a53b:aff86e98093ca4c71b1b804c5fe451cfdf868250dea30345fa4b89bb09b6a53b:6bc6726a34a64aae76ab08c92b179e54ff5d2e65eb2c6c659ae8703cc245cbc2cf45a12b22c468ae61fd9a6627ad0626c9b1e5af412cb483eaee1db11b29f0a510c13e38020e09ae0eee762537a3e9d1a0c7b033d097fdc1f4f82629a9de9ef38da1cf96a940357d5f2e0e7e8dbc29db728a1e6aad876e5e053113d06420272b87cf0c40dfe03a544de96c7aea13ba0029b57b48d99dcc6a650492d78c4cdd1b28e1a115a7e3e7a7cb21333d4ff80858dfb67782c16354b8716596560d7d8e389eb15a052a0bf5d16eb54fb3e4973ad4984e72a187f5347d5b262c32b1647e42b6a53837096cc78c2a05ce1c6e12493a03f1a667584cb97f4fcd57ee944c65b7eed25f7ae0f3f6cede173fdfacf5af1db143730d18096664914ba4cfc6966f392022781c66a9417ca2680b51f63e4fba424ecfdbc6a2f01787d0e7484f8a8ab390aeaa6d1f7ed325d82feaa1692a4984fae43da87329b045da8f0a4f56b695aa935de152ce0385153720979a2b7006d405fcb0fba09e23b85fd19b:4aaca947e3f22cc8b8588ee030ace8f6b5f5711c2974f20cc18c3b655b07a5bc1366b59a1708032d12cae01ab794f8cbcc1a330874a75035db1d69422d2fc00c6bc6726a34a64aae76ab08c92b179e54ff5d2e65eb2c6c659ae8703cc245cbc2cf45a12b22c468ae61fd9a6627ad0626c9b1e5af412cb483eaee1db11b29f0a510c13e38020e09ae0eee762537a3e9d1a0c7b033d097fdc1f4f82629a9de9ef38da1cf96a940357d5f2e0e7e8dbc29db728a1e6aad876e5e053113d06420272b87cf0c40dfe03a544de96c7aea13ba0029b57b48d99dcc6a650492d78c4cdd1b28e1a115a7e3e7a7cb21333d4ff80858dfb67782c16354b8716596560d7d8e389eb15a052a0bf5d16eb54fb3e4973ad4984e72a187f5347d5b262c32b1647e42b6a53837096cc78c2a05ce1c6e12493a03f1a667584cb97f4fcd57ee944c65b7eed25f7ae0f3f6cede173fdfacf5af1db143730d18096664914ba4cfc6966f392022781c66a9417ca2680b51f63e4fba424ecfdbc6a2f01787d0e7484f8a8ab390aeaa6d1f7ed325d82feaa1692a4984fae43da87329b045da8f0a4f56b695aa935de152ce0385153720979a2b7006d405fcb0fba09e23b85fd19b: +af2e60da0f29bb1614fc3f193cc353331986b73f3f9a0aec9421b9473d6a4b6ac8bfe2835822199c6127b806fabeef0cb9ff59f3c81ff0cb89c556f55106af6a:c8bfe2835822199c6127b806fabeef0cb9ff59f3c81ff0cb89c556f55106af6a:7dbb77b88bda94f344416a06b096566c6e8b393931a8243a6cab75c361fde7dc536aec40cded83296a89e8c3bef7d787cfc49401a7b9183f138d5000619ff073c05e2f841d6008358f10a2da7dcfac3d4d70c20d2ec34c7b6d5cd1a734d6bbb11c5fd8d2bce32ac810ef82b4188aa8ea3cfc3032233dc0e2600e9db6e18bc22b10044a31c15baceaf5554de89d2a3466807f244414d080ff2963956c6e83c8e144ed0066088b476ddcb564403447d9159f9089aba2b4d5575c4d8ae66fc8690e7349ed40832e6369c024563ec493bfcc0fc9ac787ac841397fe133167283d80c42f006a99d39e82979da3fa9334bd9ede0d14b41b7466bcebbe8171bc804a645d3723274a1b92bf82fd993358744de92441903d436fd47f23d40052a3829367f202f0553b5e49b76c5e03fa6ce7c3cf5eeb21de967bec4dd355925384ebf96697e823762bac4d43a767c241a4cef724a970d00ff3a8ab3b83eed840075c74e90f306e330013260962161e9d0910de183622ce9a6b8d5144280550fc7:50f9f941a8da9f6240f76d2fa3b06dd6b2292ed32d1c05218097d34d8a19dfe553f76ae3c6b4a2ed20852128461540decf418f52d38e64037eec7771bd1afe007dbb77b88bda94f344416a06b096566c6e8b393931a8243a6cab75c361fde7dc536aec40cded83296a89e8c3bef7d787cfc49401a7b9183f138d5000619ff073c05e2f841d6008358f10a2da7dcfac3d4d70c20d2ec34c7b6d5cd1a734d6bbb11c5fd8d2bce32ac810ef82b4188aa8ea3cfc3032233dc0e2600e9db6e18bc22b10044a31c15baceaf5554de89d2a3466807f244414d080ff2963956c6e83c8e144ed0066088b476ddcb564403447d9159f9089aba2b4d5575c4d8ae66fc8690e7349ed40832e6369c024563ec493bfcc0fc9ac787ac841397fe133167283d80c42f006a99d39e82979da3fa9334bd9ede0d14b41b7466bcebbe8171bc804a645d3723274a1b92bf82fd993358744de92441903d436fd47f23d40052a3829367f202f0553b5e49b76c5e03fa6ce7c3cf5eeb21de967bec4dd355925384ebf96697e823762bac4d43a767c241a4cef724a970d00ff3a8ab3b83eed840075c74e90f306e330013260962161e9d0910de183622ce9a6b8d5144280550fc7: +605f90b53d8e4a3b48b97d745439f2a0807d83b8502e8e2979f03e8d376ac9feaa3fae4cfa6f6bfd14ba0afa36dcb1a2656f36541ad6b3e67f1794b06360a62f:aa3fae4cfa6f6bfd14ba0afa36dcb1a2656f36541ad6b3e67f1794b06360a62f:3bcdcac292ac9519024aaecee2b3e999ff5d3445e9f1eb60940f06b91275b6c5db2722ed4d82fe89605226530f3e6b0737b308cde8956184944f388a80042f6cba274c0f7d1192a0a96b0da6e2d6a61b76518fbee555773a414590a928b4cd545fccf58172f35857120eb96e75c5c8ac9ae3add367d51d34ac403446360ec10f553ea9f14fb2b8b78cba18c3e506b2f04097063a43b2d36431cce02caf11c5a4db8c821752e52985d5af1bfbf4c61572e3fadae3ad424acd81662ea5837a1143b9669391d7b9cfe230cffb3a7bb03f6591c25a4f01c0d2d4aca3e74db1997d3739c851f0327db919ff6e77f6c8a20fdd3e1594e92d01901ab9aef194fc893e70d78c8ae0f480001a515d4f9923ae6278e8927237d05db23e984c92a683882f57b1f1882a74a193ab6912ff241b9ffa662a0d47f29205f084dbde845baaeb5dd36ae6439a437642fa763b57e8dbe84e55813f0151e97e5b9de768b234b8db15c496d4bfcfa1388788972bb50ce030bc6e0ccf4fa7d00d343782f6ba8de0:dd0212e63288cbe14a4569b4d891da3c7f92727c5e7f9a801cf9d6827085e7095b669d7d45f882ca5f0745dccd24d87a57181320191e5b7a47c3f7f2dccbd7073bcdcac292ac9519024aaecee2b3e999ff5d3445e9f1eb60940f06b91275b6c5db2722ed4d82fe89605226530f3e6b0737b308cde8956184944f388a80042f6cba274c0f7d1192a0a96b0da6e2d6a61b76518fbee555773a414590a928b4cd545fccf58172f35857120eb96e75c5c8ac9ae3add367d51d34ac403446360ec10f553ea9f14fb2b8b78cba18c3e506b2f04097063a43b2d36431cce02caf11c5a4db8c821752e52985d5af1bfbf4c61572e3fadae3ad424acd81662ea5837a1143b9669391d7b9cfe230cffb3a7bb03f6591c25a4f01c0d2d4aca3e74db1997d3739c851f0327db919ff6e77f6c8a20fdd3e1594e92d01901ab9aef194fc893e70d78c8ae0f480001a515d4f9923ae6278e8927237d05db23e984c92a683882f57b1f1882a74a193ab6912ff241b9ffa662a0d47f29205f084dbde845baaeb5dd36ae6439a437642fa763b57e8dbe84e55813f0151e97e5b9de768b234b8db15c496d4bfcfa1388788972bb50ce030bc6e0ccf4fa7d00d343782f6ba8de0: +9e2c3d189838f4dd52ef0832886874c5ca493983ddadc07cbc570af2ee9d6209f68d3b81e73557ee1f08bd2d3f46a4718256a0f3cd8d2e03eb8fe882aab65c69:f68d3b81e73557ee1f08bd2d3f46a4718256a0f3cd8d2e03eb8fe882aab65c69:19485f5238ba82eadf5eff14ca75cd42e5d56fea69d5718cfb5b1d40d760899b450e66884558f3f25b7c3de9afc4738d7ac09da5dd4689bbfac07836f5e0be432b1ddcf1b1a075bc9815d0debc865d90bd5a0c5f5604d9b46ace816c57694ecc3d40d8f84df0ede2bc4d577775a027f725de0816f563fa88f88e077720ebb6ac02574604819824db7474d4d0b22cd1bc05768e0fb867ca1c1a7b90b34ab7a41afc66957266ac0c915934aaf31c0cf6927a4f03f23285e6f24afd5813849bb08c203ac2d0336dcbf80d77f6cf7120edfbcdf181db107ec8e00f32449c1d3f5c049a92694b4ea2c6ebe5e2b0f64b5ae50ad3374d246b3270057e724a27cf263b633ab65ecb7f5c266b8007618b10ac9ac83db0febc04fd863d9661ab6e58494766f71b9a867c5a7a4555f667c1af2e54588f162a41ce756407cc4161d607b6e0682980934caa1bef036f7330d9eef01ecc553583fee5994e533a46ca916f60f8b961ae01d20f7abf0df6141b604de733c636b42018cd5f1d1ef4f84cee40fc:38a31b6b465084738262a26c065fe5d9e2886bf9dd35cde05df9bad0cc7db401c750aa19e66090bce25a3c721201e60502c8c10454346648af065eab0ee7d80f19485f5238ba82eadf5eff14ca75cd42e5d56fea69d5718cfb5b1d40d760899b450e66884558f3f25b7c3de9afc4738d7ac09da5dd4689bbfac07836f5e0be432b1ddcf1b1a075bc9815d0debc865d90bd5a0c5f5604d9b46ace816c57694ecc3d40d8f84df0ede2bc4d577775a027f725de0816f563fa88f88e077720ebb6ac02574604819824db7474d4d0b22cd1bc05768e0fb867ca1c1a7b90b34ab7a41afc66957266ac0c915934aaf31c0cf6927a4f03f23285e6f24afd5813849bb08c203ac2d0336dcbf80d77f6cf7120edfbcdf181db107ec8e00f32449c1d3f5c049a92694b4ea2c6ebe5e2b0f64b5ae50ad3374d246b3270057e724a27cf263b633ab65ecb7f5c266b8007618b10ac9ac83db0febc04fd863d9661ab6e58494766f71b9a867c5a7a4555f667c1af2e54588f162a41ce756407cc4161d607b6e0682980934caa1bef036f7330d9eef01ecc553583fee5994e533a46ca916f60f8b961ae01d20f7abf0df6141b604de733c636b42018cd5f1d1ef4f84cee40fc: +575f8fb6c7465e92c250caeec1786224bc3eed729e463953a394c9849cba908f71bfa98f5bea790ff183d924e6655cea08d0aafb617f46d23a17a657f0a9b8b2:71bfa98f5bea790ff183d924e6655cea08d0aafb617f46d23a17a657f0a9b8b2:2cc372e25e53a138793064610e7ef25d9d7422e18e249675a72e79167f43baf452cbacb50182faf80798cc38597a44b307a536360b0bc1030f8397b94cbf147353dd2d671cb8cab219a2d7b9eb828e9635d2eab6eb08182cb03557783fd282aaf7b471747c84acf72debe4514524f8447bafccccec0a840feca9755ff9adb60301c2f25d4e3ba621df5ad72100c45d7a4b91559c725ab56bb29830e35f5a6faf87db23001f11ffba9c0c15440302065827a7d7aaaeab7b446abce333c0d30c3eae9c9da63eb1c0391d4269b12c45b660290611ac29c91dbd80dc6ed302a4d191f2923922f032ab1ac10ca7323b5241c5751c3c004ac39eb1267aa10017ed2dac6c934a250dda8cb06d5be9f563b827bf3c8d95fd7d2a7e7cc3acbee92538bd7ddfba3ab2dc9f791fac76cdf9cd6a6923534cf3e067108f6aa03e320d954085c218038a70cc768b972e49952b9fe171ee1be2a52cd469b8d36b84ee902cd9410db2777192e90070d2e7c56cb6a45f0a839c78c219203b6f1b33cb4504c6a7996427741e6874cf45c5fa5a38765a1ebf1796ce16e63ee509612c40f088cbceffa3affbc13b75a1b9c02c61a180a7e83b17884fe0ec0f2fe57c47e73a22f753eaf50fca655ebb19896b827a3474911c67853c58b4a78fd085a23239b9737ef8a7baff11ddce5f2cae0543f8b45d144ae6918b9a75293ec78ea618cd2cd08c971301cdfa0a9275c1bf441d4c1f878a2e733ce0a33b6ecdacbbf0bdb5c3643fa45a013979cd01396962897421129a88757c0d88b5ac7e44fdbd938ba4bc37de4929d53751fbb43d4e09a80e735244acada8e6749f77787f33763c7472df52934591591fb226c503c8be61a920a7d37eb1686b62216957844c43c484e58745775553:903b484cb24bc503cdced844614073256c6d5aa45f1f9f62c7f22e5649212bc1d6ef9eaa617b6b835a6de2beff2faac83d37a4a5fc5cc3b556f56edde2651f022cc372e25e53a138793064610e7ef25d9d7422e18e249675a72e79167f43baf452cbacb50182faf80798cc38597a44b307a536360b0bc1030f8397b94cbf147353dd2d671cb8cab219a2d7b9eb828e9635d2eab6eb08182cb03557783fd282aaf7b471747c84acf72debe4514524f8447bafccccec0a840feca9755ff9adb60301c2f25d4e3ba621df5ad72100c45d7a4b91559c725ab56bb29830e35f5a6faf87db23001f11ffba9c0c15440302065827a7d7aaaeab7b446abce333c0d30c3eae9c9da63eb1c0391d4269b12c45b660290611ac29c91dbd80dc6ed302a4d191f2923922f032ab1ac10ca7323b5241c5751c3c004ac39eb1267aa10017ed2dac6c934a250dda8cb06d5be9f563b827bf3c8d95fd7d2a7e7cc3acbee92538bd7ddfba3ab2dc9f791fac76cdf9cd6a6923534cf3e067108f6aa03e320d954085c218038a70cc768b972e49952b9fe171ee1be2a52cd469b8d36b84ee902cd9410db2777192e90070d2e7c56cb6a45f0a839c78c219203b6f1b33cb4504c6a7996427741e6874cf45c5fa5a38765a1ebf1796ce16e63ee509612c40f088cbceffa3affbc13b75a1b9c02c61a180a7e83b17884fe0ec0f2fe57c47e73a22f753eaf50fca655ebb19896b827a3474911c67853c58b4a78fd085a23239b9737ef8a7baff11ddce5f2cae0543f8b45d144ae6918b9a75293ec78ea618cd2cd08c971301cdfa0a9275c1bf441d4c1f878a2e733ce0a33b6ecdacbbf0bdb5c3643fa45a013979cd01396962897421129a88757c0d88b5ac7e44fdbd938ba4bc37de4929d53751fbb43d4e09a80e735244acada8e6749f77787f33763c7472df52934591591fb226c503c8be61a920a7d37eb1686b62216957844c43c484e58745775553: diff --git a/ed25519-dalek/VALIDATIONVECTORS b/ed25519-dalek/VALIDATIONVECTORS new file mode 100644 index 000000000..f08d2919b --- /dev/null +++ b/ed25519-dalek/VALIDATIONVECTORS @@ -0,0 +1,11136 @@ +[ + { + "_comment": "This test vector comes from https://github.com/C2SP/CCTV/blob/5ea85644bd035c555900a2f707f7e4c31ea65ced/ed25519vectors/ed25519vectors.json", + "number": 0, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 1, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 2, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 3, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 4, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "00000000000000000000000000000000000000000000000000000000000000005e176f12cfb0d4e6eb6929b19ae4c998ef05c1c2cf628a9b1fa1c21312627108", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 5, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "00000000000000000000000000000000000000000000000000000000000000009472a69cd9a701a50d130ed52189e2455b23767db52cacb8716fb896ffeeac09", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 6, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56bc02e2b9e63e385c058bf62b14b3a2b29ccefe8e38ddb536bc3f9865320a3d801", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 7, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56bbbfd00bd9c259d8d222d15e67a3d8228585050dbb9b9585be20d8fadc721da03", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 8, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 9, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 10, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 11, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 12, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 13, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 14, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 15, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 16, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f1cb421dfbd92aa6c30d550bff53c81cf650ace6deb96a8ec22d2fef84dbbe20b", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 17, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fad7a355469b5c87e550469f6b2de409ee723acd584bf35f86b80c384e8ceb702", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 18, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f5e176f12cfb0d4e6eb6929b19ae4c998ef05c1c2cf628a9b1fa1c21312627108", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 19, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f9472a69cd9a701a50d130ed52189e2455b23767db52cacb8716fb896ffeeac09", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 20, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 21, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 22, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 23, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 24, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 25, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 26, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "000000000000000000000000000000000000000000000000000000000000008075b3d7e9547febbdbf3fde21df901c7ca1fc59e8b689a4ae283919e78cf62b03", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 27, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "0000000000000000000000000000000000000000000000000000000000000080050abffcd4d8ccbb4b8d6bf6649f5aa99e8de5cc182a7409633856ff53f49e0c", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 28, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a94639734cf989e314e9e049fc01a3864d191fed8f231b12fee6fa50aaadba44b0e", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 29, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a94732d9e0279fe001d90327efa319816e3e4506b78432b8b4e1f2fdc4b960d700f", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 30, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 31, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 32, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 33, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 34, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 35, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 36, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 37, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 38, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7117c2ec783065c50f2c930cfc9d318c9737991acb260b49e2ca815474532709", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 39, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1f5fae114eb0c534b5aed0a892d0a0e1d429df6a025c5ae08012e0ffce78310c", + "msg": "ed25519vectors 27", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 40, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff75b3d7e9547febbdbf3fde21df901c7ca1fc59e8b689a4ae283919e78cf62b03", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 41, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff050abffcd4d8ccbb4b8d6bf6649f5aa99e8de5cc182a7409633856ff53f49e0c", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 42, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 39", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 43, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 44, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 45, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 46, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 47, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 48, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "0100000000000000000000000000000000000000000000000000000000000000edfd6f478b59eab2545cf8f3d48c6574d2b4e8abd948148da5c62479113b8d0f", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_component_A" + ] + }, + { + "number": 49, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "0100000000000000000000000000000000000000000000000000000000000000879e8751046a31d163df68051bbd909e6d26c8414883ba3475bf00e17c1e7b04", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 50, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350608f32d206a7c0b7efa9a59e66546e8f1f599ef843fb502c9cc3c4ae8b7c11e05", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_component_A" + ] + }, + { + "number": 51, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a3506030b03796b78f7afeadfccaedc9d09ce6d487d1ece1f16b1ae2b59b7e5c40603", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 52, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 53, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 54, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 55, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 56, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 57, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 58, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 59, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 60, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "0100000000000000000000000000000000000000000000000000000000000080c85efbb96e35e1b671722d5d8de687d4e148ea15ec566be6a1f3cfb8a10a9d06", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 61, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "01000000000000000000000000000000000000000000000000000000000000804b18627cef9707137b02358c8b73769381269bf7cac9c473483c83c46a615d09", + "msg": "ed25519vectors 29", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 62, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "0100000000000000000000000000000000000000000000000000000000000080edfd6f478b59eab2545cf8f3d48c6574d2b4e8abd948148da5c62479113b8d0f", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 63, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "0100000000000000000000000000000000000000000000000000000000000080879e8751046a31d163df68051bbd909e6d26c8414883ba3475bf00e17c1e7b04", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 64, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 65, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 66, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f97f5fc03f658b5b733cf20c4ea5577e8e5988ee90cb2a3c919c2a05dd2fcde04", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 67, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f2786a72a405895f7b3b4752eac49c8973270173a495ec475b34933dc05d7e904", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 68, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedfd6f478b59eab2545cf8f3d48c6574d2b4e8abd948148da5c62479113b8d0f", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 69, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f879e8751046a31d163df68051bbd909e6d26c8414883ba3475bf00e17c1e7b04", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 70, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 71, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 72, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff87a0755495e4b763c07eeebdd510eb7d7b167bf13bf1489785fa2be61543890e", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 73, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffafdefad9d081387fa502d650442ed15619fc936d41444fd5c4292691a16f1d06", + "msg": "ed25519vectors 25", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 74, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedfd6f478b59eab2545cf8f3d48c6574d2b4e8abd948148da5c62479113b8d0f", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 75, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff879e8751046a31d163df68051bbd909e6d26c8414883ba3475bf00e17c1e7b04", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 76, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 77, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 78, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 79, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 22", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 80, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 81, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 82, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 83, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 84, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05aa80ce94a6f94b9e01abfc089182b3d85548437339d7ad2e3d804f60a87a8605", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 85, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d21bba68b891fdce7ad8fa923bc884aa33eeea4f341ae5ee527cb7d99a23040ab0e", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 86, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 21", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 87, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 88, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 89, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 90, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 91, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc852cd7e84d7f4609fc08f069561f201161369e38e508562ea21f0c6f582873f500", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 92, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f11efaa29ea31bbaf7b896625bd0fbe78f6bb7f3cf093407794dd2cd6096e3fd103", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 93, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 94, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 95, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 96, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 97, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 98, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a57f5931a402c5cda578690e33a33ba0458eec51036b5c01c5cd486a58c0d290f", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 99, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee8093711b51dce8d4ef35fd239caecd236d2ca58604bc779880708568423a9700", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 100, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 23", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 101, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 102, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 103, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 104, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 105, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa6913952aa42c06cd8759d2175fa60c29fba5d9767291b8cda0f58d186320d604", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 106, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de0b20981a60242434fb7351f2ebc29b90bbd45c90eae5377379d780156e297409", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 107, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 108, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 109, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 110, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 111, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 112, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 113, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 114, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f5639fc07db8ae613081841876d58857e3014e5f2efdeec154ae0318b2586f601", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 115, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f1509e3a68b74a8fd2b4e271b7c584a0e3cb857b6c3473e8fdf3436a2a2d0cc04", + "msg": "ed25519vectors 31", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 116, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9f09162ea121fb3e2d1270dd30ade8b5bcfdcfd1dcf624ac22cf60af9610c6c02", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 117, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9ecf8dc78bf5c647c714a00acf11719551952b488c2c9df967c7d48b479420e0e", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 118, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 119, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 120, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 121, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 20", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 122, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 123, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 124, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 39", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 125, + "key": "0000000000000000000000000000000000000000000000000000000000000000", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 126, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff24d6a9e426c0871c55d7163f0fe34e776bec47e582548d9bba074102c81fce02", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 127, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff35036672b82d501137113e048abbd4f44090e3aaa7e262f555e3e78fec78e507", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 128, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5639fc07db8ae613081841876d58857e3014e5f2efdeec154ae0318b2586f601", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 129, + "key": "10eb7c3acfb2bed3e0d6ab89bf5a3d6afddd1176ce4812e38d9fd485058fdb1f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1509e3a68b74a8fd2b4e271b7c584a0e3cb857b6c3473e8fdf3436a2a2d0cc04", + "msg": "ed25519vectors 31", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 130, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 131, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 132, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 133, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 134, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 135, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 136, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "00000000000000000000000000000000000000000000000000000000000000005635c691e820339382bb85c151038e4b1815ceaaeb76bfa90cb7bf3382ec510b", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 137, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "0000000000000000000000000000000000000000000000000000000000000000d2abf247722e6b4213f1890beb32c730b02a929e22a1a8de5fe84fa1e8bec40b", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 138, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b2d155343b4933733be02419ac0ad255666ea0ad80d9998cc7c6086f4cf453507", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 139, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b25e180a8f97db7419c7adb79f5063f045cb18fc6af517852e3687be84bd7e803", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 140, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 141, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 142, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 143, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 27", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 144, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 145, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 146, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 21", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 147, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 148, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f9b8a1787d3747a0740ed283e74e2c478d4b681f0aa2676a5c694889696138205", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 149, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f938dd30260e6bce7f9422c05def45ba6732946a9f1236aff3a187902d7128808", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 150, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f5635c691e820339382bb85c151038e4b1815ceaaeb76bfa90cb7bf3382ec510b", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 151, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fd2abf247722e6b4213f1890beb32c730b02a929e22a1a8de5fe84fa1e8bec40b", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 152, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 153, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 154, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 155, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 156, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 157, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 158, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "0000000000000000000000000000000000000000000000000000000000000080fc5d42211dbee053d3bac3913e05f32c8026274b1926b55706c621eefaa7c805", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 159, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "00000000000000000000000000000000000000000000000000000000000000807ecde75a10d2cf5c13c49b78e4026148484c48d151616ae934cf4ec66f0e3702", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 160, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9468966bbfc7bcce00aeebb561f0197cb0b823ec3f17056333fce73486dc3cbe06", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 161, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9426c8d0de0953df46bc0049fed1261b7c06189e84e5c14985454485ba5a4fb501", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 162, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 163, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 164, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 165, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 166, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 167, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 168, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 169, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 170, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff28d80ed8be5636443022fa8a24dbe8f649bea0e6edc5a6a65b29db14caa1b80e", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 171, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3cb05c8a71d4d341e74340536fea96cd93577c8044879400da68b577ed7d7207", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 172, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "edfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5d42211dbee053d3bac3913e05f32c8026274b1926b55706c621eefaa7c805", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 173, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ecde75a10d2cf5c13c49b78e4026148484c48d151616ae934cf4ec66f0e3702", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 174, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 175, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 176, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 177, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 178, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 179, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 180, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "0100000000000000000000000000000000000000000000000000000000000000164aae8ae8d165867053dd1c3806319e064523aa053b1d7003463de8c5fcba0f", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A" + ] + }, + { + "number": 181, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "0100000000000000000000000000000000000000000000000000000000000000f94cd85e18f5b89bfc21b4d29b43e30038f84228fe81eff5b7d735073ba29909", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 182, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a35063cb743a485cffaa684d0d66a5ae347d17a5638e90dc2be541023114a5961f805", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_component_A" + ] + }, + { + "number": 183, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a35061fc409b236539503e78560d6183d748c8a6d3e635e87c9397531394f3cb3f902", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 184, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 185, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 186, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 34", + "flags": [ + "low_order_A", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 187, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 188, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 189, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 190, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 191, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 192, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "0100000000000000000000000000000000000000000000000000000000000080001bb260c36aea3c94ff5785b5a44d99a88c33e02dceb9fdfe9ae57aad604b03", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 193, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "0100000000000000000000000000000000000000000000000000000000000080b38e0b9773175cdae4741a4973fa1ac1bbcd7263c5f28a3cf2a5bedca4d31106", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 194, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "0100000000000000000000000000000000000000000000000000000000000080164aae8ae8d165867053dd1c3806319e064523aa053b1d7003463de8c5fcba0f", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 195, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "0100000000000000000000000000000000000000000000000000000000000080f94cd85e18f5b89bfc21b4d29b43e30038f84228fe81eff5b7d735073ba29909", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 196, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 197, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 198, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f522d2c5eddb07da5dc5f2207a513322ee5860d4b5f94103ca604060d3672f402", + "msg": "ed25519vectors 24", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 199, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffba7ac98b395cf8ffaecd3676b362f25f404252b7cbf07837b6bf780d2897b0c", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 200, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f164aae8ae8d165867053dd1c3806319e064523aa053b1d7003463de8c5fcba0f", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 201, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ff94cd85e18f5b89bfc21b4d29b43e30038f84228fe81eff5b7d735073ba29909", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 202, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 203, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 204, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe29cfd8591462aa4ba19c79672667e0665bfb240f29de8ab80b43497f12b340e", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 205, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbe2295259b59b14675c8403202c2fe88c9d9eaf761f00f67db0dd24b67b09b01", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 206, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff164aae8ae8d165867053dd1c3806319e064523aa053b1d7003463de8c5fcba0f", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 207, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "eefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94cd85e18f5b89bfc21b4d29b43e30038f84228fe81eff5b7d735073ba29909", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 208, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 209, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 210, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 22", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 211, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 212, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 213, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 214, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 215, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 216, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05486fb2a5d2cb002b460db9c56c36954aebaa4e6062f300beebb2749e32274106", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 217, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d21b9d3fadc566a3fb952d94b93f7add4e9e017bcf843058986b5ec9bec0638ba05", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 218, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 219, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 220, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 221, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 222, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 223, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85b4f602297e877cbbe446de71c9868e98c04a56e9bc409f60beaa400e7c633600", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 224, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f11a106ed973e5cdc868eace49e639ee52f4ca53fc715f8ec612e0917f4204f920e", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 225, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 226, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 227, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 228, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 229, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 230, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a1873e9ebb328202c033407e8b9f67e528093ea899da61e9ede6999b358de0f08", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 231, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee1eb53c48312206ed56a5f83ef3fd7b6ca3012fd4c2fb08aceea83ad251358000", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 232, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 233, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 234, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 235, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 236, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 237, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0826b7ce39c8491fabdd6759f89e5a424c344ecb7d94636b268e61a2a90ab20a", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 238, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72deff8aa11cfa5ea34bc35398cf040ad303d96d5b5bd818963f69cdda872d536904", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 239, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 240, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 241, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 242, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 243, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 244, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 245, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 38", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 246, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f109d35eafa88df6c5770dd5ef7023b3965891d0c4050d2e9c7906613229d6c0e", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 247, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f86e5c516a446a3c8e69728091c2be6eb479dfe18bb36efd34e08fd8acc730407", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 248, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf99f45ef3994a163d7cd58c2cead128afd1e3f3bc1a8ff98cbf1bc35ed609d420b", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 249, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf96f525d28c69be17ff4c0922ec4de39da15d46baad32dde92e4c37201b5cbd103", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 250, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 251, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 21", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 252, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 253, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 254, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 255, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 38", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 256, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 257, + "key": "0000000000000000000000000000000000000000000000000000000000000080", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 258, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2323a8aa3bc6edc5f2f3590ba2db757d50bf47c9f16cd1fd6a7db0f4ca24e0b", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 259, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa9189abccf6d929dc864b3eec19e26e4cc94b244565779a7f85ddb8e03c3c108", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 260, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff109d35eafa88df6c5770dd5ef7023b3965891d0c4050d2e9c7906613229d6c0e", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 261, + "key": "dd1483c5304d412c1f29547640a5c2950222ee8931b7ed1c72602b7afa7024e0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86e5c516a446a3c8e69728091c2be6eb479dfe18bb36efd34e08fd8acc730407", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 262, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 263, + "key": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 264, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 265, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 266, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "0000000000000000000000000000000000000000000000000000000000000000ef1195f0610612912016b3ee33054829bcea20ae4de1e9343b1c4e2e15649003", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 267, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b2d471882773a677af1e3824e757a33f8ddf7bbeaf3d28a09595eb8daa0d74a03", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 268, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 269, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 20", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 270, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 271, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 272, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 273, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 274, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 275, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 25", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 276, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 277, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 278, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fa83f56d4ca92da1f056c0bbaa0cc73cb350790210431ad647415c6a71242860c", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 279, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fef1195f0610612912016b3ee33054829bcea20ae4de1e9343b1c4e2e15649003", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 280, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 281, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 282, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 283, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 30", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 284, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 285, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "00000000000000000000000000000000000000000000000000000000000000800a4940ad86a3df965346037e94d0796fa785353be5f5d25b5c3c1a507c63bf0d", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 286, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9426cc293b14d304864a4cd689cbcc23cb13fcb1098f9c434cc9ca7439c9cf2505", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 287, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 288, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 289, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 290, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 291, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 292, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 293, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 294, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 295, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 296, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 297, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff944508fdd2e7908fed1b0bbbef3342fd911990128cbaa8714b0d28a617d4b508", + "msg": "ed25519vectors 19", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 298, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a4940ad86a3df965346037e94d0796fa785353be5f5d25b5c3c1a507c63bf0d", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 299, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 300, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 301, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 302, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 23", + "flags": [ + "low_order_R", + "low_order_A" + ] + }, + { + "number": 303, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A" + ] + }, + { + "number": 304, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "0100000000000000000000000000000000000000000000000000000000000000330b30d6c1f07511e2208d233b6a34d4ed7109da2dea615bcd97daee3a842704", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R" + ] + }, + { + "number": 305, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350640657f1cb030f12543549bbabd848dc6403d354e7c99c4d0dcee9f63c9033b00", + "msg": "ed25519vectors 5", + "flags": null + }, + { + "number": 306, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A" + ] + }, + { + "number": 307, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "non_canonical_A" + ] + }, + { + "number": 308, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 309, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A" + ] + }, + { + "number": 310, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "non_canonical_A" + ] + }, + { + "number": 311, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 312, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A" + ] + }, + { + "number": 313, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "non_canonical_A" + ] + }, + { + "number": 314, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 315, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_R" + ] + }, + { + "number": 316, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "01000000000000000000000000000000000000000000000000000000000000802d32f9eeccaa31dba2ff4ab4e196b61e2ee1648073bbb5f599dcff4f7ea02900", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "non_canonical_R" + ] + }, + { + "number": 317, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "0100000000000000000000000000000000000000000000000000000000000080330b30d6c1f07511e2208d233b6a34d4ed7109da2dea615bcd97daee3a842704", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 318, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_R" + ] + }, + { + "number": 319, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f367b7a92fea8539e8793cf812e799e8ed342c635592e74323a8dfd38a06aea0b", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "non_canonical_R" + ] + }, + { + "number": 320, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f330b30d6c1f07511e2208d233b6a34d4ed7109da2dea615bcd97daee3a842704", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 321, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 18", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_R" + ] + }, + { + "number": 322, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "eefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8ee37866245b5ef5bb4863572672809b98d93997190c514ccff477ebcf82f0d", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "non_canonical_R" + ] + }, + { + "number": 323, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff330b30d6c1f07511e2208d233b6a34d4ed7109da2dea615bcd97daee3a842704", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 324, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 325, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 326, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 327, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 328, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 329, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 330, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 331, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 332, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 19", + "flags": [ + "low_order_R", + "low_order_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 333, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 334, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 335, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05aac16c21847c8f77ede0e03571488e65c01bc418470acebc90a5f65a69c3c60f", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 336, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d21fd3eacd8d7a35408e669bbf20fa791fc50be2a753015c51a7ff9554c4c540902", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 337, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 338, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 339, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 340, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 341, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 342, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 343, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 344, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 345, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 346, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 347, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 348, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc8578b7a7a27ec214b774ab6434c7afe22bc3e6fa5f12d24e81dfbd99085789170b", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 349, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f114aa4b690ec5d1502a0c77d89ede55349d93b2f4df581bc979f8f0adbe60da300", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 350, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 351, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 37", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 352, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 353, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 354, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 355, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 356, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 357, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 358, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 359, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 360, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 361, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037afe03e5c298e079a79794c3a820a61614325041fc4c1be84e6169092dd4e42a01", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 362, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0eedf2a56e3f9f022ace42aa6116f576e76d0f752df8a5c879feb2288236a882d03", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 363, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 364, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 365, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 366, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 367, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 368, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 369, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 370, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 371, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 372, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 373, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 374, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa6245db2e055cd96ba42d2e1330ef131eefb5502759cc731c8cf787d7fd2b5a0c", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 375, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de5efb4cbf95ba7a317033c634a3bd174c2e36f6fb3a0b1d96608de7cfe4374d05", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 376, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 377, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 378, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 379, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 380, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 381, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 382, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 383, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 384, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 385, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 386, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 387, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fd2c8bb23568fc2c2ab61436089349253db3045d05634c2f50f67a88ab426e709", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 388, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9598a4afbe7b2a777d59b9dd15ed248f498090c35ea40d691bab0cee574467807", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_residue" + ] + }, + { + "number": 389, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 390, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 391, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 392, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 393, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 394, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 395, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 396, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 397, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 398, + "key": "0100000000000000000000000000000000000000000000000000000000000000", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 399, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcffc829608ae700722e38df9eb9761d200a3c86e7ef6dde961ba9cc8691cbc07", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 400, + "key": "ef75b20e7540e3dff77404193652ba2bd13df99c1508eee1515e27ae25f28076", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2c8bb23568fc2c2ab61436089349253db3045d05634c2f50f67a88ab426e709", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 401, + "key": "0100000000000000000000000000000000000000000000000000000000000080", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 402, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 403, + "key": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 404, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 405, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 406, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 407, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 408, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "0000000000000000000000000000000000000000000000000000000000000000620683477c6eae0f5f962cfb675dc5f112275e7207521b05f57d861fb8dfa804", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 409, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "0000000000000000000000000000000000000000000000000000000000000000ab98e2715f01f57e976deea3afb2c51e93c46f5f7e054a3764fd076682034004", + "msg": "ed25519vectors 35", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 410, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b8043872d01ef87b42d987e20d1f5604f591441bec276cb285e00c60c3854a307", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 411, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56bd79e8fd671739b78d219e13e1b578516549b9c90c988249f62d1d6a2b40ea606", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 412, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 413, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 414, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f9d21c5ce09b181f21ab1407e47442069d686bde3a0d7d250f0746e9835319f0a", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 415, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f806f1e38871587c8ed5631faf0f941c72744d2733d285b0d26eb5c7f79982b02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 416, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f620683477c6eae0f5f962cfb675dc5f112275e7207521b05f57d861fb8dfa804", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 417, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fab98e2715f01f57e976deea3afb2c51e93c46f5f7e054a3764fd076682034004", + "msg": "ed25519vectors 35", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 418, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 419, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 420, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 421, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 422, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "0000000000000000000000000000000000000000000000000000000000000080367dbd8f23ed46b14c764374ffd8542122d8a7b57b50e54851e702e70ca6660f", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 423, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "00000000000000000000000000000000000000000000000000000000000000807df52a3fa4bde9595e64e46ee493b1f14777427d518e42f19b6e5a9d891a0004", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 424, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a94cf6ffd24d41962558b5ec187dd97dd62faa0e79f56e10b9588663b310ece9800", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 425, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a94d205a702b93f4292e22186bd167770bfa3278f37a46264a735b31e757393e50f", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 426, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 427, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 428, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "edfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff797080e0e516f4ce696c1f6508c4211246c8734fe1c740830bc07b428001007", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 429, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff881c2e6337a2fc68add023c1c3b77016cefb8304d735cca7571edde70fca1408", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 430, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff367dbd8f23ed46b14c764374ffd8542122d8a7b57b50e54851e702e70ca6660f", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 431, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7df52a3fa4bde9595e64e46ee493b1f14777427d518e42f19b6e5a9d891a0004", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 432, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 433, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 21", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 434, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 435, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 436, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "010000000000000000000000000000000000000000000000000000000000000048435f31d933b4c6418d7d48d1223ddf2005f6ff4c6555c5850313295f5f4507", + "msg": "ed25519vectors 25", + "flags": [ + "low_order_R", + "low_order_component_A" + ] + }, + { + "number": 437, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "0100000000000000000000000000000000000000000000000000000000000000b1daaf7afa2140df3989634cfeb1dd0704b1feab734e6032a97f08ff33650704", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 438, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350606eafe34c35b824e46e082060ca75777e699beb94810d8195d570395c050470f", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_A" + ] + }, + { + "number": 439, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a3506046f0694bed0011b9085a74ca8f2aded381a9392b8182a6475ce4067fe6a7b07", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 440, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 441, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 442, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "0100000000000000000000000000000000000000000000000000000000000080c57b6e27f4d1afcbc43510891ee7816e69732bdac3893a4c4d75a698ec76fd09", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 443, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "0100000000000000000000000000000000000000000000000000000000000080ef0227e52e05478966a93698d9ddcdf73008388227b82a9a3f4311cff41ebd01", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 444, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "010000000000000000000000000000000000000000000000000000000000008048435f31d933b4c6418d7d48d1223ddf2005f6ff4c6555c5850313295f5f4507", + "msg": "ed25519vectors 25", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 445, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "0100000000000000000000000000000000000000000000000000000000000080b1daaf7afa2140df3989634cfeb1dd0704b1feab734e6032a97f08ff33650704", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 446, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 447, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 448, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f69d1960a5be23a7e46d14e609465c4fb82f3a486b4cf9ba3cc00d79f371a3002", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 449, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fc5563d65a243389fca7e1e6da4223a97871ece326555c70d323ade5764f6420c", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 450, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f48435f31d933b4c6418d7d48d1223ddf2005f6ff4c6555c5850313295f5f4507", + "msg": "ed25519vectors 25", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 451, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fb1daaf7afa2140df3989634cfeb1dd0704b1feab734e6032a97f08ff33650704", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 452, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 453, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 454, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01e3f5bcb8f8809336ac1034f88ea2e77c63713da62cdd73a7f5c7550ca89208", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 455, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff161119954a491e61643a5f8ba93edccf16b52d784f8a896e5d7ba53b73c84504", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 456, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48435f31d933b4c6418d7d48d1223ddf2005f6ff4c6555c5850313295f5f4507", + "msg": "ed25519vectors 25", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 457, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb1daaf7afa2140df3989634cfeb1dd0704b1feab734e6032a97f08ff33650704", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 458, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 459, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 460, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 18", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 461, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 462, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05008fba896e3cc7324a5b000fd0b903492c2ae0ae71dff7af176665ba205f3901", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 463, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc057c047ff30db9b92cac61791c64666eb0f6f11dd840d7d05b927c85f50533600e", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 464, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d21f7d88566da564c6fa777235d8864b9df8d63ee4369bcc3dbf0f421fdfe9d7309", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 465, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d21ddfb80c3b500d19d9a01010fb34cf3c00c7bc6e972e7d672e19ec969bd5b1908", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 466, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 467, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 468, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 469, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 470, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85a12ee75b7ce36d925ba81778453a97d8344a8decfdd797ee6d398a2c6820260e", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 471, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc8527d64d53fa7d8a7a56ab4dcfce52e6411ff5c5466029d30aa4159afad83f2409", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 472, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1123de7ac4b146e4fb8b492be4fcc69c95022bb9bba7eff6839101409bd5c5d50a", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 473, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f116f03b9c47f23619e95184c7914c139f4a66906150bdc0635512421be6e282004", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 474, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 475, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 476, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 477, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 478, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037abeb9fdccdf6e0bb47df7c1cba374f20e53e2af651a4a69d9fa8554bcd539e50b", + "msg": "ed25519vectors 24", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 479, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037ab6cdec95505f3fc3a3c58d45a591399c735e98c0cadaba2b61ee8b93f54d4105", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 480, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee27f196298cd2b5aec8b6545b122eb01dc4c87aff398c5152ed458036643f6a0a", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 481, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee035953cc64888fcdb0e70de5779b546a4c56b2d8f579748b4ce963887eb36705", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 482, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 483, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 484, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 21", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 485, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 486, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fab582b7398d6916f262ad46ab12895cd197ae7a89fd94530ad4071a5d71ee870b", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 487, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8fb5bb6032e801fdce885ff4f83560b6f56e66d3d9ad3a33eb9280190b2c670a", + "msg": "ed25519vectors 41", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 488, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72def9a498ab4b8a710de4a88867179af3a355b93c22f79f39581f7fb196e72f3400", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 489, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72dec0096ae4cafa9e22026530dc5fd2efd3159c8b1e4bcbfee4bb18049c43a33a03", + "msg": "ed25519vectors 41", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 490, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 491, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 492, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 493, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 494, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffa4a318b4063e408dec239cc0589533d04f801fe25009c1edd4c0a3b25097600", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 495, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fd3092366957eb289ec452b34bb6783c1790a339ad5d004d9f6d435325bdc2c0a", + "msg": "ed25519vectors 30", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 496, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf95a0b32dab50849741c136247a6109cfa76dc577cdec798e467689e43613dfc00", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 497, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9b452dd12a8b87cd3b6a527364a5e6f99eead5739469d5d120d95e50394681605", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 498, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 499, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 500, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1e9a40075f4b371d6575911abeb73574e1ce0ada5640bda601486ef92ef7ed0d", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 501, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2f9a3ea3657c36624cec77ed3facee69b3eeeb32131c6b87ba0a76993d3a3a06", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 502, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "ecfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa4a318b4063e408dec239cc0589533d04f801fe25009c1edd4c0a3b25097600", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 503, + "key": "6718d0a3d58deaeaefa655eae3f119071deaa2cfebfd0ca28b670f879d657086", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3092366957eb289ec452b34bb6783c1790a339ad5d004d9f6d435325bdc2c0a", + "msg": "ed25519vectors 30", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 504, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 35", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 505, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 506, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 507, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 27", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 508, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "00000000000000000000000000000000000000000000000000000000000000006d14fb942d5ff13cef4d783375f3abef9aea3d9bcecc1a0866415dae3509d507", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 509, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "00000000000000000000000000000000000000000000000000000000000000005f5f7ffd508fc84bd8fb5d9e90a3abc24b2cbacc03b00ca42c28e7b879c5d90d", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 510, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b08a85cdeab6f57330926e2eb3891c1017863d51e99f8d8f732ee42f5433c7507", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 511, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b097c3f79437cd87c6061fb032f792cd8cf46cbb4ce390b4decb9c1bf5e70ad0b", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 512, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 513, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 514, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fcf5dd993590903346c6c7dbbdab784f8eb498e7074896ff06f98221870663b07", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 515, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fca87bba547ac145cd6e813328df6df16ac5a137df85037b1c5ad2877464e840d", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 516, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f6d14fb942d5ff13cef4d783375f3abef9aea3d9bcecc1a0866415dae3509d507", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 517, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f5f5f7ffd508fc84bd8fb5d9e90a3abc24b2cbacc03b00ca42c28e7b879c5d90d", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 518, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 519, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 520, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 521, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 522, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "0000000000000000000000000000000000000000000000000000000000000080bf79045665b39525ad5ec9e9ade82bd5bc33fb049b13503dfb97aacc4ad0ae0e", + "msg": "ed25519vectors 31", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 523, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "00000000000000000000000000000000000000000000000000000000000000806b115a2573c0a4de9f3411a96c31e1919e57bfc3e5c27faefebcdd47768b9a05", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 524, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9450b2750dbb4ca36a55e8561ae5f39235db090de324b3c60126ad1f5c1d1ae30a", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 525, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9416e0b2ca09fe5b8ba05f5f8d3b4ab0e39b79b549775a9e136fd9d6fedf3b8609", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 526, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 527, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 528, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9bc693ae3af4296f60ffd9afb577cabb05c2dff634a5d483e5a8c094dd068403", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 529, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2f93b9ac542ae80e1054d7f7aff2c72cfcb5140130c37c92d4eb389c806d1509", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 530, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf79045665b39525ad5ec9e9ade82bd5bc33fb049b13503dfb97aacc4ad0ae0e", + "msg": "ed25519vectors 31", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 531, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6b115a2573c0a4de9f3411a96c31e1919e57bfc3e5c27faefebcdd47768b9a05", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 532, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 533, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 534, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 535, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 536, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "010000000000000000000000000000000000000000000000000000000000000092a325759ff830a4d19c0f0cce6364311dc1e7e4bc1efaa8a54632082c05cf0f", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A" + ] + }, + { + "number": 537, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "010000000000000000000000000000000000000000000000000000000000000048e9799d7754086f6eca319160c0d2ef1d35617c0151c719806495eb1026ac05", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 538, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350610dba6a8317cea9cda386e05f66eabb4248890064325c1d7a567a3443ce26606", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_A" + ] + }, + { + "number": 539, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a3506ceeddc384993fffb6ea69400f4a1529ddbd0f43c6322bf53d9ec144e9127680d", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 540, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 541, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 542, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "0100000000000000000000000000000000000000000000000000000000000080cdd1248e749ceac01f109bce3ce41507e49ba65d6a42baa443d77aa63113cd0f", + "msg": "ed25519vectors 18", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 543, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "010000000000000000000000000000000000000000000000000000000000008063e6cef756c8afdf5e0b364b01afa219cedeadb53d76c1ac58140dc8a7b37106", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 544, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "010000000000000000000000000000000000000000000000000000000000008092a325759ff830a4d19c0f0cce6364311dc1e7e4bc1efaa8a54632082c05cf0f", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 545, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "010000000000000000000000000000000000000000000000000000000000008048e9799d7754086f6eca319160c0d2ef1d35617c0151c719806495eb1026ac05", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 546, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 547, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 548, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fd4859f5c56a843a885bd86045dfcda0bf117f95c07c298f45664ad2f7f043106", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 549, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f4ee43c88b8d6703511f5a818428fd65e564301e1840c7ede88cf15ffac567a01", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 550, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f92a325759ff830a4d19c0f0cce6364311dc1e7e4bc1efaa8a54632082c05cf0f", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 551, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f48e9799d7754086f6eca319160c0d2ef1d35617c0151c719806495eb1026ac05", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 552, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 553, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 554, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2b502e797c4ce38333e3166e4e102483cd6ea5eea07bd0347a85d303c64e8b07", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 555, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2de8d820b140fdd27706ee8011913f9542adf9641f0b2913054c4ed3c2c1be06", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 556, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92a325759ff830a4d19c0f0cce6364311dc1e7e4bc1efaa8a54632082c05cf0f", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 557, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48e9799d7754086f6eca319160c0d2ef1d35617c0151c719806495eb1026ac05", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 558, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 559, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 560, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 561, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 562, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc051f8c6e2af77751e5474253bfac76ad7d3e16be0be2ff499ac17b66beafb7270e", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 563, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc0510eb9a2150d3683d1d873d608d7fb395b5968b379a0ec726bbbfbe453114fd01", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 564, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d21a66d971845a5eed7cd0432182614117196429d78205aa912a4272b134ab1740c", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 565, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d219c41f676f85cd5a5eee282112170365be8a4820e7cc4d13fdb88b1bf1f106c0b", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 566, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 567, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 568, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 569, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 570, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85c70ad24a368812eb8a9fd7bb0e300f492a0a9dbcda01df2829bca14ccf5bf10f", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 571, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85840364150cb09a830180d30ac7907c0a858eef2a282dc539e6fd73d8a6dfad0f", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 572, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f11e35ad3a31ecbff623f4733dded01086ed68e2bdaaa53171f4b8748a26514400d", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 573, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f115f11918f318e44147d456b9e33399dd987efaa7fb06b2485e1dd2f2e0c1e4b04", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 574, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 575, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 576, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 577, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 578, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a3c8b7f81b7fccdb4c6bc85121bc77ac9b2f2b22f3241501b1521195c86f3820f", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 579, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a3b8d3ce4adae6f057f2f0b1ad9b46678443d6c79779a69254a6d112ddf435b0c", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 580, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee9e7960e86abadeb7d5e1d2492122d925685b47203130aa8e629d093c61ada90d", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 581, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee40bdefba7a8c40c0580426e32719149f9600226b48f5e27dae52b6fbbdcf5805", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 582, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 583, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 584, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 585, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 586, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa7c1368a43039c42ac2dbb604b9617df90b4d2022deee87dd75d32faf83b9b901", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 587, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03faacf8c3c342a85ff0684df2e0dbdacf3a81417755cb9f5005d22bedf43fd8c803", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 588, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de1a33a7d03bde08688f729ab233eced41ff1db67eaa08157c3a1a27a00670c701", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 589, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de54af5f2d4dd8095dbea5873cc38d78ea426817d2fd61e9de5ec5165c93e62f09", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 590, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 591, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 592, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 593, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 594, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f9dff20f0d2acccc37928a00eb22a115047b52bcc2ab4b79b4432873d20172800", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 595, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fd082268d79821ab3a47487f2de6f64a13c921c0ec23e89e57cd596e56f61fe0a", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 596, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf96c95b94a5ed966fe1ac4f858c49fe690ab5f2d3a4571548d943cd31375e3f20b", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 597, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9e8df7d32a60fca528b0606d03f8bd6e57619183cb72e99da237d97f87213d301", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 598, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 599, + "key": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 600, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff681dcf4473cd9f43e21c3392dde10617a686de272c1014020896c9f458986202", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 601, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff35ec9aadea22201caf2fadcc24f4818d1202723a9a354e7b351094f746706300", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 602, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9dff20f0d2acccc37928a00eb22a115047b52bcc2ab4b79b4432873d20172800", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 603, + "key": "eca00a6a1b1f522ff2217691059915b097b73bc69bef396c36ddcd559b79e2b0", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd082268d79821ab3a47487f2de6f64a13c921c0ec23e89e57cd596e56f61fe0a", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 604, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 605, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 606, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 607, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 608, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "000000000000000000000000000000000000000000000000000000000000000031ac3ed1453a28af252ff542be21a4c0ef8b97c74940e51766b1855dbe02350d", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 609, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "0000000000000000000000000000000000000000000000000000000000000000420360a0c176d4586f28edbbcafc6e5d63d8f70954510ade434219770a86f204", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 610, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b07fe06280ad617d2c94c06e2b20983e035b2848443f7de550e5358bea36f0c03", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 611, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b945fc1469dbba776f427c47e386524dc1916bf9aad21268232b7f49b15310c06", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 612, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 613, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 614, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f8afc6fda146d589fa805b824266862baa309bb1ec071226b06ba4eaff9763c0e", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 615, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffa0b5b45eb2cb24cab8a910bfbcb08641410d64790b516c583b63940d25a9504", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 616, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f31ac3ed1453a28af252ff542be21a4c0ef8b97c74940e51766b1855dbe02350d", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 617, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f420360a0c176d4586f28edbbcafc6e5d63d8f70954510ade434219770a86f204", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 618, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 619, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 620, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 621, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 622, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "000000000000000000000000000000000000000000000000000000000000008069c99316215043ec75ea5a3d4e1357e3d0c5602366e82b24de319a520b585106", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 623, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "0000000000000000000000000000000000000000000000000000000000000080c9a28760bfdbaf4f028fe8d8ecb8c34db3b7c0c71d24e26734b2c841e8fac207", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 624, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a94e8b6da4567e7bfba5829e7a1197f8062462342ba28f67b2cbcf14a28af6e970a", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 625, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a948f8fa9222af828b040bcd86187c66d23faa97d1a51be5d5126bfd78688897b00", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 626, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 627, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 628, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff09b548baa15c220f0c456454bc0b3501750239f69aad45100932d36f0e9f3200", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 629, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa537bd259769d9113a834f55e1f42b160fad630daf58c8f9c7e80d8e5daa1302", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 630, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff69c99316215043ec75ea5a3d4e1357e3d0c5602366e82b24de319a520b585106", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 631, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9a28760bfdbaf4f028fe8d8ecb8c34db3b7c0c71d24e26734b2c841e8fac207", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 632, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 633, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 634, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 635, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 636, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "0100000000000000000000000000000000000000000000000000000000000000c46cc62cf59c79dc96ec34243a10a14750194479376a49cc84651a23a488ee05", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_A" + ] + }, + { + "number": 637, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "01000000000000000000000000000000000000000000000000000000000000007cbd8c879c5bf2335aa640bc7becf0547146c5becaae73560e9e80c036f2d502", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 638, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a3506104c833a1253a48cd66e54cab38543281b75e53c8bccb6a1dccd45eb251f1307", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_component_A" + ] + }, + { + "number": 639, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a3506f3ae4bb3afa88c3285c8b1241cf6df8316bb4b35e71346248582cd627121ad02", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 640, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 25", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 641, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 642, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "01000000000000000000000000000000000000000000000000000000000000809dfcac23338d3f13dc0ff5de059db61934190741f1f00836d7b735975892e002", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 643, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "0100000000000000000000000000000000000000000000000000000000000080230333f78f5b3eacd737fb60742c5c041e1ea56410ac40cc56b5b40968cc1209", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 644, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "0100000000000000000000000000000000000000000000000000000000000080c46cc62cf59c79dc96ec34243a10a14750194479376a49cc84651a23a488ee05", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 645, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "01000000000000000000000000000000000000000000000000000000000000807cbd8c879c5bf2335aa640bc7becf0547146c5becaae73560e9e80c036f2d502", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 646, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 647, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 648, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3a63dbb9c17d6ca41a6e1ce55b0a99bf8025eb49cc4640b3de424cb665fba20c", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 649, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f5b028c7e15842ffa8f6a8effc6f3a447419f4228cbfba57ebdf522573ed38f08", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 650, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fc46cc62cf59c79dc96ec34243a10a14750194479376a49cc84651a23a488ee05", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 651, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7cbd8c879c5bf2335aa640bc7becf0547146c5becaae73560e9e80c036f2d502", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 652, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 653, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 654, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92d85e93707e2f67157e9e4b3e289b823be4ccec80abd861efb9ba2e4c32510e", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 655, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaced0fbc977b44ec36d82176d929c9878bc6a90dbabdac84f071fa6daf97050a", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 656, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc46cc62cf59c79dc96ec34243a10a14750194479376a49cc84651a23a488ee05", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 657, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7cbd8c879c5bf2335aa640bc7becf0547146c5becaae73560e9e80c036f2d502", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 658, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 659, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 660, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 661, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 662, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc053fe4d58f46c5232b61f8e315b21a99832e7edb9875c9c2cfd0d77626215b580a", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 663, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc053d8acb56c081e29da3329a1f78ceff08c5f925cde1c64690dbf91d5260bcd50b", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 664, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d21ea7f1306764d7e910babd66ac6b9ed1b7db6c0381fbefe5d98b70a2c8fe97407", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 665, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2110ac576cd0481197776c0121a40caf560b3fc593fa0982e1e274007955fe530a", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 666, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 667, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 668, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 669, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 670, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc858c6564558b985cc383035bfb3572083c323717acb6c014db50b4a539a1e8900a", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 671, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc851feb0bd9cb3ea94d28ecce323f06901a96b3ea2f9e5b885aafa13d571ae4f70b", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 672, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f11fa299c89564128d4fe83c4758eb9c28990407191109ad31f0ca2b1548da63404", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 673, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f119a4fca0c7482f8d9f37923d8702d104d07b549e08225193b2818a6380e9ab40f", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 674, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 675, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 676, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 677, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 678, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037ae37e2cac72091af68b51b43b40f15e499c41621707e1fb30cb17362333cbba09", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 679, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a1e7d219f4540986f8904c6a16a2b74967c013b9ff1a99e6b9fdbb4835c19d70d", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 680, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee9101d1fb7d624768ec8ea7e31aca21042f3495ad5e48fdd151423f5c5f216c04", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 681, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0eef282a24a316fe5449ea437d32470df2c968f2f27688653d1e026ad3d3bfb530c", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 682, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 683, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 684, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 685, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 686, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fabfad7e6fdf808e46ddaaa65ad1e5fc4751473c239f63c49c2e017d7209058900", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 687, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa750d023533f655c6f32c38992a8a30f9f20c59bda30682a7f5f692764724e604", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 688, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72def2c459284b532cb7a74779ced5cc538521b7e466561e8abdcda7f64238404200", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 689, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de55ba20be6f48cddf9d90aef69958f1c53baa96226c0d788f25b13754d1a33207", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 690, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 691, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 692, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 693, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 694, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ff14a0b307122c632de6f34f1107225f88b1e21893f4d6719ddefd90f44b11f05", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 695, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f517fa7eb17544d51490f2417a13f0d85919dd5998cc3c465b8c3614f4651d20d", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 696, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9a05c2ebdd26e6d36b0d39a6dc8cad91ac0934700d6b796b6d7499d6eb81f1301", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 697, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9e97e9b1f47281ed688a320de5912618b62c9dac64d5971e2aab2d487038cc90b", + "msg": "ed25519vectors 18", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 698, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 699, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 700, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff248f13d1b0c2af4782513a8c33da39dd7cf9caf4ee3c85e58dbcbaec928aee0b", + "msg": "ed25519vectors 20", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 701, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff10e1e32f76302558b064ad4873824195afc9fbdd1a6aa20a8dd05cd54f708f00", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 702, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "ecfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14a0b307122c632de6f34f1107225f88b1e21893f4d6719ddefd90f44b11f05", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 703, + "key": "015ff595e4e0add00dde896efa66ea4f6848c4396410c693c92232aa64861d4f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff517fa7eb17544d51490f2417a13f0d85919dd5998cc3c465b8c3614f4651d20d", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 704, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 705, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 30", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 706, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 707, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 708, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "0000000000000000000000000000000000000000000000000000000000000000ff3d622b55aad17c5c7aad97a56a7ada9eda2a92a14a4c73e349d8da4f64c70a", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 709, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "00000000000000000000000000000000000000000000000000000000000000000734b8823047a23fb776be86db7b3f4bb1c9e49bc29b352c760002bdc8e54d02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 710, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b55a1b09e210288e47a4796def776679cdec5a64bd2bb9bc69932c3bd47b96109", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 711, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b074fc0dd361fa65cf275443e324c504017fa8e80bba2a1c5ad46f116c3dac901", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 712, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 713, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 714, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fa6f79db3f81348fd22224e50a25621f810d038de2060250f8a4937f3b4cc5208", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 715, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f59c48433c25fcb5f435c328aff1bad6eaf88cc0d7586a723ba3dc921f5009f0a", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 716, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fff3d622b55aad17c5c7aad97a56a7ada9eda2a92a14a4c73e349d8da4f64c70a", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 717, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0734b8823047a23fb776be86db7b3f4bb1c9e49bc29b352c760002bdc8e54d02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 718, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 719, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 720, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 721, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 722, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "0000000000000000000000000000000000000000000000000000000000000080216c38d9eae130fee53569d8a1750b2f2ef49185cddd7cf43379e84a3ef50d04", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 723, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "000000000000000000000000000000000000000000000000000000000000008026d690d9305a0d0a44ebb4e82d11b7fb6e0850fde3b27cdf662dfd300393eb01", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 724, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9452834a44fb880f6b87a7e173a2856a90f987bef39f1d95b066a528099af13302", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 725, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a94a69145f508ef4ce1a0fd25025d82516e06e492ef088de45da784f8a863ebe401", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 726, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 727, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 728, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56668e1aa7f6b00250315677063e6f347c869cc31c7a9f31ed42d02e1bdd9e0d", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 729, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff368ce93ef4a864890115ed9cb1341fa32fa0996911fe07c1496e8c9a3df43a08", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 730, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff216c38d9eae130fee53569d8a1750b2f2ef49185cddd7cf43379e84a3ef50d04", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 731, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff26d690d9305a0d0a44ebb4e82d11b7fb6e0850fde3b27cdf662dfd300393eb01", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 732, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 733, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 734, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 735, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 736, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "0100000000000000000000000000000000000000000000000000000000000000cdf25d18d1d94aa074c5277cafc39c51286021e21678ccc919bd6f326cfcb709", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_component_A" + ] + }, + { + "number": 737, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "01000000000000000000000000000000000000000000000000000000000000004071f5e71c483f0886dd678575b498d03177d51ad542edf113b6214b93c79b0b", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 738, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a3506bc1f0d2c7b653d5aaf07a71c130d8aff5bef8653d6984f2b223081ac24a62005", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_component_A" + ] + }, + { + "number": 739, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a3506134ff3e6e5e3fce6d8f46295871735f1700c2674d3892a7f06f055533336a002", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 740, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 741, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 742, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "010000000000000000000000000000000000000000000000000000000000008040ab130e002935091a7eac0f1476b9b5e60411ead58a3c0e95765c234752f702", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 743, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "0100000000000000000000000000000000000000000000000000000000000080f28144c16a59ecedbbe82aa3481cf42279d82c6c669beb6c59622e94bcc03808", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 744, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "0100000000000000000000000000000000000000000000000000000000000080cdf25d18d1d94aa074c5277cafc39c51286021e21678ccc919bd6f326cfcb709", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 745, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "01000000000000000000000000000000000000000000000000000000000000804071f5e71c483f0886dd678575b498d03177d51ad542edf113b6214b93c79b0b", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 746, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 747, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 25", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 748, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f4524c928a583ec7cbddab4765dbdaf532c7fd278a5c4fd933e9c4c01c2f58302", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 749, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f335ec19261efdcd25bbe64dde6dcc7815b237bf53ffedc45d44351d9690e0e0b", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 750, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fcdf25d18d1d94aa074c5277cafc39c51286021e21678ccc919bd6f326cfcb709", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 751, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f4071f5e71c483f0886dd678575b498d03177d51ad542edf113b6214b93c79b0b", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 752, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 753, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 754, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff69a153a2d8922b9fcfbc06a425e6a50f28dfe3799f91cb5f983b16eadf930405", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 755, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb61ad06789857c7a7c9025df6b6321483f533c775ababa02b57ea2508507340c", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 756, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf25d18d1d94aa074c5277cafc39c51286021e21678ccc919bd6f326cfcb709", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 757, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4071f5e71c483f0886dd678575b498d03177d51ad542edf113b6214b93c79b0b", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 758, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 759, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 760, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 761, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 762, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05dd5e46f50f59e854fda2b2ae82c6f0c64da07146d4b7d388a9c0acec0387de06", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 763, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc057a8afc08cd56ba356afe59be2d03de9d4d0f44cd72c00f85ddb1e844275b9601", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 764, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d21e25115117021871ba256c845f462422e380099235eb48e8fc898ef6b49ee5a0c", + "msg": "ed25519vectors 21", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 765, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d214f406acc5ef89838ac824d84529e2557b738d678e3b9070634232af8e8a16d02", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 766, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 767, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 768, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 769, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 770, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85e12d9510d58203c89c7d06a611815a2b390a6f363885b90da266c85135bc5c05", + "msg": "ed25519vectors 17", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 771, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850bbeccb5223743bd17f3a73dac85074bce77ce102d031b2e2a897a8b66ec650b", + "msg": "ed25519vectors 39", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 772, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f11701a598b9a02ae60505dd0c2938a1a0c2d6ffd4676cfb49125b19e9cb358da06", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 773, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f111a1ba75dc71a1c3275e4dd3115b1638f67d16f1440d16dcc2c0188bbb17d6206", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 774, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 775, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 776, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 777, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 778, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a1d48955627f685fca00a5d62886fa4cae966af752251034904358448891d9000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 779, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a19775c38558dafa093e9e2492933bcd4dd13656d43b75c7d13b450a986cc360d", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 780, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee91cfdeb875d86bf70f14733791c85add6b98dc813842c1338c48ea3e53e4aa0f", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 781, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee3939ad4e3797f4d869b51cb36f6b937987df797d46b851c6abc76ef707c60503", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 782, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 783, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 784, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 785, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 786, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03faf51deee4ffb00d126b97ff2d901b8e7de8bfb8a96e1dfabf4949a30b1c28ec01", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 787, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa4b4f0d7171f609289d3bbb7cbcefb424a13b468e848d58fddbb73429040c7906", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 788, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de1bdf452e3274bda9648c0e27ac7139f6c99c7ff2e96637afe541ce414e378b05", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 789, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de83458650b497c3f7226cb93e9324df567b1adda39378e844230453b95aa8c801", + "msg": "ed25519vectors", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 790, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 791, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 792, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 793, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 794, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f96d76d748c70430e986190b547bef03c36d3e53d4834f5c60b23d392695bbe06", + "msg": "ed25519vectors 22", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 795, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ff899fcb87a689f9a17bb3d7a54ab6bbd060f3f3061502f1fa6a1fc2a8eee0603", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 796, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9e9bcd5643add13de8c05d9e630359815212df872304bef491f58f867bd542709", + "msg": "ed25519vectors 15", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 797, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf904864848c5ff5361609e941b2136012ac88139a34707e12cadf6645dff0b1008", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 798, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 799, + "key": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 800, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff77de70f3611eb29ee726ca74d20267c184a35f0fbc4261458eaad86f545d5b03", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 801, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5c1a58a253fdd422102558a41077d95055a4f988bb5f475006a41a79d3a2ba01", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 802, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff96d76d748c70430e986190b547bef03c36d3e53d4834f5c60b23d392695bbe06", + "msg": "ed25519vectors 22", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 803, + "key": "86e72f5c2a7215151059aa151c0ee6f8e2155d301402f35d7498f078629a8f79", + "sig": "ecfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff899fcb87a689f9a17bb3d7a54ab6bbd060f3f3061502f1fa6a1fc2a8eee0603", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 804, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 805, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 806, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "0000000000000000000000000000000000000000000000000000000000000000819aa7c9081f2e43b7524fdd27ef578f48dd9f02371b31f8013bd0c5321c660f", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 807, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b9dbda34f2ac60ee9d893b9b16f898617e81347886067f49d79d37740bb42a80b", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 808, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 809, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 810, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "36684ea91032ba5b1dbab2d02f4debc74c3327f2b3802e2e4d371aa42b12b56b05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 811, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 812, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f1630a351114792030905842b0d440c30c3c3c08f8e275cc32718756675d10f06", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 813, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f819aa7c9081f2e43b7524fdd27ef578f48dd9f02371b31f8013bd0c5321c660f", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 814, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 815, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 19", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 816, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 817, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "0000000000000000000000000000000000000000000000000000000000000080008207ec4d9a9b8aaeee217ecb5d87a958de17beb51faec53236e7f7e07e6c05", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 818, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9467f05af9575f4d1a13f23973e28c591c4944c7dec5e4178c71a88110cc175006", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 819, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 820, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 821, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b797b156efcd45a4e2454d2fd0b21438b3ccd80d4c7fd1d1b2c8e55bd4ed4a9405ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 822, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 823, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48ed3504f9d9a85115643ab1fefe191b70c39dc708708236227941792dc8c502", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 824, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008207ec4d9a9b8aaeee217ecb5d87a958de17beb51faec53236e7f7e07e6c05", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 825, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 826, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 827, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 828, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_A", + "low_order_component_A" + ] + }, + { + "number": 829, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 830, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "0100000000000000000000000000000000000000000000000000000000000000ce34fe4edd707095877049d405f52b52a726b4cbef9b8a1f950340d521fe110d", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_A" + ] + }, + { + "number": 831, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "01000000000000000000000000000000000000000000000000000000000000007798d1693338d7c46e61a3aae05bd23a89fdf7b62b83efdd062dd19a39d8d505", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 832, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a3506ccbd210592f2a2b70a9c9ba91f97d642a2e51b9a67ec788188039228a24e0e09", + "msg": "ed25519vectors 23", + "flags": [ + "low_order_component_A" + ] + }, + { + "number": 833, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350660f862046e40dcc3af08e1b97b6cd10ee44158cbccab65668862e844ace00500", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 834, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 12", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 835, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 836, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 837, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 838, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 839, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "b62cf890de42c413b11b1411c9f01f1c4d77aa87ef182258d1251f69af2a350605ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 840, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 24", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 841, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 16", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 842, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "010000000000000000000000000000000000000000000000000000000000008041bd7afd3d12b42f00f9ac87804fceeea002eb2800665b0fe8acd0cf53ee3207", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 843, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "0100000000000000000000000000000000000000000000000000000000000080739deeff2a8c311e6172a2e9d05f6d8a048df123aa27e1015bda974e6b32b306", + "msg": "ed25519vectors 21", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 844, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "0100000000000000000000000000000000000000000000000000000000000080ce34fe4edd707095877049d405f52b52a726b4cbef9b8a1f950340d521fe110d", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 845, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "01000000000000000000000000000000000000000000000000000000000000807798d1693338d7c46e61a3aae05bd23a89fdf7b62b83efdd062dd19a39d8d505", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 846, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 847, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 848, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f736cd390d6a2cb3d3a40bbbe09c87fa3caced72cdd853bfbf047adf1dec92207", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 849, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fbe39026eed2d5f2b23510d25bc1a7bface53b1d7b949facee0c7f6d1121bbe02", + "msg": "ed25519vectors 23", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 850, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fce34fe4edd707095877049d405f52b52a726b4cbef9b8a1f950340d521fe110d", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 851, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7798d1693338d7c46e61a3aae05bd23a89fdf7b62b83efdd062dd19a39d8d505", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 852, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 853, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 854, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a4fe32e72294d34ff5060efff2141687dd52117f36311af924b73638f7bc604", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 855, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2e6065b5a7c4aa919800747605e99800c074041d01eecca3ac39b78ef00da906", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 856, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffce34fe4edd707095877049d405f52b52a726b4cbef9b8a1f950340d521fe110d", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 857, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7798d1693338d7c46e61a3aae05bd23a89fdf7b62b83efdd062dd19a39d8d505", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 858, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 859, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "01000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 860, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 861, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 862, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 863, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 864, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 865, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 866, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05dcf76895217bf0dacec839953c960ee6d7840b9fa8ec66377df8a2e2db722305", + "msg": "ed25519vectors 10", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 867, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d211566a1ad3f92ada58707e452dcd290efc6a1951aaefe43be3b4663e38c3ac002", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 868, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc050000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 869, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 870, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "5ae36d433a7bd0efb150b6b04610d1986e3044c46b6ad69bae17aaf76b608d2105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 871, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 872, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 873, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc8507e25ac429f3fda828fd20bbe35e9d834875b64098f05e40d1bbe63f20b9c50d", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 874, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f113fc2c91b53d127bfc4fb6910467e737fc5a6463963ca4df83d0c82a419299e06", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 875, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 876, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 877, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "fa9dde274f4820efb19a890f8ba2d8791710a4303ceef4aedf9dddc4e81a1f1105ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 878, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 879, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 880, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a3540a57b2ba00d60510ca5174b63f5ad6289f50241887ec114583b643dfe6003", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 881, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0eef081c939b0fb2f42749cd392be91b90b20875f6a7abd4019a470299569f16f01", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 882, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 9", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 883, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 884, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "f36121d8b0b7df104e6576f0745d2786e8ef5bcfc3110b512062223b17e5e0ee05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 13", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 885, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 11", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 886, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 887, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c7fe7a9b40ddb9617a6ca678729b53ad7c9916531c829288e416e56fbb74809", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 888, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de73da5e09d360debd54177128d8b403f3d8cdd80ec83cd60b138b515d89d5cb0a", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 889, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 890, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 19", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 891, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "931c92bcc5842f104eaf494fb9ef2e6791cfbb3b9495296451e85508949f72de05ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 892, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 893, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 894, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 895, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 896, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f63ec463daf4a74749995e1bca07d169051630e9cf36860b86536f5c7f6e87405", + "msg": "ed25519vectors 36", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 897, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f8fcc9e160cf71f1343cf2a6cc8d51cae1a9dc2e3debc99d97ec1190782406e05", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 898, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf92adec0cbdc3718697e370f88b291cbe1965f51921474e0fe35973dbc471c3e01", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_component_R", + "low_order_component_A", + "low_order_residue" + ] + }, + { + "number": 899, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf9327f51a83cacea96d1f3fc6be0e2682f22ce35400ccb707aa30a7321ed6dff05", + "msg": "ed25519vectors 3", + "flags": [ + "low_order_component_R", + "low_order_component_A" + ] + }, + { + "number": 900, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 901, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 902, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A" + ] + }, + { + "number": 903, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 4", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A" + ] + }, + { + "number": 904, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 14", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 905, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "37d3076f21bd3bec4ee4ebee360fe0e3b288557810e7dda72edae09650d5caf905ba9a796274d80437afa36f1236563f2f3b0aa84cecddc3d20914615ba4fe02", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "reencoded_k" + ] + }, + { + "number": 906, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 907, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 5", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 908, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0d5f3d4d7d4fd1b055ea05193ec32458d796b69aca128d34d5e4dbaec8a86e0c", + "msg": "ed25519vectors 2", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R" + ] + }, + { + "number": 909, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff472e9141da7cc7352acd9c8688b89b9c2ab873aa6c4270e9c9830051f861860f", + "msg": "ed25519vectors 6", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R" + ] + }, + { + "number": 910, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff63ec463daf4a74749995e1bca07d169051630e9cf36860b86536f5c7f6e87405", + "msg": "ed25519vectors 36", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 911, + "key": "fe894df18abf1c20088bfbe6c9ad45d42ec20663eaf7111eaea1d851da0d7f89", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8fcc9e160cf71f1343cf2a6cc8d51cae1a9dc2e3debc99d97ec1190782406e05", + "msg": "ed25519vectors 7", + "flags": [ + "low_order_R", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_R", + "reencoded_k" + ] + }, + { + "number": 912, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 1", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "low_order_residue", + "non_canonical_A", + "non_canonical_R" + ] + }, + { + "number": 913, + "key": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "sig": "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000", + "msg": "ed25519vectors 8", + "flags": [ + "low_order_R", + "low_order_A", + "low_order_component_R", + "low_order_component_A", + "non_canonical_A", + "non_canonical_R" + ] + } +] diff --git a/ed25519-dalek/benches/ed25519_benchmarks.rs b/ed25519-dalek/benches/ed25519_benchmarks.rs new file mode 100644 index 000000000..7c9685337 --- /dev/null +++ b/ed25519-dalek/benches/ed25519_benchmarks.rs @@ -0,0 +1,101 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2018-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +use criterion::{criterion_group, Criterion}; + +mod ed25519_benches { + use super::*; + use ed25519_dalek::Signature; + use ed25519_dalek::Signer; + use ed25519_dalek::SigningKey; + use rand::prelude::ThreadRng; + use rand::thread_rng; + + fn sign(c: &mut Criterion) { + let mut csprng: ThreadRng = thread_rng(); + let keypair: SigningKey = SigningKey::generate(&mut csprng); + let msg: &[u8] = b""; + + c.bench_function("Ed25519 signing", move |b| b.iter(|| keypair.sign(msg))); + } + + fn verify(c: &mut Criterion) { + let mut csprng: ThreadRng = thread_rng(); + let keypair: SigningKey = SigningKey::generate(&mut csprng); + let msg: &[u8] = b""; + let sig: Signature = keypair.sign(msg); + + c.bench_function("Ed25519 signature verification", move |b| { + b.iter(|| keypair.verify(msg, &sig)) + }); + } + + fn verify_strict(c: &mut Criterion) { + let mut csprng: ThreadRng = thread_rng(); + let keypair: SigningKey = SigningKey::generate(&mut csprng); + let msg: &[u8] = b""; + let sig: Signature = keypair.sign(msg); + + c.bench_function("Ed25519 strict signature verification", move |b| { + b.iter(|| keypair.verify_strict(msg, &sig)) + }); + } + + #[cfg(feature = "batch")] + fn verify_batch_signatures(c: &mut Criterion) { + use ed25519_dalek::verify_batch; + + static BATCH_SIZES: [usize; 8] = [4, 8, 16, 32, 64, 96, 128, 256]; + + // Benchmark batch verification for all the above batch sizes + let mut group = c.benchmark_group("Ed25519 batch signature verification"); + for size in BATCH_SIZES { + let name = format!("size={size}"); + group.bench_function(name, |b| { + let mut csprng: ThreadRng = thread_rng(); + let keypairs: Vec = (0..size) + .map(|_| SigningKey::generate(&mut csprng)) + .collect(); + let msg: &[u8] = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let messages: Vec<&[u8]> = (0..size).map(|_| msg).collect(); + let signatures: Vec = + keypairs.iter().map(|key| key.sign(&msg)).collect(); + let verifying_keys: Vec<_> = + keypairs.iter().map(|key| key.verifying_key()).collect(); + + b.iter(|| verify_batch(&messages[..], &signatures[..], &verifying_keys[..])); + }); + } + } + + // If the above function isn't defined, make a placeholder function + #[cfg(not(feature = "batch"))] + fn verify_batch_signatures(_: &mut Criterion) {} + + fn key_generation(c: &mut Criterion) { + let mut csprng: ThreadRng = thread_rng(); + + c.bench_function("Ed25519 keypair generation", move |b| { + b.iter(|| SigningKey::generate(&mut csprng)) + }); + } + + criterion_group! { + name = ed25519_benches; + config = Criterion::default(); + targets = + sign, + verify, + verify_strict, + verify_batch_signatures, + key_generation, + } +} + +criterion::criterion_main!(ed25519_benches::ed25519_benches); diff --git a/ed25519-dalek/docs/assets/ed25519-malleability.png b/ed25519-dalek/docs/assets/ed25519-malleability.png new file mode 100644 index 000000000..fe5896e99 Binary files /dev/null and b/ed25519-dalek/docs/assets/ed25519-malleability.png differ diff --git a/ed25519-dalek/docs/assets/rustdoc-include-katex-header.html b/ed25519-dalek/docs/assets/rustdoc-include-katex-header.html new file mode 100644 index 000000000..d240432aa --- /dev/null +++ b/ed25519-dalek/docs/assets/rustdoc-include-katex-header.html @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/ed25519-dalek/src/batch.rs b/ed25519-dalek/src/batch.rs new file mode 100644 index 000000000..d5d174643 --- /dev/null +++ b/ed25519-dalek/src/batch.rs @@ -0,0 +1,242 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! Batch signature verification. + +use alloc::vec::Vec; + +use core::convert::TryFrom; +use core::iter::once; + +use curve25519_dalek::constants; +use curve25519_dalek::edwards::EdwardsPoint; +use curve25519_dalek::scalar::Scalar; +use curve25519_dalek::traits::IsIdentity; +use curve25519_dalek::traits::VartimeMultiscalarMul; + +pub use curve25519_dalek::digest::Digest; + +use merlin::Transcript; + +use rand_core::RngCore; + +use sha2::Sha512; + +use crate::errors::InternalError; +use crate::errors::SignatureError; +use crate::signature::InternalSignature; +use crate::VerifyingKey; + +/// An implementation of `rand_core::RngCore` which does nothing. This is necessary because merlin +/// demands an `Rng` as input to `TranscriptRngBuilder::finalize()`. Using this with `finalize()` +/// yields a PRG whose input is the hashed transcript. +struct ZeroRng; + +impl rand_core::RngCore for ZeroRng { + fn next_u32(&mut self) -> u32 { + rand_core::impls::next_u32_via_fill(self) + } + + fn next_u64(&mut self) -> u64 { + rand_core::impls::next_u64_via_fill(self) + } + + /// A no-op function which leaves the destination bytes for randomness unchanged. + /// + /// In this case, the internal merlin code is initialising the destination + /// by doing `[0u8; …]`, which means that when we call + /// `merlin::TranscriptRngBuilder.finalize()`, rather than rekeying the + /// STROBE state based on external randomness, we're doing an + /// `ENC_{state}(00000000000000000000000000000000)` operation, which is + /// identical to the STROBE `MAC` operation. + fn fill_bytes(&mut self, _dest: &mut [u8]) {} + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +// `TranscriptRngBuilder::finalize()` requires a `CryptoRng` +impl rand_core::CryptoRng for ZeroRng {} + +// We write our own gen() function so we don't need to pull in the rand crate +fn gen_u128(rng: &mut R) -> u128 { + let mut buf = [0u8; 16]; + rng.fill_bytes(&mut buf); + u128::from_le_bytes(buf) +} + +/// Verify a batch of `signatures` on `messages` with their respective `verifying_keys`. +/// +/// # Inputs +/// +/// * `messages` is a slice of byte slices, one per signed message. +/// * `signatures` is a slice of `Signature`s. +/// * `verifying_keys` is a slice of `VerifyingKey`s. +/// +/// # Returns +/// +/// * A `Result` whose `Ok` value is an empty tuple and whose `Err` value is a +/// `SignatureError` containing a description of the internal error which +/// occurred. +/// +/// ## On Deterministic Nonces +/// +/// The nonces for batch signature verification are derived purely from the inputs to this function +/// themselves. +/// +/// In any sigma protocol it is wise to include as much context pertaining +/// to the public state in the protocol as possible, to avoid malleability +/// attacks where an adversary alters publics in an algebraic manner that +/// manages to satisfy the equations for the protocol in question. +/// +/// For ed25519 batch verification we include the following as scalars in the protocol transcript: +/// +/// * All of the computed `H(R||A||M)`s to the protocol transcript, and +/// * All of the `s` components of each signature. +/// +/// The former, while not quite as elegant as adding the `R`s, `A`s, and +/// `M`s separately, saves us a bit of context hashing since the +/// `H(R||A||M)`s need to be computed for the verification equation anyway. +/// +/// The latter prevents a malleability attack wherein an adversary, without access +/// to the signing key(s), can take any valid signature, `(s,R)`, and swap +/// `s` with `s' = -z1`. This doesn't constitute a signature forgery, merely +/// a vulnerability, as the resulting signature will not pass single +/// signature verification. (Thanks to Github users @real_or_random and +/// @jonasnick for pointing out this malleability issue.) +/// +/// # Examples +/// +/// ``` +/// use ed25519_dalek::{ +/// verify_batch, SigningKey, VerifyingKey, Signer, Signature, +/// }; +/// use rand::rngs::OsRng; +/// +/// # fn main() { +/// let mut csprng = OsRng; +/// let signing_keys: Vec<_> = (0..64).map(|_| SigningKey::generate(&mut csprng)).collect(); +/// let msg: &[u8] = b"They're good dogs Brant"; +/// let messages: Vec<_> = (0..64).map(|_| msg).collect(); +/// let signatures: Vec<_> = signing_keys.iter().map(|key| key.sign(&msg)).collect(); +/// let verifying_keys: Vec<_> = signing_keys.iter().map(|key| key.verifying_key()).collect(); +/// +/// let result = verify_batch(&messages, &signatures, &verifying_keys); +/// assert!(result.is_ok()); +/// # } +/// ``` +#[allow(non_snake_case)] +pub fn verify_batch( + messages: &[&[u8]], + signatures: &[ed25519::Signature], + verifying_keys: &[VerifyingKey], +) -> Result<(), SignatureError> { + // Return an Error if any of the vectors were not the same size as the others. + if signatures.len() != messages.len() + || signatures.len() != verifying_keys.len() + || verifying_keys.len() != messages.len() + { + return Err(InternalError::ArrayLength { + name_a: "signatures", + length_a: signatures.len(), + name_b: "messages", + length_b: messages.len(), + name_c: "verifying_keys", + length_c: verifying_keys.len(), + } + .into()); + } + + // Make a transcript which logs all inputs to this function + let mut transcript: Transcript = Transcript::new(b"ed25519 batch verification"); + + // We make one optimization in the transcript: since we will end up computing H(R || A || M) + // for each (R, A, M) triplet, we will feed _that_ into our transcript rather than each R, A, M + // individually. Since R and A are fixed-length, this modification is secure so long as SHA-512 + // is collision-resistant. + // It suffices to take `verifying_keys[i].as_bytes()` even though a `VerifyingKey` has two + // fields, and `as_bytes()` only returns the bytes of the first. This is because of an + // invariant guaranteed by `VerifyingKey`: the second field is always the (unique) + // decompression of the first. Thus, the serialized first field is a unique representation of + // the entire `VerifyingKey`. + let hrams: Vec<[u8; 64]> = (0..signatures.len()) + .map(|i| { + // Compute H(R || A || M), where + // R = sig.R + // A = verifying key + // M = msg + let mut h: Sha512 = Sha512::default(); + h.update(signatures[i].r_bytes()); + h.update(verifying_keys[i].as_bytes()); + h.update(&messages[i]); + *h.finalize().as_ref() + }) + .collect(); + + // Update transcript with the hashes above. This covers verifying_keys, messages, and the R + // half of signatures + for hram in hrams.iter() { + transcript.append_message(b"hram", hram); + } + // Update transcript with the rest of the data. This covers the s half of the signatures + for sig in signatures { + transcript.append_message(b"sig.s", sig.s_bytes()); + } + + // All function inputs have now been hashed into the transcript. Finalize it and use it as + // randomness for the batch verification. + let mut rng = transcript.build_rng().finalize(&mut ZeroRng); + + // Convert all signatures to `InternalSignature` + let signatures = signatures + .iter() + .map(InternalSignature::try_from) + .collect::, _>>()?; + // Convert the H(R || A || M) values into scalars + let hrams: Vec = hrams + .iter() + .map(Scalar::from_bytes_mod_order_wide) + .collect(); + + // Select a random 128-bit scalar for each signature. + let zs: Vec = signatures + .iter() + .map(|_| Scalar::from(gen_u128(&mut rng))) + .collect(); + + // Compute the basepoint coefficient, ∑ s[i]z[i] (mod l) + let B_coefficient: Scalar = signatures + .iter() + .map(|sig| sig.s) + .zip(zs.iter()) + .map(|(s, z)| z * s) + .sum(); + + // Multiply each H(R || A || M) by the random value + let zhrams = hrams.iter().zip(zs.iter()).map(|(hram, z)| hram * z); + + let Rs = signatures.iter().map(|sig| sig.R.decompress()); + let As = verifying_keys.iter().map(|pk| Some(pk.point)); + let B = once(Some(constants::ED25519_BASEPOINT_POINT)); + + // Compute (-∑ z[i]s[i] (mod l)) B + ∑ z[i]R[i] + ∑ (z[i]H(R||A||M)[i] (mod l)) A[i] = 0 + let id = EdwardsPoint::optional_multiscalar_mul( + once(-B_coefficient).chain(zs.iter().cloned()).chain(zhrams), + B.chain(Rs).chain(As), + ) + .ok_or(InternalError::Verify)?; + + if id.is_identity() { + Ok(()) + } else { + Err(InternalError::Verify.into()) + } +} diff --git a/ed25519-dalek/src/constants.rs b/ed25519-dalek/src/constants.rs new file mode 100644 index 000000000..4dc48a04b --- /dev/null +++ b/ed25519-dalek/src/constants.rs @@ -0,0 +1,32 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! Common constants such as buffer sizes for keypairs and signatures. + +/// The length of a ed25519 `Signature`, in bytes. +pub const SIGNATURE_LENGTH: usize = 64; + +/// The length of a ed25519 `SecretKey`, in bytes. +pub const SECRET_KEY_LENGTH: usize = 32; + +/// The length of an ed25519 `PublicKey`, in bytes. +pub const PUBLIC_KEY_LENGTH: usize = 32; + +/// The length of an ed25519 `Keypair`, in bytes. +pub const KEYPAIR_LENGTH: usize = SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH; + +/// The length of the "key" portion of an "expanded" ed25519 secret key, in bytes. +const EXPANDED_SECRET_KEY_KEY_LENGTH: usize = 32; + +/// The length of the "nonce" portion of an "expanded" ed25519 secret key, in bytes. +const EXPANDED_SECRET_KEY_NONCE_LENGTH: usize = 32; + +/// The length of an "expanded" ed25519 key, `ExpandedSecretKey`, in bytes. +pub const EXPANDED_SECRET_KEY_LENGTH: usize = + EXPANDED_SECRET_KEY_KEY_LENGTH + EXPANDED_SECRET_KEY_NONCE_LENGTH; diff --git a/ed25519-dalek/src/context.rs b/ed25519-dalek/src/context.rs new file mode 100644 index 000000000..afc64377c --- /dev/null +++ b/ed25519-dalek/src/context.rs @@ -0,0 +1,110 @@ +use crate::{InternalError, SignatureError}; + +/// Ed25519 contexts as used by Ed25519ph. +/// +/// Contexts are domain separator strings that can be used to isolate uses of +/// the algorithm between different protocols (which is very hard to reliably do +/// otherwise) and between different uses within the same protocol. +/// +/// To create a context, call either of the following: +/// +/// - [`SigningKey::with_context`](crate::SigningKey::with_context) +/// - [`VerifyingKey::with_context`](crate::VerifyingKey::with_context) +/// +/// For more information, see [RFC8032 § 8.3](https://www.rfc-editor.org/rfc/rfc8032#section-8.3). +/// +/// # Example +/// +#[cfg_attr(all(feature = "digest", feature = "rand_core"), doc = "```")] +#[cfg_attr( + any(not(feature = "digest"), not(feature = "rand_core")), + doc = "```ignore" +)] +/// # fn main() { +/// use ed25519_dalek::{Signature, SigningKey, VerifyingKey, Sha512}; +/// # use curve25519_dalek::digest::Digest; +/// # use rand::rngs::OsRng; +/// use ed25519_dalek::{DigestSigner, DigestVerifier}; +/// +/// # let mut csprng = OsRng; +/// # let signing_key = SigningKey::generate(&mut csprng); +/// # let verifying_key = signing_key.verifying_key(); +/// let context_str = b"Local Channel 3"; +/// let prehashed_message = Sha512::default().chain_update(b"Stay tuned for more news at 7"); +/// +/// // Signer +/// let signing_context = signing_key.with_context(context_str).unwrap(); +/// let signature = signing_context.sign_digest(prehashed_message.clone()); +/// +/// // Verifier +/// let verifying_context = verifying_key.with_context(context_str).unwrap(); +/// let verified: bool = verifying_context +/// .verify_digest(prehashed_message, &signature) +/// .is_ok(); +/// +/// # assert!(verified); +/// # } +/// ``` +#[derive(Clone, Debug)] +pub struct Context<'k, 'v, K> { + /// Key this context is being used with. + key: &'k K, + + /// Context value: a bytestring no longer than 255 octets. + value: &'v [u8], +} + +impl<'k, 'v, K> Context<'k, 'v, K> { + /// Maximum length of the context value in octets. + pub const MAX_LENGTH: usize = 255; + + /// Create a new Ed25519ph context. + pub(crate) fn new(key: &'k K, value: &'v [u8]) -> Result { + if value.len() <= Self::MAX_LENGTH { + Ok(Self { key, value }) + } else { + Err(SignatureError::from(InternalError::PrehashedContextLength)) + } + } + + /// Borrow the key. + pub fn key(&self) -> &'k K { + self.key + } + + /// Borrow the context string value. + pub fn value(&self) -> &'v [u8] { + self.value + } +} + +#[cfg(all(test, feature = "digest"))] +mod test { + use crate::{Signature, SigningKey, VerifyingKey}; + use curve25519_dalek::digest::Digest; + use ed25519::signature::{DigestSigner, DigestVerifier}; + use rand::rngs::OsRng; + use sha2::Sha512; + + #[test] + fn context_correctness() { + let mut csprng = OsRng; + let signing_key: SigningKey = SigningKey::generate(&mut csprng); + let verifying_key: VerifyingKey = signing_key.verifying_key(); + + let context_str = b"Local Channel 3"; + let prehashed_message = Sha512::default().chain_update(b"Stay tuned for more news at 7"); + + // Signer + let signing_context = signing_key.with_context(context_str).unwrap(); + let signature: Signature = signing_context.sign_digest(prehashed_message.clone()); + + // Verifier + let verifying_context = verifying_key.with_context(context_str).unwrap(); + let verified: bool = verifying_context + .verify_digest(prehashed_message, &signature) + .is_ok(); + + assert!(verified); + } +} diff --git a/ed25519-dalek/src/errors.rs b/ed25519-dalek/src/errors.rs new file mode 100644 index 000000000..7cba06db5 --- /dev/null +++ b/ed25519-dalek/src/errors.rs @@ -0,0 +1,119 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! Errors which may occur when parsing keys and/or signatures to or from wire formats. + +// rustc seems to think the typenames in match statements (e.g. in +// Display) should be snake cased, for some reason. +#![allow(non_snake_case)] + +use core::fmt; +use core::fmt::Display; + +#[cfg(feature = "std")] +use std::error::Error; + +/// Internal errors. Most application-level developers will likely not +/// need to pay any attention to these. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub(crate) enum InternalError { + PointDecompression, + ScalarFormat, + /// An error in the length of bytes handed to a constructor. + /// + /// To use this, pass a string specifying the `name` of the type which is + /// returning the error, and the `length` in bytes which its constructor + /// expects. + BytesLength { + name: &'static str, + length: usize, + }, + /// The verification equation wasn't satisfied + Verify, + /// Two arrays did not match in size, making the called signature + /// verification method impossible. + #[cfg(feature = "batch")] + ArrayLength { + name_a: &'static str, + length_a: usize, + name_b: &'static str, + length_b: usize, + name_c: &'static str, + length_c: usize, + }, + /// An ed25519ph signature can only take up to 255 octets of context. + #[cfg(feature = "digest")] + PrehashedContextLength, + /// A mismatched (public, secret) key pair. + MismatchedKeypair, +} + +impl Display for InternalError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + InternalError::PointDecompression => write!(f, "Cannot decompress Edwards point"), + InternalError::ScalarFormat => write!(f, "Cannot use scalar with high-bit set"), + InternalError::BytesLength { name: n, length: l } => { + write!(f, "{} must be {} bytes in length", n, l) + } + InternalError::Verify => write!(f, "Verification equation was not satisfied"), + #[cfg(feature = "batch")] + InternalError::ArrayLength { + name_a: na, + length_a: la, + name_b: nb, + length_b: lb, + name_c: nc, + length_c: lc, + } => write!( + f, + "Arrays must be the same length: {} has length {}, + {} has length {}, {} has length {}.", + na, la, nb, lb, nc, lc + ), + #[cfg(feature = "digest")] + InternalError::PrehashedContextLength => write!( + f, + "An ed25519ph signature can only take up to 255 octets of context" + ), + InternalError::MismatchedKeypair => write!(f, "Mismatched Keypair detected"), + } + } +} + +#[cfg(feature = "std")] +impl Error for InternalError {} + +/// Errors which may occur while processing signatures and keypairs. +/// +/// This error may arise due to: +/// +/// * Being given bytes with a length different to what was expected. +/// +/// * A problem decompressing `r`, a curve point, in the `Signature`, or the +/// curve point for a `PublicKey`. +/// +/// * A problem with the format of `s`, a scalar, in the `Signature`. This +/// is only raised if the high-bit of the scalar was set. (Scalars must +/// only be constructed from 255-bit integers.) +/// +/// * Failure of a signature to satisfy the verification equation. +pub type SignatureError = ed25519::signature::Error; + +impl From for SignatureError { + #[cfg(not(feature = "std"))] + fn from(_err: InternalError) -> SignatureError { + SignatureError::new() + } + + #[cfg(feature = "std")] + fn from(err: InternalError) -> SignatureError { + SignatureError::from_source(err) + } +} diff --git a/ed25519-dalek/src/hazmat.rs b/ed25519-dalek/src/hazmat.rs new file mode 100644 index 000000000..4414a84eb --- /dev/null +++ b/ed25519-dalek/src/hazmat.rs @@ -0,0 +1,278 @@ +//! Low-level interfaces to ed25519 functions +//! +//! # ⚠️ Warning: Hazmat +//! +//! These primitives are easy-to-misuse low-level interfaces. +//! +//! If you are an end user / non-expert in cryptography, **do not use any of these functions**. +//! Failure to use them correctly can lead to catastrophic failures including **full private key +//! recovery.** + +// Permit dead code because 1) this module is only public when the `hazmat` feature is set, and 2) +// even without `hazmat` we still need this module because this is where `ExpandedSecretKey` is +// defined. +#![allow(dead_code)] + +use crate::{InternalError, SignatureError}; + +use curve25519_dalek::scalar::{clamp_integer, Scalar}; + +#[cfg(feature = "zeroize")] +use zeroize::{Zeroize, ZeroizeOnDrop}; + +// These are used in the functions that are made public when the hazmat feature is set +use crate::{Signature, VerifyingKey}; +use curve25519_dalek::digest::{generic_array::typenum::U64, Digest}; + +/// Contains the secret scalar and domain separator used for generating signatures. +/// +/// This is used internally for signing. +/// +/// In the usual Ed25519 signing algorithm, `scalar` and `hash_prefix` are defined such that +/// `scalar || hash_prefix = H(sk)` where `sk` is the signing key and `H` is SHA-512. +/// **WARNING:** Deriving the values for these fields in any other way can lead to full key +/// recovery, as documented in [`raw_sign`] and [`raw_sign_prehashed`]. +/// +/// Instances of this secret are automatically overwritten with zeroes when they fall out of scope. +pub struct ExpandedSecretKey { + // `scalar_bytes` and `scalar` are separate, because the public key is computed as an unreduced + // scalar multiplication (ie `mul_base_clamped`), whereas the signing operations are done + // modulo l. + pub(crate) scalar_bytes: [u8; 32], + /// The secret scalar used for signing + pub scalar: Scalar, + /// The domain separator used when hashing the message to generate the pseudorandom `r` value + pub hash_prefix: [u8; 32], +} + +#[cfg(feature = "zeroize")] +impl Drop for ExpandedSecretKey { + fn drop(&mut self) { + self.scalar.zeroize(); + self.hash_prefix.zeroize() + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for ExpandedSecretKey {} + +// Some conversion methods for `ExpandedSecretKey`. The signing methods are defined in +// `signing.rs`, since we need them even when `not(feature = "hazmat")` +impl ExpandedSecretKey { + /// Convert this `ExpandedSecretKey` into an array of 64 bytes. + pub fn to_bytes(&self) -> [u8; 64] { + let mut bytes: [u8; 64] = [0u8; 64]; + + bytes[..32].copy_from_slice(self.scalar.as_bytes()); + bytes[32..].copy_from_slice(&self.hash_prefix[..]); + bytes + } + + /// Construct an `ExpandedSecretKey` from an array of 64 bytes. In the spec, the bytes are the + /// output of a SHA-512 hash. This clamps the first 32 bytes and uses it as a scalar, and uses + /// the second 32 bytes as a domain separator for hashing. + pub fn from_bytes(bytes: &[u8; 64]) -> Self { + // TODO: Use bytes.split_array_ref once it’s in MSRV. + let mut scalar_bytes: [u8; 32] = [0u8; 32]; + let mut hash_prefix: [u8; 32] = [0u8; 32]; + scalar_bytes.copy_from_slice(&bytes[00..32]); + hash_prefix.copy_from_slice(&bytes[32..64]); + + // For signing, we'll need the integer, clamped, and converted to a Scalar. See + // PureEdDSA.keygen in RFC 8032 Appendix A. + let scalar = Scalar::from_bytes_mod_order(clamp_integer(scalar_bytes)); + + ExpandedSecretKey { + scalar_bytes, + scalar, + hash_prefix, + } + } + + /// Construct an `ExpandedSecretKey` from a slice of 64 bytes. + /// + /// # Returns + /// + /// A `Result` whose okay value is an EdDSA `ExpandedSecretKey` or whose error value is an + /// `SignatureError` describing the error that occurred, namely that the given slice's length + /// is not 64. + pub fn from_slice(bytes: &[u8]) -> Result { + // Try to coerce bytes to a [u8; 64] + bytes.try_into().map(Self::from_bytes).map_err(|_| { + InternalError::BytesLength { + name: "ExpandedSecretKey", + length: 64, + } + .into() + }) + } +} + +impl TryFrom<&[u8]> for ExpandedSecretKey { + type Error = SignatureError; + + fn try_from(bytes: &[u8]) -> Result { + Self::from_slice(bytes) + } +} + +/// Compute an ordinary Ed25519 signature over the given message. `CtxDigest` is the digest used to +/// calculate the pseudorandomness needed for signing. According to the Ed25519 spec, `CtxDigest = +/// Sha512`. +/// +/// # ⚠️ Unsafe +/// +/// Do NOT use this function unless you absolutely must. Using the wrong values in +/// `ExpandedSecretKey` can leak your signing key. See +/// [here](https://github.com/MystenLabs/ed25519-unsafe-libs) for more details on this attack. +pub fn raw_sign( + esk: &ExpandedSecretKey, + message: &[u8], + verifying_key: &VerifyingKey, +) -> Signature +where + CtxDigest: Digest, +{ + esk.raw_sign::(message, verifying_key) +} + +/// Compute a signature over the given prehashed message, the Ed25519ph algorithm defined in +/// [RFC8032 §5.1][rfc8032]. `MsgDigest` is the digest function used to hash the signed message. +/// `CtxDigest` is the digest function used to calculate the pseudorandomness needed for signing. +/// According to the Ed25519 spec, `MsgDigest = CtxDigest = Sha512`. +/// +/// # ⚠️ Unsafe +// +/// Do NOT use this function unless you absolutely must. Using the wrong values in +/// `ExpandedSecretKey` can leak your signing key. See +/// [here](https://github.com/MystenLabs/ed25519-unsafe-libs) for more details on this attack. +/// +/// # Inputs +/// +/// * `esk` is the [`ExpandedSecretKey`] being used for signing +/// * `prehashed_message` is an instantiated hash digest with 512-bits of +/// output which has had the message to be signed previously fed into its +/// state. +/// * `verifying_key` is a [`VerifyingKey`] which corresponds to this secret key. +/// * `context` is an optional context string, up to 255 bytes inclusive, +/// which may be used to provide additional domain separation. If not +/// set, this will default to an empty string. +/// +/// `scalar` and `hash_prefix` are usually selected such that `scalar || hash_prefix = H(sk)` where +/// `sk` is the signing key +/// +/// # Returns +/// +/// A `Result` whose `Ok` value is an Ed25519ph [`Signature`] on the +/// `prehashed_message` if the context was 255 bytes or less, otherwise +/// a `SignatureError`. +/// +/// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1 +#[cfg(feature = "digest")] +#[allow(non_snake_case)] +pub fn raw_sign_prehashed<'a, CtxDigest, MsgDigest>( + esk: &ExpandedSecretKey, + prehashed_message: MsgDigest, + verifying_key: &VerifyingKey, + context: Option<&'a [u8]>, +) -> Result +where + MsgDigest: Digest, + CtxDigest: Digest, +{ + esk.raw_sign_prehashed::(prehashed_message, verifying_key, context) +} + +/// The ordinary non-batched Ed25519 verification check, rejecting non-canonical R +/// values.`CtxDigest` is the digest used to calculate the pseudorandomness needed for signing. +/// According to the Ed25519 spec, `CtxDigest = Sha512`. +pub fn raw_verify( + vk: &VerifyingKey, + message: &[u8], + signature: &ed25519::Signature, +) -> Result<(), SignatureError> +where + CtxDigest: Digest, +{ + vk.raw_verify::(message, signature) +} + +/// The batched Ed25519 verification check, rejecting non-canonical R values. `MsgDigest` is the +/// digest used to hash the signed message. `CtxDigest` is the digest used to calculate the +/// pseudorandomness needed for signing. According to the Ed25519 spec, `MsgDigest = CtxDigest = +/// Sha512`. +#[cfg(feature = "digest")] +#[allow(non_snake_case)] +pub fn raw_verify_prehashed( + vk: &VerifyingKey, + prehashed_message: MsgDigest, + context: Option<&[u8]>, + signature: &ed25519::Signature, +) -> Result<(), SignatureError> +where + MsgDigest: Digest, + CtxDigest: Digest, +{ + vk.raw_verify_prehashed::(prehashed_message, context, signature) +} + +#[cfg(test)] +mod test { + use super::*; + + use rand::{rngs::OsRng, CryptoRng, RngCore}; + + // Pick distinct, non-spec 512-bit hash functions for message and sig-context hashing + type CtxDigest = blake2::Blake2b512; + type MsgDigest = sha3::Sha3_512; + + impl ExpandedSecretKey { + // Make a random expanded secret key for testing purposes. This is NOT how you generate + // expanded secret keys IRL. They're the hash of a seed. + fn random(mut rng: R) -> Self { + let mut bytes = [0u8; 64]; + rng.fill_bytes(&mut bytes); + ExpandedSecretKey::from_bytes(&bytes) + } + } + + // Check that raw_sign and raw_verify work when a non-spec CtxDigest is used + #[test] + fn sign_verify_nonspec() { + // Generate the keypair + let mut rng = OsRng; + let esk = ExpandedSecretKey::random(&mut rng); + let vk = VerifyingKey::from(&esk); + + let msg = b"Then one day, a piano fell on my head"; + + // Sign and verify + let sig = raw_sign::(&esk, msg, &vk); + raw_verify::(&vk, msg, &sig).unwrap(); + } + + // Check that raw_sign_prehashed and raw_verify_prehashed work when distinct, non-spec + // MsgDigest and CtxDigest are used + #[cfg(feature = "digest")] + #[test] + fn sign_verify_prehashed_nonspec() { + use curve25519_dalek::digest::Digest; + + // Generate the keypair + let mut rng = OsRng; + let esk = ExpandedSecretKey::random(&mut rng); + let vk = VerifyingKey::from(&esk); + + // Hash the message + let msg = b"And then I got trampled by a herd of buffalo"; + let mut h = MsgDigest::new(); + h.update(msg); + + let ctx_str = &b"consequences"[..]; + + // Sign and verify prehashed + let sig = raw_sign_prehashed::(&esk, h.clone(), &vk, Some(ctx_str)) + .unwrap(); + raw_verify_prehashed::(&vk, h, Some(ctx_str), &sig).unwrap(); + } +} diff --git a/ed25519-dalek/src/lib.rs b/ed25519-dalek/src/lib.rs new file mode 100644 index 000000000..a7cfac488 --- /dev/null +++ b/ed25519-dalek/src/lib.rs @@ -0,0 +1,293 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! A Rust implementation of ed25519 key generation, signing, and verification. +//! +//! # Example +//! +//! Creating an ed25519 signature on a message is simple. +//! +//! First, we need to generate a `SigningKey`, which includes both public and +//! secret halves of an asymmetric key. To do so, we need a cryptographically +//! secure pseudorandom number generator (CSPRNG). For this example, we'll use +//! the operating system's builtin PRNG: +//! +#![cfg_attr(feature = "rand_core", doc = "```")] +#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")] +//! # fn main() { +//! use rand::rngs::OsRng; +//! use ed25519_dalek::SigningKey; +//! use ed25519_dalek::Signature; +//! +//! let mut csprng = OsRng; +//! let signing_key: SigningKey = SigningKey::generate(&mut csprng); +//! # } +//! ``` +//! +//! We can now use this `signing_key` to sign a message: +//! +#![cfg_attr(feature = "rand_core", doc = "```")] +#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")] +//! # fn main() { +//! # use rand::rngs::OsRng; +//! # use ed25519_dalek::SigningKey; +//! # let mut csprng = OsRng; +//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng); +//! use ed25519_dalek::{Signature, Signer}; +//! let message: &[u8] = b"This is a test of the tsunami alert system."; +//! let signature: Signature = signing_key.sign(message); +//! # } +//! ``` +//! +//! As well as to verify that this is, indeed, a valid signature on +//! that `message`: +//! +#![cfg_attr(feature = "rand_core", doc = "```")] +#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")] +//! # fn main() { +//! # use rand::rngs::OsRng; +//! # use ed25519_dalek::{SigningKey, Signature, Signer}; +//! # let mut csprng = OsRng; +//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng); +//! # let message: &[u8] = b"This is a test of the tsunami alert system."; +//! # let signature: Signature = signing_key.sign(message); +//! use ed25519_dalek::Verifier; +//! assert!(signing_key.verify(message, &signature).is_ok()); +//! # } +//! ``` +//! +//! Anyone else, given the `public` half of the `signing_key` can also easily +//! verify this signature: +//! +#![cfg_attr(feature = "rand_core", doc = "```")] +#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")] +//! # fn main() { +//! # use rand::rngs::OsRng; +//! # use ed25519_dalek::SigningKey; +//! # use ed25519_dalek::Signature; +//! # use ed25519_dalek::Signer; +//! use ed25519_dalek::{VerifyingKey, Verifier}; +//! # let mut csprng = OsRng; +//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng); +//! # let message: &[u8] = b"This is a test of the tsunami alert system."; +//! # let signature: Signature = signing_key.sign(message); +//! +//! let verifying_key: VerifyingKey = signing_key.verifying_key(); +//! assert!(verifying_key.verify(message, &signature).is_ok()); +//! # } +//! ``` +//! +//! ## Serialisation +//! +//! `VerifyingKey`s, `SecretKey`s, `SigningKey`s, and `Signature`s can be serialised +//! into byte-arrays by calling `.to_bytes()`. It's perfectly acceptable and +//! safe to transfer and/or store those bytes. (Of course, never transfer your +//! secret key to anyone else, since they will only need the public key to +//! verify your signatures!) +//! +#![cfg_attr(feature = "rand_core", doc = "```")] +#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")] +//! # fn main() { +//! # use rand::rngs::OsRng; +//! # use ed25519_dalek::{SigningKey, Signature, Signer, VerifyingKey}; +//! use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH}; +//! # let mut csprng = OsRng; +//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng); +//! # let message: &[u8] = b"This is a test of the tsunami alert system."; +//! # let signature: Signature = signing_key.sign(message); +//! +//! let verifying_key_bytes: [u8; PUBLIC_KEY_LENGTH] = signing_key.verifying_key().to_bytes(); +//! let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = signing_key.to_bytes(); +//! let signing_key_bytes: [u8; KEYPAIR_LENGTH] = signing_key.to_keypair_bytes(); +//! let signature_bytes: [u8; SIGNATURE_LENGTH] = signature.to_bytes(); +//! # } +//! ``` +//! +//! And similarly, decoded from bytes with `::from_bytes()`: +//! +#![cfg_attr(feature = "rand_core", doc = "```")] +#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")] +//! # use core::convert::{TryFrom, TryInto}; +//! # use rand::rngs::OsRng; +//! # use ed25519_dalek::{SigningKey, Signature, Signer, VerifyingKey, SecretKey, SignatureError}; +//! # use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH}; +//! # fn do_test() -> Result<(SigningKey, VerifyingKey, Signature), SignatureError> { +//! # let mut csprng = OsRng; +//! # let signing_key_orig: SigningKey = SigningKey::generate(&mut csprng); +//! # let message: &[u8] = b"This is a test of the tsunami alert system."; +//! # let signature_orig: Signature = signing_key_orig.sign(message); +//! # let verifying_key_bytes: [u8; PUBLIC_KEY_LENGTH] = signing_key_orig.verifying_key().to_bytes(); +//! # let signing_key_bytes: [u8; SECRET_KEY_LENGTH] = signing_key_orig.to_bytes(); +//! # let signature_bytes: [u8; SIGNATURE_LENGTH] = signature_orig.to_bytes(); +//! # +//! let verifying_key: VerifyingKey = VerifyingKey::from_bytes(&verifying_key_bytes)?; +//! let signing_key: SigningKey = SigningKey::from_bytes(&signing_key_bytes); +//! let signature: Signature = Signature::try_from(&signature_bytes[..])?; +//! # +//! # Ok((signing_key, verifying_key, signature)) +//! # } +//! # fn main() { +//! # do_test(); +//! # } +//! ``` +//! +//! ### PKCS#8 Key Encoding +//! +//! PKCS#8 is a private key format with support for multiple algorithms. +//! It can be encoded as binary (DER) or text (PEM). +//! +//! You can recognize PEM-encoded PKCS#8 keys by the following: +//! +//! ```text +//! -----BEGIN PRIVATE KEY----- +//! ``` +//! +//! To use PKCS#8, you need to enable the `pkcs8` crate feature. +//! +//! The following traits can be used to decode/encode [`SigningKey`] and +//! [`VerifyingKey`] as PKCS#8. Note that [`pkcs8`] is re-exported from the +//! toplevel of the crate: +//! +//! - [`pkcs8::DecodePrivateKey`]: decode private keys from PKCS#8 +//! - [`pkcs8::EncodePrivateKey`]: encode private keys to PKCS#8 +//! - [`pkcs8::DecodePublicKey`]: decode public keys from PKCS#8 +//! - [`pkcs8::EncodePublicKey`]: encode public keys to PKCS#8 +//! +//! #### Example +//! +//! NOTE: this requires the `pem` crate feature. +//! +#![cfg_attr(feature = "pem", doc = "```")] +#![cfg_attr(not(feature = "pem"), doc = "```ignore")] +//! use ed25519_dalek::{VerifyingKey, pkcs8::DecodePublicKey}; +//! +//! let pem = "-----BEGIN PUBLIC KEY----- +//! MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE= +//! -----END PUBLIC KEY-----"; +//! +//! let verifying_key = VerifyingKey::from_public_key_pem(pem) +//! .expect("invalid public key PEM"); +//! ``` +//! +//! ### Using Serde +//! +//! If you prefer the bytes to be wrapped in another serialisation format, all +//! types additionally come with built-in [serde](https://serde.rs) support by +//! building `ed25519-dalek` via: +//! +//! ```bash +//! $ cargo build --features="serde" +//! ``` +//! +//! They can be then serialised into any of the wire formats which serde supports. +//! For example, using [bincode](https://github.com/TyOverby/bincode): +//! +#![cfg_attr(all(feature = "rand_core", feature = "serde"), doc = "```")] +#![cfg_attr(not(all(feature = "rand_core", feature = "serde")), doc = "```ignore")] +//! # fn main() { +//! # use rand::rngs::OsRng; +//! # use ed25519_dalek::{SigningKey, Signature, Signer, Verifier, VerifyingKey}; +//! use bincode::serialize; +//! # let mut csprng = OsRng; +//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng); +//! # let message: &[u8] = b"This is a test of the tsunami alert system."; +//! # let signature: Signature = signing_key.sign(message); +//! # let verifying_key: VerifyingKey = signing_key.verifying_key(); +//! # let verified: bool = verifying_key.verify(message, &signature).is_ok(); +//! +//! let encoded_verifying_key: Vec = serialize(&verifying_key).unwrap(); +//! let encoded_signature: Vec = serialize(&signature).unwrap(); +//! # } +//! ``` +//! +//! After sending the `encoded_verifying_key` and `encoded_signature`, the +//! recipient may deserialise them and verify: +//! +#![cfg_attr(all(feature = "rand_core", feature = "serde"), doc = "```")] +#![cfg_attr(not(all(feature = "rand_core", feature = "serde")), doc = "```ignore")] +//! # fn main() { +//! # use rand::rngs::OsRng; +//! # use ed25519_dalek::{SigningKey, Signature, Signer, Verifier, VerifyingKey}; +//! # use bincode::serialize; +//! use bincode::deserialize; +//! +//! # let mut csprng = OsRng; +//! # let signing_key: SigningKey = SigningKey::generate(&mut csprng); +//! let message: &[u8] = b"This is a test of the tsunami alert system."; +//! # let signature: Signature = signing_key.sign(message); +//! # let verifying_key: VerifyingKey = signing_key.verifying_key(); +//! # let verified: bool = verifying_key.verify(message, &signature).is_ok(); +//! # let encoded_verifying_key: Vec = serialize(&verifying_key).unwrap(); +//! # let encoded_signature: Vec = serialize(&signature).unwrap(); +//! let decoded_verifying_key: VerifyingKey = deserialize(&encoded_verifying_key).unwrap(); +//! let decoded_signature: Signature = deserialize(&encoded_signature).unwrap(); +//! +//! # assert_eq!(verifying_key, decoded_verifying_key); +//! # assert_eq!(signature, decoded_signature); +//! # +//! let verified: bool = decoded_verifying_key.verify(&message, &decoded_signature).is_ok(); +//! +//! assert!(verified); +//! # } +//! ``` + +#![no_std] +#![warn(future_incompatible, rust_2018_idioms)] +#![deny(missing_docs)] // refuse to compile if documentation is missing +#![deny(clippy::unwrap_used)] // don't allow unwrap +#![cfg_attr(not(test), forbid(unsafe_code))] +#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg, doc_cfg_hide))] +#![cfg_attr(docsrs, doc(cfg_hide(docsrs)))] + +#[cfg(feature = "batch")] +extern crate alloc; + +#[cfg(any(feature = "std", test))] +#[macro_use] +extern crate std; + +pub use ed25519; + +#[cfg(feature = "batch")] +mod batch; +mod constants; +#[cfg(feature = "digest")] +mod context; +mod errors; +mod signature; +mod signing; +mod verifying; + +#[cfg(feature = "hazmat")] +pub mod hazmat; +#[cfg(not(feature = "hazmat"))] +mod hazmat; + +#[cfg(feature = "digest")] +pub use curve25519_dalek::digest::Digest; +#[cfg(feature = "digest")] +pub use sha2::Sha512; + +#[cfg(feature = "batch")] +pub use crate::batch::*; +pub use crate::constants::*; +#[cfg(feature = "digest")] +pub use crate::context::Context; +pub use crate::errors::*; +pub use crate::signing::*; +pub use crate::verifying::*; + +// Re-export the `Signer` and `Verifier` traits from the `signature` crate +#[cfg(feature = "digest")] +pub use ed25519::signature::{DigestSigner, DigestVerifier}; +pub use ed25519::signature::{Signer, Verifier}; +pub use ed25519::Signature; + +#[cfg(feature = "pkcs8")] +pub use ed25519::pkcs8; diff --git a/ed25519-dalek/src/signature.rs b/ed25519-dalek/src/signature.rs new file mode 100644 index 000000000..36174c8d6 --- /dev/null +++ b/ed25519-dalek/src/signature.rs @@ -0,0 +1,178 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! An ed25519 signature. + +use core::convert::TryFrom; +use core::fmt::Debug; + +use curve25519_dalek::edwards::CompressedEdwardsY; +use curve25519_dalek::scalar::Scalar; + +use crate::constants::*; +use crate::errors::*; + +/// An ed25519 signature. +/// +/// # Note +/// +/// These signatures, unlike the ed25519 signature reference implementation, are +/// "detached"—that is, they do **not** include a copy of the message which has +/// been signed. +#[allow(non_snake_case)] +#[derive(Copy, Eq, PartialEq)] +pub(crate) struct InternalSignature { + /// `R` is an `EdwardsPoint`, formed by using an hash function with + /// 512-bits output to produce the digest of: + /// + /// - the nonce half of the `ExpandedSecretKey`, and + /// - the message to be signed. + /// + /// This digest is then interpreted as a `Scalar` and reduced into an + /// element in ℤ/lℤ. The scalar is then multiplied by the distinguished + /// basepoint to produce `R`, and `EdwardsPoint`. + pub(crate) R: CompressedEdwardsY, + + /// `s` is a `Scalar`, formed by using an hash function with 512-bits output + /// to produce the digest of: + /// + /// - the `r` portion of this `Signature`, + /// - the `PublicKey` which should be used to verify this `Signature`, and + /// - the message to be signed. + /// + /// This digest is then interpreted as a `Scalar` and reduced into an + /// element in ℤ/lℤ. + pub(crate) s: Scalar, +} + +impl Clone for InternalSignature { + fn clone(&self) -> Self { + *self + } +} + +impl Debug for InternalSignature { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s) + } +} + +/// Ensures that the scalar `s` of a signature is within the bounds [0, 2^253). +/// +/// **Unsafe**: This version of `check_scalar` permits signature malleability. See README. +#[cfg(feature = "legacy_compatibility")] +#[inline(always)] +fn check_scalar(bytes: [u8; 32]) -> Result { + // The highest 3 bits must not be set. No other checking for the + // remaining 2^253 - 2^252 + 27742317777372353535851937790883648493 + // potential non-reduced scalars is performed. + // + // This is compatible with ed25519-donna and libsodium when + // -DED25519_COMPAT is NOT specified. + if bytes[31] & 224 != 0 { + return Err(InternalError::ScalarFormat.into()); + } + + // You cannot do arithmetic with scalars construct with Scalar::from_bits. We only use this + // scalar for EdwardsPoint::vartime_double_scalar_mul_basepoint, which is an accepted usecase. + // The `from_bits` method is deprecated because it's unsafe. We know this. + #[allow(deprecated)] + Ok(Scalar::from_bits(bytes)) +} + +/// Ensures that the scalar `s` of a signature is within the bounds [0, ℓ) +#[cfg(not(feature = "legacy_compatibility"))] +#[inline(always)] +fn check_scalar(bytes: [u8; 32]) -> Result { + match Scalar::from_canonical_bytes(bytes).into() { + None => Err(InternalError::ScalarFormat.into()), + Some(x) => Ok(x), + } +} + +impl InternalSignature { + /// Construct a `Signature` from a slice of bytes. + /// + /// # Scalar Malleability Checking + /// + /// As originally specified in the ed25519 paper (cf. the "Malleability" + /// section of the README in this repo), no checks whatsoever were performed + /// for signature malleability. + /// + /// Later, a semi-functional, hacky check was added to most libraries to + /// "ensure" that the scalar portion, `s`, of the signature was reduced `mod + /// \ell`, the order of the basepoint: + /// + /// ```ignore + /// if signature.s[31] & 224 != 0 { + /// return Err(); + /// } + /// ``` + /// + /// This bit-twiddling ensures that the most significant three bits of the + /// scalar are not set: + /// + /// ```python,ignore + /// >>> 0b00010000 & 224 + /// 0 + /// >>> 0b00100000 & 224 + /// 32 + /// >>> 0b01000000 & 224 + /// 64 + /// >>> 0b10000000 & 224 + /// 128 + /// ``` + /// + /// However, this check is hacky and insufficient to check that the scalar is + /// fully reduced `mod \ell = 2^252 + 27742317777372353535851937790883648493` as + /// it leaves us with a guanteed bound of 253 bits. This means that there are + /// `2^253 - 2^252 + 2774231777737235353585193779088364849311` remaining scalars + /// which could cause malleabilllity. + /// + /// RFC8032 [states](https://tools.ietf.org/html/rfc8032#section-5.1.7): + /// + /// > To verify a signature on a message M using public key A, [...] + /// > first split the signature into two 32-octet halves. Decode the first + /// > half as a point R, and the second half as an integer S, in the range + /// > 0 <= s < L. Decode the public key A as point A'. If any of the + /// > decodings fail (including S being out of range), the signature is + /// > invalid. + /// + /// However, by the time this was standardised, most libraries in use were + /// only checking the most significant three bits. (See also the + /// documentation for [`crate::VerifyingKey::verify_strict`].) + #[inline] + #[allow(non_snake_case)] + pub fn from_bytes(bytes: &[u8; SIGNATURE_LENGTH]) -> Result { + // TODO: Use bytes.split_array_ref once it’s in MSRV. + let mut R_bytes: [u8; 32] = [0u8; 32]; + let mut s_bytes: [u8; 32] = [0u8; 32]; + R_bytes.copy_from_slice(&bytes[00..32]); + s_bytes.copy_from_slice(&bytes[32..64]); + + Ok(InternalSignature { + R: CompressedEdwardsY(R_bytes), + s: check_scalar(s_bytes)?, + }) + } +} + +impl TryFrom<&ed25519::Signature> for InternalSignature { + type Error = SignatureError; + + fn try_from(sig: &ed25519::Signature) -> Result { + InternalSignature::from_bytes(&sig.to_bytes()) + } +} + +impl From for ed25519::Signature { + fn from(sig: InternalSignature) -> ed25519::Signature { + ed25519::Signature::from_components(*sig.R.as_bytes(), *sig.s.as_bytes()) + } +} diff --git a/ed25519-dalek/src/signing.rs b/ed25519-dalek/src/signing.rs new file mode 100644 index 000000000..b0f0b49b0 --- /dev/null +++ b/ed25519-dalek/src/signing.rs @@ -0,0 +1,845 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! ed25519 signing keys. + +#[cfg(feature = "pkcs8")] +use ed25519::pkcs8; + +#[cfg(any(test, feature = "rand_core"))] +use rand_core::CryptoRngCore; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use sha2::Sha512; + +use curve25519_dalek::{ + digest::{generic_array::typenum::U64, Digest}, + edwards::{CompressedEdwardsY, EdwardsPoint}, + scalar::Scalar, +}; + +use ed25519::signature::{KeypairRef, Signer, Verifier}; + +#[cfg(feature = "digest")] +use crate::context::Context; +#[cfg(feature = "digest")] +use signature::DigestSigner; + +#[cfg(feature = "zeroize")] +use zeroize::{Zeroize, ZeroizeOnDrop}; + +use crate::{ + constants::{KEYPAIR_LENGTH, SECRET_KEY_LENGTH}, + errors::{InternalError, SignatureError}, + hazmat::ExpandedSecretKey, + signature::InternalSignature, + verifying::VerifyingKey, + Signature, +}; + +/// ed25519 secret key as defined in [RFC8032 § 5.1.5]: +/// +/// > The private key is 32 octets (256 bits, corresponding to b) of +/// > cryptographically secure random data. +/// +/// [RFC8032 § 5.1.5]: https://www.rfc-editor.org/rfc/rfc8032#section-5.1.5 +pub type SecretKey = [u8; SECRET_KEY_LENGTH]; + +/// ed25519 signing key which can be used to produce signatures. +// Invariant: `public` is always the public key of `secret`. This prevents the signing function +// oracle attack described in https://github.com/MystenLabs/ed25519-unsafe-libs +#[derive(Clone, Debug)] +pub struct SigningKey { + /// The secret half of this signing key. + pub(crate) secret_key: SecretKey, + /// The public half of this signing key. + pub(crate) verifying_key: VerifyingKey, +} + +/// # Example +/// +/// ``` +/// # extern crate ed25519_dalek; +/// # +/// use ed25519_dalek::SigningKey; +/// use ed25519_dalek::SECRET_KEY_LENGTH; +/// use ed25519_dalek::SignatureError; +/// +/// # fn doctest() -> Result { +/// let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = [ +/// 157, 097, 177, 157, 239, 253, 090, 096, +/// 186, 132, 074, 244, 146, 236, 044, 196, +/// 068, 073, 197, 105, 123, 050, 105, 025, +/// 112, 059, 172, 003, 028, 174, 127, 096, ]; +/// +/// let signing_key: SigningKey = SigningKey::from_bytes(&secret_key_bytes); +/// assert_eq!(signing_key.to_bytes(), secret_key_bytes); +/// +/// # Ok(signing_key) +/// # } +/// # +/// # fn main() { +/// # let result = doctest(); +/// # assert!(result.is_ok()); +/// # } +/// ``` +impl SigningKey { + /// Construct a [`SigningKey`] from a [`SecretKey`] + /// + #[inline] + pub fn from_bytes(secret_key: &SecretKey) -> Self { + let verifying_key = VerifyingKey::from(&ExpandedSecretKey::from(secret_key)); + Self { + secret_key: *secret_key, + verifying_key, + } + } + + /// Convert this [`SigningKey`] into a [`SecretKey`] + #[inline] + pub fn to_bytes(&self) -> SecretKey { + self.secret_key + } + + /// Construct a [`SigningKey`] from the bytes of a `VerifyingKey` and `SecretKey`. + /// + /// # Inputs + /// + /// * `bytes`: an `&[u8]` of length [`KEYPAIR_LENGTH`], representing the + /// scalar for the secret key, and a compressed Edwards-Y coordinate of a + /// point on curve25519, both as bytes. (As obtained from + /// [`SigningKey::to_bytes`].) + /// + /// # Returns + /// + /// A `Result` whose okay value is an EdDSA [`SigningKey`] or whose error value + /// is an `SignatureError` describing the error that occurred. + #[inline] + pub fn from_keypair_bytes(bytes: &[u8; 64]) -> Result { + let (secret_key, verifying_key) = bytes.split_at(SECRET_KEY_LENGTH); + let signing_key = SigningKey::try_from(secret_key)?; + let verifying_key = VerifyingKey::try_from(verifying_key)?; + + if signing_key.verifying_key() != verifying_key { + return Err(InternalError::MismatchedKeypair.into()); + } + + Ok(signing_key) + } + + /// Convert this signing key to a 64-byte keypair. + /// + /// # Returns + /// + /// An array of bytes, `[u8; KEYPAIR_LENGTH]`. The first + /// `SECRET_KEY_LENGTH` of bytes is the `SecretKey`, and the next + /// `PUBLIC_KEY_LENGTH` bytes is the `VerifyingKey` (the same as other + /// libraries, such as [Adam Langley's ed25519 Golang + /// implementation](https://github.com/agl/ed25519/)). It is guaranteed that + /// the encoded public key is the one derived from the encoded secret key. + pub fn to_keypair_bytes(&self) -> [u8; KEYPAIR_LENGTH] { + let mut bytes: [u8; KEYPAIR_LENGTH] = [0u8; KEYPAIR_LENGTH]; + + bytes[..SECRET_KEY_LENGTH].copy_from_slice(&self.secret_key); + bytes[SECRET_KEY_LENGTH..].copy_from_slice(self.verifying_key.as_bytes()); + bytes + } + + /// Get the [`VerifyingKey`] for this [`SigningKey`]. + pub fn verifying_key(&self) -> VerifyingKey { + self.verifying_key + } + + /// Create a signing context that can be used for Ed25519ph with + /// [`DigestSigner`]. + #[cfg(feature = "digest")] + pub fn with_context<'k, 'v>( + &'k self, + context_value: &'v [u8], + ) -> Result, SignatureError> { + Context::new(self, context_value) + } + + /// Generate an ed25519 signing key. + /// + /// # Example + /// + #[cfg_attr(feature = "rand_core", doc = "```")] + #[cfg_attr(not(feature = "rand_core"), doc = "```ignore")] + /// # fn main() { + /// use rand::rngs::OsRng; + /// use ed25519_dalek::{Signature, SigningKey}; + /// + /// let mut csprng = OsRng; + /// let signing_key: SigningKey = SigningKey::generate(&mut csprng); + /// # } + /// ``` + /// + /// # Input + /// + /// A CSPRNG with a `fill_bytes()` method, e.g. `rand_os::OsRng`. + /// + /// The caller must also supply a hash function which implements the + /// `Digest` and `Default` traits, and which returns 512 bits of output. + /// The standard hash function used for most ed25519 libraries is SHA-512, + /// which is available with `use sha2::Sha512` as in the example above. + /// Other suitable hash functions include Keccak-512 and Blake2b-512. + #[cfg(any(test, feature = "rand_core"))] + pub fn generate(csprng: &mut R) -> SigningKey { + let mut secret = SecretKey::default(); + csprng.fill_bytes(&mut secret); + Self::from_bytes(&secret) + } + + /// Sign a `prehashed_message` with this [`SigningKey`] using the + /// Ed25519ph algorithm defined in [RFC8032 §5.1][rfc8032]. + /// + /// # Inputs + /// + /// * `prehashed_message` is an instantiated hash digest with 512-bits of + /// output which has had the message to be signed previously fed into its + /// state. + /// * `context` is an optional context string, up to 255 bytes inclusive, + /// which may be used to provide additional domain separation. If not + /// set, this will default to an empty string. + /// + /// # Returns + /// + /// An Ed25519ph [`Signature`] on the `prehashed_message`. + /// + /// # Note + /// + /// The RFC only permits SHA-512 to be used for prehashing, i.e., `MsgDigest = Sha512`. This + /// function technically works, and is probably safe to use, with any secure hash function with + /// 512-bit digests, but anything outside of SHA-512 is NOT specification-compliant. We expose + /// [`crate::Sha512`] for user convenience. + /// + /// # Examples + /// + #[cfg_attr(all(feature = "rand_core", feature = "digest"), doc = "```")] + #[cfg_attr( + any(not(feature = "rand_core"), not(feature = "digest")), + doc = "```ignore" + )] + /// use ed25519_dalek::Digest; + /// use ed25519_dalek::SigningKey; + /// use ed25519_dalek::Signature; + /// use sha2::Sha512; + /// use rand::rngs::OsRng; + /// + /// # fn main() { + /// let mut csprng = OsRng; + /// let signing_key: SigningKey = SigningKey::generate(&mut csprng); + /// let message: &[u8] = b"All I want is to pet all of the dogs."; + /// + /// // Create a hash digest object which we'll feed the message into: + /// let mut prehashed: Sha512 = Sha512::new(); + /// + /// prehashed.update(message); + /// # } + /// ``` + /// + /// If you want, you can optionally pass a "context". It is generally a + /// good idea to choose a context and try to make it unique to your project + /// and this specific usage of signatures. + /// + /// For example, without this, if you were to [convert your OpenPGP key + /// to a Bitcoin key][terrible_idea] (just as an example, and also Don't + /// Ever Do That) and someone tricked you into signing an "email" which was + /// actually a Bitcoin transaction moving all your magic internet money to + /// their address, it'd be a valid transaction. + /// + /// By adding a context, this trick becomes impossible, because the context + /// is concatenated into the hash, which is then signed. So, going with the + /// previous example, if your bitcoin wallet used a context of + /// "BitcoinWalletAppTxnSigning" and OpenPGP used a context (this is likely + /// the least of their safety problems) of "GPGsCryptoIsntConstantTimeLol", + /// then the signatures produced by both could never match the other, even + /// if they signed the exact same message with the same key. + /// + /// Let's add a context for good measure (remember, you'll want to choose + /// your own!): + /// + #[cfg_attr(all(feature = "rand_core", feature = "digest"), doc = "```")] + #[cfg_attr( + any(not(feature = "rand_core"), not(feature = "digest")), + doc = "```ignore" + )] + /// # use ed25519_dalek::Digest; + /// # use ed25519_dalek::SigningKey; + /// # use ed25519_dalek::Signature; + /// # use ed25519_dalek::SignatureError; + /// # use sha2::Sha512; + /// # use rand::rngs::OsRng; + /// # + /// # fn do_test() -> Result { + /// # let mut csprng = OsRng; + /// # let signing_key: SigningKey = SigningKey::generate(&mut csprng); + /// # let message: &[u8] = b"All I want is to pet all of the dogs."; + /// # let mut prehashed: Sha512 = Sha512::new(); + /// # prehashed.update(message); + /// # + /// let context: &[u8] = b"Ed25519DalekSignPrehashedDoctest"; + /// + /// let sig: Signature = signing_key.sign_prehashed(prehashed, Some(context))?; + /// # + /// # Ok(sig) + /// # } + /// # fn main() { + /// # do_test(); + /// # } + /// ``` + /// + /// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1 + /// [terrible_idea]: https://github.com/isislovecruft/scripts/blob/master/gpgkey2bc.py + #[cfg(feature = "digest")] + pub fn sign_prehashed( + &self, + prehashed_message: MsgDigest, + context: Option<&[u8]>, + ) -> Result + where + MsgDigest: Digest, + { + ExpandedSecretKey::from(&self.secret_key).raw_sign_prehashed::( + prehashed_message, + &self.verifying_key, + context, + ) + } + + /// Verify a signature on a message with this signing key's public key. + pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> { + self.verifying_key.verify(message, signature) + } + + /// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm. + /// + /// # Inputs + /// + /// * `prehashed_message` is an instantiated hash digest with 512-bits of + /// output which has had the message to be signed previously fed into its + /// state. + /// * `context` is an optional context string, up to 255 bytes inclusive, + /// which may be used to provide additional domain separation. If not + /// set, this will default to an empty string. + /// * `signature` is a purported Ed25519ph [`Signature`] on the `prehashed_message`. + /// + /// # Returns + /// + /// Returns `true` if the `signature` was a valid signature created by this + /// [`SigningKey`] on the `prehashed_message`. + /// + /// # Note + /// + /// The RFC only permits SHA-512 to be used for prehashing, i.e., `MsgDigest = Sha512`. This + /// function technically works, and is probably safe to use, with any secure hash function with + /// 512-bit digests, but anything outside of SHA-512 is NOT specification-compliant. We expose + /// [`crate::Sha512`] for user convenience. + /// + /// # Examples + /// + #[cfg_attr(all(feature = "rand_core", feature = "digest"), doc = "```")] + #[cfg_attr( + any(not(feature = "rand_core"), not(feature = "digest")), + doc = "```ignore" + )] + /// use ed25519_dalek::Digest; + /// use ed25519_dalek::SigningKey; + /// use ed25519_dalek::Signature; + /// use ed25519_dalek::SignatureError; + /// use sha2::Sha512; + /// use rand::rngs::OsRng; + /// + /// # fn do_test() -> Result<(), SignatureError> { + /// let mut csprng = OsRng; + /// let signing_key: SigningKey = SigningKey::generate(&mut csprng); + /// let message: &[u8] = b"All I want is to pet all of the dogs."; + /// + /// let mut prehashed: Sha512 = Sha512::new(); + /// prehashed.update(message); + /// + /// let context: &[u8] = b"Ed25519DalekSignPrehashedDoctest"; + /// + /// let sig: Signature = signing_key.sign_prehashed(prehashed, Some(context))?; + /// + /// // The sha2::Sha512 struct doesn't implement Copy, so we'll have to create a new one: + /// let mut prehashed_again: Sha512 = Sha512::default(); + /// prehashed_again.update(message); + /// + /// let verified = signing_key.verifying_key().verify_prehashed(prehashed_again, Some(context), &sig); + /// + /// assert!(verified.is_ok()); + /// + /// # verified + /// # } + /// # + /// # fn main() { + /// # do_test(); + /// # } + /// ``` + /// + /// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1 + #[cfg(feature = "digest")] + pub fn verify_prehashed( + &self, + prehashed_message: MsgDigest, + context: Option<&[u8]>, + signature: &Signature, + ) -> Result<(), SignatureError> + where + MsgDigest: Digest, + { + self.verifying_key + .verify_prehashed(prehashed_message, context, signature) + } + + /// Strictly verify a signature on a message with this signing key's public key. + /// + /// # On The (Multiple) Sources of Malleability in Ed25519 Signatures + /// + /// This version of verification is technically non-RFC8032 compliant. The + /// following explains why. + /// + /// 1. Scalar Malleability + /// + /// The authors of the RFC explicitly stated that verification of an ed25519 + /// signature must fail if the scalar `s` is not properly reduced mod \ell: + /// + /// > To verify a signature on a message M using public key A, with F + /// > being 0 for Ed25519ctx, 1 for Ed25519ph, and if Ed25519ctx or + /// > Ed25519ph is being used, C being the context, first split the + /// > signature into two 32-octet halves. Decode the first half as a + /// > point R, and the second half as an integer S, in the range + /// > 0 <= s < L. Decode the public key A as point A'. If any of the + /// > decodings fail (including S being out of range), the signature is + /// > invalid.) + /// + /// All `verify_*()` functions within ed25519-dalek perform this check. + /// + /// 2. Point malleability + /// + /// The authors of the RFC added in a malleability check to step #3 in + /// §5.1.7, for small torsion components in the `R` value of the signature, + /// *which is not strictly required*, as they state: + /// + /// > Check the group equation \[8\]\[S\]B = \[8\]R + \[8\]\[k\]A'. It's + /// > sufficient, but not required, to instead check \[S\]B = R + \[k\]A'. + /// + /// # History of Malleability Checks + /// + /// As originally defined (cf. the "Malleability" section in the README of + /// this repo), ed25519 signatures didn't consider *any* form of + /// malleability to be an issue. Later the scalar malleability was + /// considered important. Still later, particularly with interests in + /// cryptocurrency design and in unique identities (e.g. for Signal users, + /// Tor onion services, etc.), the group element malleability became a + /// concern. + /// + /// However, libraries had already been created to conform to the original + /// definition. One well-used library in particular even implemented the + /// group element malleability check, *but only for batch verification*! + /// Which meant that even using the same library, a single signature could + /// verify fine individually, but suddenly, when verifying it with a bunch + /// of other signatures, the whole batch would fail! + /// + /// # "Strict" Verification + /// + /// This method performs *both* of the above signature malleability checks. + /// + /// It must be done as a separate method because one doesn't simply get to + /// change the definition of a cryptographic primitive ten years + /// after-the-fact with zero consideration for backwards compatibility in + /// hardware and protocols which have it already have the older definition + /// baked in. + /// + /// # Return + /// + /// Returns `Ok(())` if the signature is valid, and `Err` otherwise. + #[allow(non_snake_case)] + pub fn verify_strict( + &self, + message: &[u8], + signature: &Signature, + ) -> Result<(), SignatureError> { + self.verifying_key.verify_strict(message, signature) + } + + /// Convert this signing key into a byte representation of a(n) (unreduced) Curve25519 scalar. + /// + /// This can be used for performing X25519 Diffie-Hellman using Ed25519 keys. The bytes output + /// by this function are a valid secret key for the X25519 public key given by + /// `self.verifying_key().to_montgomery()`. + /// + /// # Note + /// + /// We do NOT recommend this usage of a signing/verifying key. Signing keys are usually + /// long-term keys, while keys used for key exchange should rather be ephemeral. If you can + /// help it, use a separate key for encryption. + /// + /// For more information on the security of systems which use the same keys for both signing + /// and Diffie-Hellman, see the paper + /// [On using the same key pair for Ed25519 and an X25519 based KEM](https://eprint.iacr.org/2021/509). + pub fn to_scalar_bytes(&self) -> [u8; 32] { + ExpandedSecretKey::from(&self.secret_key).scalar_bytes + } +} + +impl AsRef for SigningKey { + fn as_ref(&self) -> &VerifyingKey { + &self.verifying_key + } +} + +impl KeypairRef for SigningKey { + type VerifyingKey = VerifyingKey; +} + +impl Signer for SigningKey { + /// Sign a message with this signing key's secret key. + fn try_sign(&self, message: &[u8]) -> Result { + let expanded: ExpandedSecretKey = (&self.secret_key).into(); + Ok(expanded.raw_sign::(message, &self.verifying_key)) + } +} + +/// Equivalent to [`SigningKey::sign_prehashed`] with `context` set to [`None`]. +/// +/// # Note +/// +/// The RFC only permits SHA-512 to be used for prehashing. This function technically works, and is +/// probably safe to use, with any secure hash function with 512-bit digests, but anything outside +/// of SHA-512 is NOT specification-compliant. We expose [`crate::Sha512`] for user convenience. +#[cfg(feature = "digest")] +impl DigestSigner for SigningKey +where + D: Digest, +{ + fn try_sign_digest(&self, msg_digest: D) -> Result { + self.sign_prehashed(msg_digest, None) + } +} + +/// Equivalent to [`SigningKey::sign_prehashed`] with `context` set to [`Some`] +/// containing `self.value()`. +/// +/// # Note +/// +/// The RFC only permits SHA-512 to be used for prehashing. This function technically works, and is +/// probably safe to use, with any secure hash function with 512-bit digests, but anything outside +/// of SHA-512 is NOT specification-compliant. We expose [`crate::Sha512`] for user convenience. +#[cfg(feature = "digest")] +impl DigestSigner for Context<'_, '_, SigningKey> +where + D: Digest, +{ + fn try_sign_digest(&self, msg_digest: D) -> Result { + self.key().sign_prehashed(msg_digest, Some(self.value())) + } +} + +impl Verifier for SigningKey { + /// Verify a signature on a message with this signing key's public key. + fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> { + self.verifying_key.verify(message, signature) + } +} + +impl From for SigningKey { + #[inline] + fn from(secret: SecretKey) -> Self { + Self::from_bytes(&secret) + } +} + +impl From<&SecretKey> for SigningKey { + #[inline] + fn from(secret: &SecretKey) -> Self { + Self::from_bytes(secret) + } +} + +impl TryFrom<&[u8]> for SigningKey { + type Error = SignatureError; + + fn try_from(bytes: &[u8]) -> Result { + SecretKey::try_from(bytes) + .map(|bytes| Self::from_bytes(&bytes)) + .map_err(|_| { + InternalError::BytesLength { + name: "SecretKey", + length: SECRET_KEY_LENGTH, + } + .into() + }) + } +} + +#[cfg(feature = "zeroize")] +impl Drop for SigningKey { + fn drop(&mut self) { + self.secret_key.zeroize(); + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for SigningKey {} + +#[cfg(all(feature = "alloc", feature = "pkcs8"))] +impl pkcs8::EncodePrivateKey for SigningKey { + fn to_pkcs8_der(&self) -> pkcs8::Result { + pkcs8::KeypairBytes::from(self).to_pkcs8_der() + } +} + +#[cfg(feature = "pkcs8")] +impl TryFrom for SigningKey { + type Error = pkcs8::Error; + + fn try_from(pkcs8_key: pkcs8::KeypairBytes) -> pkcs8::Result { + SigningKey::try_from(&pkcs8_key) + } +} + +#[cfg(feature = "pkcs8")] +impl TryFrom<&pkcs8::KeypairBytes> for SigningKey { + type Error = pkcs8::Error; + + fn try_from(pkcs8_key: &pkcs8::KeypairBytes) -> pkcs8::Result { + let signing_key = SigningKey::from_bytes(&pkcs8_key.secret_key); + + // Validate the public key in the PKCS#8 document if present + if let Some(public_bytes) = &pkcs8_key.public_key { + let expected_verifying_key = VerifyingKey::from_bytes(public_bytes.as_ref()) + .map_err(|_| pkcs8::Error::KeyMalformed)?; + + if signing_key.verifying_key() != expected_verifying_key { + return Err(pkcs8::Error::KeyMalformed); + } + } + + Ok(signing_key) + } +} + +#[cfg(feature = "pkcs8")] +impl From for pkcs8::KeypairBytes { + fn from(signing_key: SigningKey) -> pkcs8::KeypairBytes { + pkcs8::KeypairBytes::from(&signing_key) + } +} + +#[cfg(feature = "pkcs8")] +impl From<&SigningKey> for pkcs8::KeypairBytes { + fn from(signing_key: &SigningKey) -> pkcs8::KeypairBytes { + pkcs8::KeypairBytes { + secret_key: signing_key.to_bytes(), + public_key: Some(pkcs8::PublicKeyBytes(signing_key.verifying_key.to_bytes())), + } + } +} + +#[cfg(feature = "pkcs8")] +impl TryFrom> for SigningKey { + type Error = pkcs8::Error; + + fn try_from(private_key: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result { + pkcs8::KeypairBytes::try_from(private_key)?.try_into() + } +} + +#[cfg(feature = "serde")] +impl Serialize for SigningKey { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(&self.secret_key) + } +} + +#[cfg(feature = "serde")] +impl<'d> Deserialize<'d> for SigningKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'d>, + { + struct SigningKeyVisitor; + + impl<'de> serde::de::Visitor<'de> for SigningKeyVisitor { + type Value = SigningKey; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(formatter, concat!("An ed25519 signing (private) key")) + } + + fn visit_borrowed_bytes( + self, + bytes: &'de [u8], + ) -> Result { + SigningKey::try_from(bytes.as_ref()).map_err(E::custom) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut bytes = [0u8; 32]; + for i in 0..32 { + bytes[i] = seq + .next_element()? + .ok_or_else(|| serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; + } + + let remaining = (0..) + .map(|_| seq.next_element::()) + .take_while(|el| matches!(el, Ok(Some(_)))) + .count(); + + if remaining > 0 { + return Err(serde::de::Error::invalid_length( + 32 + remaining, + &"expected 32 bytes", + )); + } + + SigningKey::try_from(bytes).map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_bytes(SigningKeyVisitor) + } +} + +/// The spec-compliant way to define an expanded secret key. This computes `SHA512(sk)`, clamps the +/// first 32 bytes and uses it as a scalar, and uses the second 32 bytes as a domain separator for +/// hashing. +impl From<&SecretKey> for ExpandedSecretKey { + #[allow(clippy::unwrap_used)] + fn from(secret_key: &SecretKey) -> ExpandedSecretKey { + let hash = Sha512::default().chain_update(secret_key).finalize(); + ExpandedSecretKey::from_bytes(hash.as_ref()) + } +} + +// +// Signing functions. These are pub(crate) so that the `hazmat` module can use them +// + +impl ExpandedSecretKey { + /// The plain, non-prehashed, signing function for Ed25519. `CtxDigest` is the digest used to + /// calculate the pseudorandomness needed for signing. According to the spec, `CtxDigest = + /// Sha512`, and `self` is derived via the method defined in `impl From<&SigningKey> for + /// ExpandedSecretKey`. + /// + /// This definition is loose in its parameters so that end-users of the `hazmat` module can + /// change how the `ExpandedSecretKey` is calculated and which hash function to use. + #[allow(non_snake_case)] + #[inline(always)] + pub(crate) fn raw_sign( + &self, + message: &[u8], + verifying_key: &VerifyingKey, + ) -> Signature + where + CtxDigest: Digest, + { + let mut h = CtxDigest::new(); + + h.update(self.hash_prefix); + h.update(message); + + let r = Scalar::from_hash(h); + let R: CompressedEdwardsY = EdwardsPoint::mul_base(&r).compress(); + + h = CtxDigest::new(); + h.update(R.as_bytes()); + h.update(verifying_key.as_bytes()); + h.update(message); + + let k = Scalar::from_hash(h); + let s: Scalar = (k * self.scalar) + r; + + InternalSignature { R, s }.into() + } + + /// The prehashed signing function for Ed25519 (i.e., Ed25519ph). `CtxDigest` is the digest + /// function used to calculate the pseudorandomness needed for signing. `MsgDigest` is the + /// digest function used to hash the signed message. According to the spec, `MsgDigest = + /// CtxDigest = Sha512`, and `self` is derived via the method defined in `impl + /// From<&SigningKey> for ExpandedSecretKey`. + /// + /// This definition is loose in its parameters so that end-users of the `hazmat` module can + /// change how the `ExpandedSecretKey` is calculated and which `CtxDigest` function to use. + #[cfg(feature = "digest")] + #[allow(non_snake_case)] + #[inline(always)] + pub(crate) fn raw_sign_prehashed<'a, CtxDigest, MsgDigest>( + &self, + prehashed_message: MsgDigest, + verifying_key: &VerifyingKey, + context: Option<&'a [u8]>, + ) -> Result + where + CtxDigest: Digest, + MsgDigest: Digest, + { + let mut prehash: [u8; 64] = [0u8; 64]; + + let ctx: &[u8] = context.unwrap_or(b""); // By default, the context is an empty string. + + if ctx.len() > 255 { + return Err(SignatureError::from(InternalError::PrehashedContextLength)); + } + + let ctx_len: u8 = ctx.len() as u8; + + // Get the result of the pre-hashed message. + prehash.copy_from_slice(prehashed_message.finalize().as_slice()); + + // This is the dumbest, ten-years-late, non-admission of fucking up the + // domain separation I have ever seen. Why am I still required to put + // the upper half "prefix" of the hashed "secret key" in here? Why + // can't the user just supply their own nonce and decide for themselves + // whether or not they want a deterministic signature scheme? Why does + // the message go into what's ostensibly the signature domain separation + // hash? Why wasn't there always a way to provide a context string? + // + // ... + // + // This is a really fucking stupid bandaid, and the damned scheme is + // still bleeding from malleability, for fuck's sake. + let mut h = CtxDigest::new() + .chain_update(b"SigEd25519 no Ed25519 collisions") + .chain_update([1]) // Ed25519ph + .chain_update([ctx_len]) + .chain_update(ctx) + .chain_update(self.hash_prefix) + .chain_update(&prehash[..]); + + let r = Scalar::from_hash(h); + let R: CompressedEdwardsY = EdwardsPoint::mul_base(&r).compress(); + + h = CtxDigest::new() + .chain_update(b"SigEd25519 no Ed25519 collisions") + .chain_update([1]) // Ed25519ph + .chain_update([ctx_len]) + .chain_update(ctx) + .chain_update(R.as_bytes()) + .chain_update(verifying_key.as_bytes()) + .chain_update(&prehash[..]); + + let k = Scalar::from_hash(h); + let s: Scalar = (k * self.scalar) + r; + + Ok(InternalSignature { R, s }.into()) + } +} diff --git a/ed25519-dalek/src/verifying.rs b/ed25519-dalek/src/verifying.rs new file mode 100644 index 000000000..1d25f3856 --- /dev/null +++ b/ed25519-dalek/src/verifying.rs @@ -0,0 +1,686 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! ed25519 public keys. + +use core::convert::TryFrom; +use core::fmt::Debug; +use core::hash::{Hash, Hasher}; + +use curve25519_dalek::{ + digest::{generic_array::typenum::U64, Digest}, + edwards::{CompressedEdwardsY, EdwardsPoint}, + montgomery::MontgomeryPoint, + scalar::Scalar, +}; + +use ed25519::signature::Verifier; + +use sha2::Sha512; + +#[cfg(feature = "pkcs8")] +use ed25519::pkcs8; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[cfg(feature = "digest")] +use crate::context::Context; +#[cfg(feature = "digest")] +use signature::DigestVerifier; + +use crate::{ + constants::PUBLIC_KEY_LENGTH, + errors::{InternalError, SignatureError}, + hazmat::ExpandedSecretKey, + signature::InternalSignature, + signing::SigningKey, +}; + +/// An ed25519 public key. +/// +/// # Note +/// +/// The `Eq` and `Hash` impls here use the compressed Edwards y encoding, _not_ the algebraic +/// representation. This means if this `VerifyingKey` is non-canonically encoded, it will be +/// considered unequal to the other equivalent encoding, despite the two representing the same +/// point. More encoding details can be found +/// [here](https://hdevalence.ca/blog/2020-10-04-its-25519am). +/// If you want to make sure that signatures produced with respect to those sorts of public keys +/// are rejected, use [`VerifyingKey::verify_strict`]. +// Invariant: VerifyingKey.1 is always the decompression of VerifyingKey.0 +#[derive(Copy, Clone, Default, Eq)] +pub struct VerifyingKey { + /// Serialized compressed Edwards-y point. + pub(crate) compressed: CompressedEdwardsY, + + /// Decompressed Edwards point used for curve arithmetic operations. + pub(crate) point: EdwardsPoint, +} + +impl Debug for VerifyingKey { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "VerifyingKey({:?}), {:?})", self.compressed, self.point) + } +} + +impl AsRef<[u8]> for VerifyingKey { + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +impl Hash for VerifyingKey { + fn hash(&self, state: &mut H) { + self.as_bytes().hash(state); + } +} + +impl PartialEq for VerifyingKey { + fn eq(&self, other: &VerifyingKey) -> bool { + self.as_bytes() == other.as_bytes() + } +} + +impl From<&ExpandedSecretKey> for VerifyingKey { + /// Derive this public key from its corresponding `ExpandedSecretKey`. + fn from(expanded_secret_key: &ExpandedSecretKey) -> VerifyingKey { + VerifyingKey::clamp_and_mul_base(expanded_secret_key.scalar_bytes) + } +} + +impl From<&SigningKey> for VerifyingKey { + fn from(signing_key: &SigningKey) -> VerifyingKey { + signing_key.verifying_key() + } +} + +impl From for VerifyingKey { + fn from(point: EdwardsPoint) -> VerifyingKey { + VerifyingKey { + point, + compressed: point.compress(), + } + } +} + +impl VerifyingKey { + /// Convert this public key to a byte array. + #[inline] + pub fn to_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH] { + self.compressed.to_bytes() + } + + /// View this public key as a byte array. + #[inline] + pub fn as_bytes(&self) -> &[u8; PUBLIC_KEY_LENGTH] { + &(self.compressed).0 + } + + /// Construct a `VerifyingKey` from a slice of bytes. + /// + /// # Warning + /// + /// The caller is responsible for ensuring that the bytes passed into this + /// method actually represent a `curve25519_dalek::curve::CompressedEdwardsY` + /// and that said compressed point is actually a point on the curve. + /// + /// # Example + /// + /// ``` + /// use ed25519_dalek::VerifyingKey; + /// use ed25519_dalek::PUBLIC_KEY_LENGTH; + /// use ed25519_dalek::SignatureError; + /// + /// # fn doctest() -> Result { + /// let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = [ + /// 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, + /// 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26]; + /// + /// let public_key = VerifyingKey::from_bytes(&public_key_bytes)?; + /// # + /// # Ok(public_key) + /// # } + /// # + /// # fn main() { + /// # doctest(); + /// # } + /// ``` + /// + /// # Returns + /// + /// A `Result` whose okay value is an EdDSA `VerifyingKey` or whose error value + /// is a `SignatureError` describing the error that occurred. + #[inline] + pub fn from_bytes(bytes: &[u8; PUBLIC_KEY_LENGTH]) -> Result { + let compressed = CompressedEdwardsY(*bytes); + let point = compressed + .decompress() + .ok_or(InternalError::PointDecompression)?; + + // Invariant: VerifyingKey.1 is always the decompression of VerifyingKey.0 + Ok(VerifyingKey { compressed, point }) + } + + /// Create a verifying context that can be used for Ed25519ph with + /// [`DigestVerifier`]. + #[cfg(feature = "digest")] + pub fn with_context<'k, 'v>( + &'k self, + context_value: &'v [u8], + ) -> Result, SignatureError> { + Context::new(self, context_value) + } + + /// Returns whether this is a _weak_ public key, i.e., if this public key has low order. + /// + /// A weak public key can be used to generate a signature that's valid for almost every + /// message. [`Self::verify_strict`] denies weak keys, but if you want to check for this + /// property before verification, then use this method. + pub fn is_weak(&self) -> bool { + self.point.is_small_order() + } + + /// Internal utility function for clamping a scalar representation and multiplying by the + /// basepont to produce a public key. + fn clamp_and_mul_base(bits: [u8; 32]) -> VerifyingKey { + let point = EdwardsPoint::mul_base_clamped(bits); + let compressed = point.compress(); + + // Invariant: VerifyingKey.1 is always the decompression of VerifyingKey.0 + VerifyingKey { compressed, point } + } + + // A helper function that computes `H(R || A || M)` where `H` is the 512-bit hash function + // given by `CtxDigest` (this is SHA-512 in spec-compliant Ed25519). If `context.is_some()`, + // this does the prehashed variant of the computation using its contents. + #[allow(non_snake_case)] + fn compute_challenge( + context: Option<&[u8]>, + R: &CompressedEdwardsY, + A: &CompressedEdwardsY, + M: &[u8], + ) -> Scalar + where + CtxDigest: Digest, + { + let mut h = CtxDigest::new(); + if let Some(c) = context { + h.update(b"SigEd25519 no Ed25519 collisions"); + h.update([1]); // Ed25519ph + h.update([c.len() as u8]); + h.update(c); + } + h.update(R.as_bytes()); + h.update(A.as_bytes()); + h.update(M); + + Scalar::from_hash(h) + } + + // Helper function for verification. Computes the _expected_ R component of the signature. The + // caller compares this to the real R component. If `context.is_some()`, this does the + // prehashed variant of the computation using its contents. + // Note that this returns the compressed form of R and the caller does a byte comparison. This + // means that all our verification functions do not accept non-canonically encoded R values. + // See the validation criteria blog post for more details: + // https://hdevalence.ca/blog/2020-10-04-its-25519am + #[allow(non_snake_case)] + fn recompute_R( + &self, + context: Option<&[u8]>, + signature: &InternalSignature, + M: &[u8], + ) -> CompressedEdwardsY + where + CtxDigest: Digest, + { + let k = Self::compute_challenge::(context, &signature.R, &self.compressed, M); + let minus_A: EdwardsPoint = -self.point; + // Recall the (non-batched) verification equation: -[k]A + [s]B = R + EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s).compress() + } + + /// The ordinary non-batched Ed25519 verification check, rejecting non-canonical R values. (see + /// [`Self::recompute_R`]). `CtxDigest` is the digest used to calculate the pseudorandomness + /// needed for signing. According to the spec, `CtxDigest = Sha512`. + /// + /// This definition is loose in its parameters so that end-users of the `hazmat` module can + /// change how the `ExpandedSecretKey` is calculated and which hash function to use. + #[allow(non_snake_case)] + pub(crate) fn raw_verify( + &self, + message: &[u8], + signature: &ed25519::Signature, + ) -> Result<(), SignatureError> + where + CtxDigest: Digest, + { + let signature = InternalSignature::try_from(signature)?; + + let expected_R = self.recompute_R::(None, &signature, message); + if expected_R == signature.R { + Ok(()) + } else { + Err(InternalError::Verify.into()) + } + } + + /// The prehashed non-batched Ed25519 verification check, rejecting non-canonical R values. + /// (see [`Self::recompute_R`]). `CtxDigest` is the digest used to calculate the + /// pseudorandomness needed for signing. `MsgDigest` is the digest used to hash the signed + /// message. According to the spec, `MsgDigest = CtxDigest = Sha512`. + /// + /// This definition is loose in its parameters so that end-users of the `hazmat` module can + /// change how the `ExpandedSecretKey` is calculated and which hash function to use. + #[cfg(feature = "digest")] + #[allow(non_snake_case)] + pub(crate) fn raw_verify_prehashed( + &self, + prehashed_message: MsgDigest, + context: Option<&[u8]>, + signature: &ed25519::Signature, + ) -> Result<(), SignatureError> + where + CtxDigest: Digest, + MsgDigest: Digest, + { + let signature = InternalSignature::try_from(signature)?; + + let ctx: &[u8] = context.unwrap_or(b""); + debug_assert!( + ctx.len() <= 255, + "The context must not be longer than 255 octets." + ); + + let message = prehashed_message.finalize(); + let expected_R = self.recompute_R::(Some(ctx), &signature, &message); + + if expected_R == signature.R { + Ok(()) + } else { + Err(InternalError::Verify.into()) + } + } + + /// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm. + /// + /// # Inputs + /// + /// * `prehashed_message` is an instantiated hash digest with 512-bits of + /// output which has had the message to be signed previously fed into its + /// state. + /// * `context` is an optional context string, up to 255 bytes inclusive, + /// which may be used to provide additional domain separation. If not + /// set, this will default to an empty string. + /// * `signature` is a purported Ed25519ph signature on the `prehashed_message`. + /// + /// # Returns + /// + /// Returns `true` if the `signature` was a valid signature created by this + /// [`SigningKey`] on the `prehashed_message`. + /// + /// # Note + /// + /// The RFC only permits SHA-512 to be used for prehashing, i.e., `MsgDigest = Sha512`. This + /// function technically works, and is probably safe to use, with any secure hash function with + /// 512-bit digests, but anything outside of SHA-512 is NOT specification-compliant. We expose + /// [`crate::Sha512`] for user convenience. + #[cfg(feature = "digest")] + #[allow(non_snake_case)] + pub fn verify_prehashed( + &self, + prehashed_message: MsgDigest, + context: Option<&[u8]>, + signature: &ed25519::Signature, + ) -> Result<(), SignatureError> + where + MsgDigest: Digest, + { + self.raw_verify_prehashed::(prehashed_message, context, signature) + } + + /// Strictly verify a signature on a message with this keypair's public key. + /// + /// # On The (Multiple) Sources of Malleability in Ed25519 Signatures + /// + /// This version of verification is technically non-RFC8032 compliant. The + /// following explains why. + /// + /// 1. Scalar Malleability + /// + /// The authors of the RFC explicitly stated that verification of an ed25519 + /// signature must fail if the scalar `s` is not properly reduced mod $\ell$: + /// + /// > To verify a signature on a message M using public key A, with F + /// > being 0 for Ed25519ctx, 1 for Ed25519ph, and if Ed25519ctx or + /// > Ed25519ph is being used, C being the context, first split the + /// > signature into two 32-octet halves. Decode the first half as a + /// > point R, and the second half as an integer S, in the range + /// > 0 <= s < L. Decode the public key A as point A'. If any of the + /// > decodings fail (including S being out of range), the signature is + /// > invalid.) + /// + /// All `verify_*()` functions within ed25519-dalek perform this check. + /// + /// 2. Point malleability + /// + /// The authors of the RFC added in a malleability check to step #3 in + /// §5.1.7, for small torsion components in the `R` value of the signature, + /// *which is not strictly required*, as they state: + /// + /// > Check the group equation \[8\]\[S\]B = \[8\]R + \[8\]\[k\]A'. It's + /// > sufficient, but not required, to instead check \[S\]B = R + \[k\]A'. + /// + /// # History of Malleability Checks + /// + /// As originally defined (cf. the "Malleability" section in the README of + /// this repo), ed25519 signatures didn't consider *any* form of + /// malleability to be an issue. Later the scalar malleability was + /// considered important. Still later, particularly with interests in + /// cryptocurrency design and in unique identities (e.g. for Signal users, + /// Tor onion services, etc.), the group element malleability became a + /// concern. + /// + /// However, libraries had already been created to conform to the original + /// definition. One well-used library in particular even implemented the + /// group element malleability check, *but only for batch verification*! + /// Which meant that even using the same library, a single signature could + /// verify fine individually, but suddenly, when verifying it with a bunch + /// of other signatures, the whole batch would fail! + /// + /// # "Strict" Verification + /// + /// This method performs *both* of the above signature malleability checks. + /// + /// It must be done as a separate method because one doesn't simply get to + /// change the definition of a cryptographic primitive ten years + /// after-the-fact with zero consideration for backwards compatibility in + /// hardware and protocols which have it already have the older definition + /// baked in. + /// + /// # Return + /// + /// Returns `Ok(())` if the signature is valid, and `Err` otherwise. + #[allow(non_snake_case)] + pub fn verify_strict( + &self, + message: &[u8], + signature: &ed25519::Signature, + ) -> Result<(), SignatureError> { + let signature = InternalSignature::try_from(signature)?; + + let signature_R = signature + .R + .decompress() + .ok_or_else(|| SignatureError::from(InternalError::Verify))?; + + // Logical OR is fine here as we're not trying to be constant time. + if signature_R.is_small_order() || self.point.is_small_order() { + return Err(InternalError::Verify.into()); + } + + let expected_R = self.recompute_R::(None, &signature, message); + if expected_R == signature.R { + Ok(()) + } else { + Err(InternalError::Verify.into()) + } + } + + /// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm, + /// using strict signture checking as defined by [`Self::verify_strict`]. + /// + /// # Inputs + /// + /// * `prehashed_message` is an instantiated hash digest with 512-bits of + /// output which has had the message to be signed previously fed into its + /// state. + /// * `context` is an optional context string, up to 255 bytes inclusive, + /// which may be used to provide additional domain separation. If not + /// set, this will default to an empty string. + /// * `signature` is a purported Ed25519ph signature on the `prehashed_message`. + /// + /// # Returns + /// + /// Returns `true` if the `signature` was a valid signature created by this + /// [`SigningKey`] on the `prehashed_message`. + /// + /// # Note + /// + /// The RFC only permits SHA-512 to be used for prehashing, i.e., `MsgDigest = Sha512`. This + /// function technically works, and is probably safe to use, with any secure hash function with + /// 512-bit digests, but anything outside of SHA-512 is NOT specification-compliant. We expose + /// [`crate::Sha512`] for user convenience. + #[cfg(feature = "digest")] + #[allow(non_snake_case)] + pub fn verify_prehashed_strict( + &self, + prehashed_message: MsgDigest, + context: Option<&[u8]>, + signature: &ed25519::Signature, + ) -> Result<(), SignatureError> + where + MsgDigest: Digest, + { + let signature = InternalSignature::try_from(signature)?; + + let ctx: &[u8] = context.unwrap_or(b""); + debug_assert!( + ctx.len() <= 255, + "The context must not be longer than 255 octets." + ); + + let signature_R = signature + .R + .decompress() + .ok_or_else(|| SignatureError::from(InternalError::Verify))?; + + // Logical OR is fine here as we're not trying to be constant time. + if signature_R.is_small_order() || self.point.is_small_order() { + return Err(InternalError::Verify.into()); + } + + let message = prehashed_message.finalize(); + let expected_R = self.recompute_R::(Some(ctx), &signature, &message); + + if expected_R == signature.R { + Ok(()) + } else { + Err(InternalError::Verify.into()) + } + } + + /// Convert this verifying key into Montgomery form. + /// + /// This can be used for performing X25519 Diffie-Hellman using Ed25519 keys. The output of + /// this function is a valid X25519 public key whose secret key is `sk.to_scalar_bytes()`, + /// where `sk` is a valid signing key for this `VerifyingKey`. + /// + /// # Note + /// + /// We do NOT recommend this usage of a signing/verifying key. Signing keys are usually + /// long-term keys, while keys used for key exchange should rather be ephemeral. If you can + /// help it, use a separate key for encryption. + /// + /// For more information on the security of systems which use the same keys for both signing + /// and Diffie-Hellman, see the paper + /// [On using the same key pair for Ed25519 and an X25519 based KEM](https://eprint.iacr.org/2021/509). + pub fn to_montgomery(&self) -> MontgomeryPoint { + self.point.to_montgomery() + } +} + +impl Verifier for VerifyingKey { + /// Verify a signature on a message with this keypair's public key. + /// + /// # Return + /// + /// Returns `Ok(())` if the signature is valid, and `Err` otherwise. + fn verify(&self, message: &[u8], signature: &ed25519::Signature) -> Result<(), SignatureError> { + self.raw_verify::(message, signature) + } +} + +/// Equivalent to [`VerifyingKey::verify_prehashed`] with `context` set to [`None`]. +#[cfg(feature = "digest")] +impl DigestVerifier for VerifyingKey +where + MsgDigest: Digest, +{ + fn verify_digest( + &self, + msg_digest: MsgDigest, + signature: &ed25519::Signature, + ) -> Result<(), SignatureError> { + self.verify_prehashed(msg_digest, None, signature) + } +} + +/// Equivalent to [`VerifyingKey::verify_prehashed`] with `context` set to [`Some`] +/// containing `self.value()`. +#[cfg(feature = "digest")] +impl DigestVerifier for Context<'_, '_, VerifyingKey> +where + MsgDigest: Digest, +{ + fn verify_digest( + &self, + msg_digest: MsgDigest, + signature: &ed25519::Signature, + ) -> Result<(), SignatureError> { + self.key() + .verify_prehashed(msg_digest, Some(self.value()), signature) + } +} + +impl TryFrom<&[u8]> for VerifyingKey { + type Error = SignatureError; + + #[inline] + fn try_from(bytes: &[u8]) -> Result { + let bytes = bytes.try_into().map_err(|_| InternalError::BytesLength { + name: "VerifyingKey", + length: PUBLIC_KEY_LENGTH, + })?; + Self::from_bytes(bytes) + } +} + +#[cfg(all(feature = "alloc", feature = "pkcs8"))] +impl pkcs8::EncodePublicKey for VerifyingKey { + fn to_public_key_der(&self) -> pkcs8::spki::Result { + pkcs8::PublicKeyBytes::from(self).to_public_key_der() + } +} + +#[cfg(feature = "pkcs8")] +impl TryFrom for VerifyingKey { + type Error = pkcs8::spki::Error; + + fn try_from(pkcs8_key: pkcs8::PublicKeyBytes) -> pkcs8::spki::Result { + VerifyingKey::try_from(&pkcs8_key) + } +} + +#[cfg(feature = "pkcs8")] +impl TryFrom<&pkcs8::PublicKeyBytes> for VerifyingKey { + type Error = pkcs8::spki::Error; + + fn try_from(pkcs8_key: &pkcs8::PublicKeyBytes) -> pkcs8::spki::Result { + VerifyingKey::from_bytes(pkcs8_key.as_ref()).map_err(|_| pkcs8::spki::Error::KeyMalformed) + } +} + +#[cfg(feature = "pkcs8")] +impl From for pkcs8::PublicKeyBytes { + fn from(verifying_key: VerifyingKey) -> pkcs8::PublicKeyBytes { + pkcs8::PublicKeyBytes::from(&verifying_key) + } +} + +#[cfg(feature = "pkcs8")] +impl From<&VerifyingKey> for pkcs8::PublicKeyBytes { + fn from(verifying_key: &VerifyingKey) -> pkcs8::PublicKeyBytes { + pkcs8::PublicKeyBytes(verifying_key.to_bytes()) + } +} + +#[cfg(feature = "pkcs8")] +impl TryFrom> for VerifyingKey { + type Error = pkcs8::spki::Error; + + fn try_from(public_key: pkcs8::spki::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result { + pkcs8::PublicKeyBytes::try_from(public_key)?.try_into() + } +} + +#[cfg(feature = "serde")] +impl Serialize for VerifyingKey { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(&self.as_bytes()[..]) + } +} + +#[cfg(feature = "serde")] +impl<'d> Deserialize<'d> for VerifyingKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'d>, + { + struct VerifyingKeyVisitor; + + impl<'de> serde::de::Visitor<'de> for VerifyingKeyVisitor { + type Value = VerifyingKey; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(formatter, concat!("An ed25519 verifying (public) key")) + } + + fn visit_borrowed_bytes( + self, + bytes: &'de [u8], + ) -> Result { + VerifyingKey::try_from(bytes.as_ref()).map_err(E::custom) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut bytes = [0u8; 32]; + + for i in 0..32 { + bytes[i] = seq + .next_element()? + .ok_or_else(|| serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; + } + + let remaining = (0..) + .map(|_| seq.next_element::()) + .take_while(|el| matches!(el, Ok(Some(_)))) + .count(); + + if remaining > 0 { + return Err(serde::de::Error::invalid_length( + 32 + remaining, + &"expected 32 bytes", + )); + } + + VerifyingKey::try_from(&bytes[..]).map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_bytes(VerifyingKeyVisitor) + } +} diff --git a/ed25519-dalek/tests/ed25519.rs b/ed25519-dalek/tests/ed25519.rs new file mode 100644 index 000000000..6632f015e --- /dev/null +++ b/ed25519-dalek/tests/ed25519.rs @@ -0,0 +1,660 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2019 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! Integration tests for ed25519-dalek. + +use curve25519_dalek; + +use ed25519_dalek::*; + +use hex::FromHex; +#[cfg(feature = "digest")] +use hex_literal::hex; + +#[cfg(test)] +mod vectors { + use super::*; + + use curve25519_dalek::{ + constants::ED25519_BASEPOINT_POINT, + edwards::{CompressedEdwardsY, EdwardsPoint}, + scalar::Scalar, + traits::IsIdentity, + }; + use sha2::{digest::Digest, Sha512}; + + use std::{ + convert::TryFrom, + fs::File, + io::{BufRead, BufReader}, + ops::Neg, + }; + + // TESTVECTORS is taken from sign.input.gz in agl's ed25519 Golang + // package. It is a selection of test cases from + // http://ed25519.cr.yp.to/python/sign.input + #[test] + fn against_reference_implementation() { + // TestGolden + let mut line: String; + let mut lineno: usize = 0; + + let f = File::open("TESTVECTORS"); + if f.is_err() { + println!( + "This test is only available when the code has been cloned \ + from the git repository, since the TESTVECTORS file is large \ + and is therefore not included within the distributed crate." + ); + panic!(); + } + let file = BufReader::new(f.unwrap()); + + for l in file.lines() { + lineno += 1; + line = l.unwrap(); + + let parts: Vec<&str> = line.split(':').collect(); + assert_eq!(parts.len(), 5, "wrong number of fields in line {}", lineno); + + let sec_bytes: Vec = FromHex::from_hex(&parts[0]).unwrap(); + let pub_bytes: Vec = FromHex::from_hex(&parts[1]).unwrap(); + let msg_bytes: Vec = FromHex::from_hex(&parts[2]).unwrap(); + let sig_bytes: Vec = FromHex::from_hex(&parts[3]).unwrap(); + + let sec_bytes = &sec_bytes[..SECRET_KEY_LENGTH].try_into().unwrap(); + let pub_bytes = &pub_bytes[..PUBLIC_KEY_LENGTH].try_into().unwrap(); + + let signing_key = SigningKey::from_bytes(sec_bytes); + let expected_verifying_key = VerifyingKey::from_bytes(pub_bytes).unwrap(); + assert_eq!(expected_verifying_key, signing_key.verifying_key()); + + // The signatures in the test vectors also include the message + // at the end, but we just want R and S. + let sig1: Signature = Signature::try_from(&sig_bytes[..64]).unwrap(); + let sig2: Signature = signing_key.sign(&msg_bytes); + + assert!(sig1 == sig2, "Signature bytes not equal on line {}", lineno); + assert!( + signing_key.verify(&msg_bytes, &sig2).is_ok(), + "Signature verification failed on line {}", + lineno + ); + assert!( + expected_verifying_key + .verify_strict(&msg_bytes, &sig2) + .is_ok(), + "Signature strict verification failed on line {}", + lineno + ); + } + } + + // From https://tools.ietf.org/html/rfc8032#section-7.3 + #[cfg(feature = "digest")] + #[test] + fn ed25519ph_rf8032_test_vector_prehash() { + let sec_bytes = hex!("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42"); + let pub_bytes = hex!("ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf"); + let msg_bytes = hex!("616263"); + let sig_bytes = hex!("98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406"); + + let signing_key = SigningKey::from_bytes(&sec_bytes); + let expected_verifying_key = VerifyingKey::from_bytes(&pub_bytes).unwrap(); + assert_eq!(expected_verifying_key, signing_key.verifying_key()); + let sig1 = Signature::try_from(&sig_bytes[..]).unwrap(); + + let mut prehash_for_signing = Sha512::default(); + let mut prehash_for_verifying = Sha512::default(); + + prehash_for_signing.update(&msg_bytes[..]); + prehash_for_verifying.update(&msg_bytes[..]); + + let sig2: Signature = signing_key + .sign_prehashed(prehash_for_signing, None) + .unwrap(); + + assert!( + sig1 == sig2, + "Original signature from test vectors doesn't equal signature produced:\ + \noriginal:\n{:?}\nproduced:\n{:?}", + sig1, + sig2 + ); + assert!( + signing_key + .verify_prehashed(prehash_for_verifying.clone(), None, &sig2) + .is_ok(), + "Could not verify ed25519ph signature!" + ); + assert!( + expected_verifying_key + .verify_prehashed_strict(prehash_for_verifying, None, &sig2) + .is_ok(), + "Could not strict-verify ed25519ph signature!" + ); + } + + // + // The remaining items in this mod are for the repudiation tests + // + + // Taken from curve25519_dalek::constants::EIGHT_TORSION[4] + const EIGHT_TORSION_4: [u8; 32] = [ + 236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, + ]; + + // Computes the prehashed or non-prehashed challenge, depending on whether context is given + fn compute_challenge( + message: &[u8], + pub_key: &EdwardsPoint, + signature_r: &EdwardsPoint, + context: Option<&[u8]>, + ) -> Scalar { + let mut h = Sha512::default(); + if let Some(c) = context { + h.update(b"SigEd25519 no Ed25519 collisions"); + h.update(&[1]); + h.update(&[c.len() as u8]); + h.update(c); + } + h.update(&signature_r.compress().as_bytes()); + h.update(&pub_key.compress().as_bytes()[..]); + h.update(&message); + Scalar::from_hash(h) + } + + fn serialize_signature(r: &EdwardsPoint, s: &Scalar) -> Vec { + [&r.compress().as_bytes()[..], &s.as_bytes()[..]].concat() + } + + const WEAK_PUBKEY: CompressedEdwardsY = CompressedEdwardsY(EIGHT_TORSION_4); + + // Pick a random Scalar + fn non_null_scalar() -> Scalar { + let mut rng = rand::rngs::OsRng; + let mut s_candidate = Scalar::random(&mut rng); + while s_candidate == Scalar::ZERO { + s_candidate = Scalar::random(&mut rng); + } + s_candidate + } + + fn pick_r(s: Scalar) -> EdwardsPoint { + let r0 = s * ED25519_BASEPOINT_POINT; + // Pick a torsion point of order 2 + r0 + WEAK_PUBKEY.decompress().unwrap().neg() + } + + // Tests that verify_strict() rejects small-order pubkeys. We test this by explicitly + // constructing a pubkey-signature pair that verifies with respect to two distinct messages. + // This should be accepted by verify(), but rejected by verify_strict(). + #[test] + fn repudiation() { + let message1 = b"Send 100 USD to Alice"; + let message2 = b"Send 100000 USD to Alice"; + + let mut s: Scalar = non_null_scalar(); + let pubkey = WEAK_PUBKEY.decompress().unwrap(); + let mut r = pick_r(s); + + // Find an R such that + // H(R || A || M₁) · A == A == H(R || A || M₂) · A + // This happens with high probability when A is low order. + while !(pubkey.neg() + compute_challenge(message1, &pubkey, &r, None) * pubkey) + .is_identity() + || !(pubkey.neg() + compute_challenge(message2, &pubkey, &r, None) * pubkey) + .is_identity() + { + // We pick an s and let R = sB - A where B is the basepoint + s = non_null_scalar(); + r = pick_r(s); + } + + // At this point, both verification equations hold: + // sB = R + H(R || A || M₁) · A + // = R + H(R || A || M₂) · A + // Check that this is true + let signature = serialize_signature(&r, &s); + let vk = VerifyingKey::from_bytes(&pubkey.compress().as_bytes()).unwrap(); + let sig = Signature::try_from(&signature[..]).unwrap(); + assert!(vk.verify(message1, &sig).is_ok()); + assert!(vk.verify(message2, &sig).is_ok()); + + // Check that this public key appears as weak + assert!(vk.is_weak()); + + // Now check that the sigs fail under verify_strict. This is because verify_strict rejects + // small order pubkeys. + assert!(vk.verify_strict(message1, &sig).is_err()); + assert!(vk.verify_strict(message2, &sig).is_err()); + } + + // Identical to repudiation() above, but testing verify_prehashed against + // verify_prehashed_strict. See comments above for a description of what's happening. + #[cfg(feature = "digest")] + #[test] + fn repudiation_prehash() { + let message1 = Sha512::new().chain_update(b"Send 100 USD to Alice"); + let message2 = Sha512::new().chain_update(b"Send 100000 USD to Alice"); + let message1_bytes = message1.clone().finalize(); + let message2_bytes = message2.clone().finalize(); + + let mut s: Scalar = non_null_scalar(); + let pubkey = WEAK_PUBKEY.decompress().unwrap(); + let mut r = pick_r(s); + let context_str = Some(&b"edtest"[..]); + + while !(pubkey.neg() + + compute_challenge(&message1_bytes, &pubkey, &r, context_str) * pubkey) + .is_identity() + || !(pubkey.neg() + + compute_challenge(&message2_bytes, &pubkey, &r, context_str) * pubkey) + .is_identity() + { + s = non_null_scalar(); + r = pick_r(s); + } + + // Check that verify_prehashed succeeds on both sigs + let signature = serialize_signature(&r, &s); + let vk = VerifyingKey::from_bytes(&pubkey.compress().as_bytes()).unwrap(); + let sig = Signature::try_from(&signature[..]).unwrap(); + assert!(vk + .verify_prehashed(message1.clone(), context_str, &sig) + .is_ok()); + assert!(vk + .verify_prehashed(message2.clone(), context_str, &sig) + .is_ok()); + + // Check that verify_prehashed_strict fails on both sigs + assert!(vk + .verify_prehashed_strict(message1.clone(), context_str, &sig) + .is_err()); + assert!(vk + .verify_prehashed_strict(message2.clone(), context_str, &sig) + .is_err()); + } +} + +#[cfg(feature = "rand_core")] +mod integrations { + use super::*; + use rand::rngs::OsRng; + #[cfg(feature = "digest")] + use sha2::Sha512; + use std::collections::HashMap; + + #[test] + fn sign_verify() { + // TestSignVerify + let signing_key: SigningKey; + let good_sig: Signature; + let bad_sig: Signature; + + let good: &[u8] = "test message".as_bytes(); + let bad: &[u8] = "wrong message".as_bytes(); + + let mut csprng = OsRng; + + signing_key = SigningKey::generate(&mut csprng); + let verifying_key = signing_key.verifying_key(); + good_sig = signing_key.sign(&good); + bad_sig = signing_key.sign(&bad); + + // Check that an honestly generated public key is not weak + assert!(!verifying_key.is_weak()); + + assert!( + signing_key.verify(&good, &good_sig).is_ok(), + "Verification of a valid signature failed!" + ); + assert!( + verifying_key.verify_strict(&good, &good_sig).is_ok(), + "Strict verification of a valid signature failed!" + ); + assert!( + signing_key.verify(&good, &bad_sig).is_err(), + "Verification of a signature on a different message passed!" + ); + assert!( + verifying_key.verify_strict(&good, &bad_sig).is_err(), + "Strict verification of a signature on a different message passed!" + ); + assert!( + signing_key.verify(&bad, &good_sig).is_err(), + "Verification of a signature on a different message passed!" + ); + assert!( + verifying_key.verify_strict(&bad, &good_sig).is_err(), + "Strict verification of a signature on a different message passed!" + ); + } + + #[cfg(feature = "digest")] + #[test] + fn ed25519ph_sign_verify() { + let signing_key: SigningKey; + let good_sig: Signature; + let bad_sig: Signature; + + let good: &[u8] = b"test message"; + let bad: &[u8] = b"wrong message"; + + let mut csprng = OsRng; + + // ugh… there's no `impl Copy for Sha512`… i hope we can all agree these are the same hashes + let mut prehashed_good1: Sha512 = Sha512::default(); + prehashed_good1.update(good); + let mut prehashed_good2: Sha512 = Sha512::default(); + prehashed_good2.update(good); + let mut prehashed_good3: Sha512 = Sha512::default(); + prehashed_good3.update(good); + + let mut prehashed_bad1: Sha512 = Sha512::default(); + prehashed_bad1.update(bad); + let mut prehashed_bad2: Sha512 = Sha512::default(); + prehashed_bad2.update(bad); + + let context: &[u8] = b"testing testing 1 2 3"; + + signing_key = SigningKey::generate(&mut csprng); + let verifying_key = signing_key.verifying_key(); + good_sig = signing_key + .sign_prehashed(prehashed_good1, Some(context)) + .unwrap(); + bad_sig = signing_key + .sign_prehashed(prehashed_bad1, Some(context)) + .unwrap(); + + assert!( + signing_key + .verify_prehashed(prehashed_good2.clone(), Some(context), &good_sig) + .is_ok(), + "Verification of a valid signature failed!" + ); + assert!( + verifying_key + .verify_prehashed_strict(prehashed_good2, Some(context), &good_sig) + .is_ok(), + "Strict verification of a valid signature failed!" + ); + assert!( + signing_key + .verify_prehashed(prehashed_good3.clone(), Some(context), &bad_sig) + .is_err(), + "Verification of a signature on a different message passed!" + ); + assert!( + verifying_key + .verify_prehashed_strict(prehashed_good3, Some(context), &bad_sig) + .is_err(), + "Strict verification of a signature on a different message passed!" + ); + assert!( + signing_key + .verify_prehashed(prehashed_bad2.clone(), Some(context), &good_sig) + .is_err(), + "Verification of a signature on a different message passed!" + ); + assert!( + verifying_key + .verify_prehashed_strict(prehashed_bad2, Some(context), &good_sig) + .is_err(), + "Strict verification of a signature on a different message passed!" + ); + } + + #[cfg(feature = "batch")] + #[test] + fn verify_batch_seven_signatures() { + let messages: [&[u8]; 7] = [ + b"Watch closely everyone, I'm going to show you how to kill a god.", + b"I'm not a cryptographer I just encrypt a lot.", + b"Still not a cryptographer.", + b"This is a test of the tsunami alert system. This is only a test.", + b"Fuck dumbin' it down, spit ice, skip jewellery: Molotov cocktails on me like accessories.", + b"Hey, I never cared about your bucks, so if I run up with a mask on, probably got a gas can too.", + b"And I'm not here to fill 'er up. Nope, we came to riot, here to incite, we don't want any of your stuff.", ]; + let mut csprng = OsRng; + let mut signing_keys: Vec = Vec::new(); + let mut signatures: Vec = Vec::new(); + + for i in 0..messages.len() { + let signing_key: SigningKey = SigningKey::generate(&mut csprng); + signatures.push(signing_key.sign(&messages[i])); + signing_keys.push(signing_key); + } + let verifying_keys: Vec = + signing_keys.iter().map(|key| key.verifying_key()).collect(); + + let result = verify_batch(&messages, &signatures, &verifying_keys); + + assert!(result.is_ok()); + } + + #[test] + fn public_key_hash_trait_check() { + let mut csprng = OsRng {}; + let secret: SigningKey = SigningKey::generate(&mut csprng); + let public_from_secret: VerifyingKey = (&secret).into(); + + let mut m = HashMap::new(); + m.insert(public_from_secret, "Example_Public_Key"); + + m.insert(public_from_secret, "Updated Value"); + + let (k, v) = m.get_key_value(&public_from_secret).unwrap(); + assert_eq!(k, &public_from_secret); + assert_eq!(v.clone(), "Updated Value"); + assert_eq!(m.len(), 1usize); + + let second_secret: SigningKey = SigningKey::generate(&mut csprng); + let public_from_second_secret: VerifyingKey = (&second_secret).into(); + assert_ne!(public_from_secret, public_from_second_secret); + m.insert(public_from_second_secret, "Second public key"); + + let (k, v) = m.get_key_value(&public_from_second_secret).unwrap(); + assert_eq!(k, &public_from_second_secret); + assert_eq!(v.clone(), "Second public key"); + assert_eq!(m.len(), 2usize); + } +} + +#[cfg(all(test, feature = "serde"))] +#[derive(Debug, serde::Serialize, serde::Deserialize)] +#[serde(crate = "serde")] +struct Demo { + signing_key: SigningKey, +} + +#[cfg(all(test, feature = "serde"))] +mod serialisation { + use super::*; + + // The size for bincode to serialize the length of a byte array. + static BINCODE_INT_LENGTH: usize = 8; + + static PUBLIC_KEY_BYTES: [u8; PUBLIC_KEY_LENGTH] = [ + 130, 039, 155, 015, 062, 076, 188, 063, 124, 122, 026, 251, 233, 253, 225, 220, 014, 041, + 166, 120, 108, 035, 254, 077, 160, 083, 172, 058, 219, 042, 086, 120, + ]; + + static SECRET_KEY_BYTES: [u8; SECRET_KEY_LENGTH] = [ + 062, 070, 027, 163, 092, 182, 011, 003, 077, 234, 098, 004, 011, 127, 079, 228, 243, 187, + 150, 073, 201, 137, 076, 022, 085, 251, 152, 002, 241, 042, 072, 054, + ]; + + /// Signature with the above signing_key of a blank message. + static SIGNATURE_BYTES: [u8; SIGNATURE_LENGTH] = [ + 010, 126, 151, 143, 157, 064, 047, 001, 196, 140, 179, 058, 226, 152, 018, 102, 160, 123, + 080, 016, 210, 086, 196, 028, 053, 231, 012, 157, 169, 019, 158, 063, 045, 154, 238, 007, + 053, 185, 227, 229, 079, 108, 213, 080, 124, 252, 084, 167, 216, 085, 134, 144, 129, 149, + 041, 081, 063, 120, 126, 100, 092, 059, 050, 011, + ]; + + #[test] + fn serialize_deserialize_signature_bincode() { + let signature: Signature = Signature::from_bytes(&SIGNATURE_BYTES); + let encoded_signature: Vec = bincode::serialize(&signature).unwrap(); + let decoded_signature: Signature = bincode::deserialize(&encoded_signature).unwrap(); + + assert_eq!(signature, decoded_signature); + } + + #[test] + fn serialize_deserialize_signature_json() { + let signature: Signature = Signature::from_bytes(&SIGNATURE_BYTES); + let encoded_signature = serde_json::to_string(&signature).unwrap(); + let decoded_signature: Signature = serde_json::from_str(&encoded_signature).unwrap(); + + assert_eq!(signature, decoded_signature); + } + + #[test] + fn serialize_deserialize_verifying_key_bincode() { + let verifying_key: VerifyingKey = VerifyingKey::from_bytes(&PUBLIC_KEY_BYTES).unwrap(); + let encoded_verifying_key: Vec = bincode::serialize(&verifying_key).unwrap(); + let decoded_verifying_key: VerifyingKey = + bincode::deserialize(&encoded_verifying_key).unwrap(); + + assert_eq!( + &PUBLIC_KEY_BYTES[..], + &encoded_verifying_key[encoded_verifying_key.len() - PUBLIC_KEY_LENGTH..] + ); + assert_eq!(verifying_key, decoded_verifying_key); + } + + #[test] + fn serialize_deserialize_verifying_key_json() { + let verifying_key: VerifyingKey = VerifyingKey::from_bytes(&PUBLIC_KEY_BYTES).unwrap(); + let encoded_verifying_key = serde_json::to_string(&verifying_key).unwrap(); + let decoded_verifying_key: VerifyingKey = + serde_json::from_str(&encoded_verifying_key).unwrap(); + + assert_eq!(verifying_key, decoded_verifying_key); + } + + #[test] + fn serialize_deserialize_verifying_key_json_too_long() { + // derived from `serialize_deserialize_verifying_key_json` test + // trailing zero elements makes key too long (34 bytes) + let encoded_verifying_key_too_long = "[130,39,155,15,62,76,188,63,124,122,26,251,233,253,225,220,14,41,166,120,108,35,254,77,160,83,172,58,219,42,86,120,0,0]"; + let de_err = serde_json::from_str::(&encoded_verifying_key_too_long) + .unwrap_err() + .to_string(); + assert!( + de_err.contains("invalid length 34"), + "expected invalid length error, got: {de_err}", + ); + } + + #[test] + fn serialize_deserialize_verifying_key_json_too_short() { + // derived from `serialize_deserialize_verifying_key_json` test + let encoded_verifying_key_too_long = "[130,39,155,15]"; + let de_err = serde_json::from_str::(&encoded_verifying_key_too_long) + .unwrap_err() + .to_string(); + assert!( + de_err.contains("invalid length 4"), + "expected invalid length error, got: {de_err}" + ); + } + + #[test] + fn serialize_deserialize_signing_key_bincode() { + let signing_key = SigningKey::from_bytes(&SECRET_KEY_BYTES); + let encoded_signing_key: Vec = bincode::serialize(&signing_key).unwrap(); + let decoded_signing_key: SigningKey = bincode::deserialize(&encoded_signing_key).unwrap(); + + for i in 0..SECRET_KEY_LENGTH { + assert_eq!(SECRET_KEY_BYTES[i], decoded_signing_key.to_bytes()[i]); + } + } + + #[test] + fn serialize_deserialize_signing_key_json() { + let signing_key = SigningKey::from_bytes(&SECRET_KEY_BYTES); + let encoded_signing_key = serde_json::to_string(&signing_key).unwrap(); + let decoded_signing_key: SigningKey = serde_json::from_str(&encoded_signing_key).unwrap(); + + for i in 0..SECRET_KEY_LENGTH { + assert_eq!(SECRET_KEY_BYTES[i], decoded_signing_key.to_bytes()[i]); + } + } + + #[test] + fn serialize_deserialize_signing_key_json_too_long() { + // derived from `serialize_deserialize_signing_key_json` test + // trailing zero elements makes key too long (34 bytes) + let encoded_signing_key_too_long = "[62,70,27,163,92,182,11,3,77,234,98,4,11,127,79,228,243,187,150,73,201,137,76,22,85,251,152,2,241,42,72,54,0,0]"; + let de_err = serde_json::from_str::(&encoded_signing_key_too_long) + .unwrap_err() + .to_string(); + assert!( + de_err.contains("invalid length 34"), + "expected invalid length error, got: {de_err}", + ); + } + + #[test] + fn serialize_deserialize_signing_key_json_too_short() { + // derived from `serialize_deserialize_signing_key_json` test + let encoded_signing_key_too_long = "[62,70,27,163]"; + let de_err = serde_json::from_str::(&encoded_signing_key_too_long) + .unwrap_err() + .to_string(); + assert!( + de_err.contains("invalid length 4"), + "expected invalid length error, got: {de_err}" + ); + } + + #[test] + fn serialize_deserialize_signing_key_toml() { + let demo = Demo { + signing_key: SigningKey::from_bytes(&SECRET_KEY_BYTES), + }; + + println!("\n\nWrite to toml"); + let demo_toml = toml::to_string(&demo).unwrap(); + println!("{}", demo_toml); + let demo_toml_rebuild: Result = toml::from_str(&demo_toml); + println!("{:?}", demo_toml_rebuild); + } + + #[test] + fn serialize_verifying_key_size() { + let verifying_key: VerifyingKey = VerifyingKey::from_bytes(&PUBLIC_KEY_BYTES).unwrap(); + assert_eq!( + bincode::serialized_size(&verifying_key).unwrap() as usize, + BINCODE_INT_LENGTH + PUBLIC_KEY_LENGTH + ); + } + + #[test] + fn serialize_signature_size() { + let signature: Signature = Signature::from_bytes(&SIGNATURE_BYTES); + assert_eq!( + bincode::serialized_size(&signature).unwrap() as usize, + SIGNATURE_LENGTH + ); + } + + #[test] + fn serialize_signing_key_size() { + let signing_key = SigningKey::from_bytes(&SECRET_KEY_BYTES); + assert_eq!( + bincode::serialized_size(&signing_key).unwrap() as usize, + BINCODE_INT_LENGTH + SECRET_KEY_LENGTH + ); + } +} diff --git a/ed25519-dalek/tests/examples/pkcs8-v1.der b/ed25519-dalek/tests/examples/pkcs8-v1.der new file mode 100644 index 000000000..cb780b362 Binary files /dev/null and b/ed25519-dalek/tests/examples/pkcs8-v1.der differ diff --git a/ed25519-dalek/tests/examples/pkcs8-v2.der b/ed25519-dalek/tests/examples/pkcs8-v2.der new file mode 100644 index 000000000..3358e8a73 Binary files /dev/null and b/ed25519-dalek/tests/examples/pkcs8-v2.der differ diff --git a/ed25519-dalek/tests/examples/pubkey.der b/ed25519-dalek/tests/examples/pubkey.der new file mode 100644 index 000000000..d1002c4a4 Binary files /dev/null and b/ed25519-dalek/tests/examples/pubkey.der differ diff --git a/ed25519-dalek/tests/pkcs8.rs b/ed25519-dalek/tests/pkcs8.rs new file mode 100644 index 000000000..fecdba94e --- /dev/null +++ b/ed25519-dalek/tests/pkcs8.rs @@ -0,0 +1,71 @@ +//! PKCS#8 private key and SPKI public key tests. +//! +//! These are standard formats for storing public and private keys, defined in +//! RFC5958 (PKCS#8) and RFC5280 (SPKI). + +#![cfg(feature = "pkcs8")] + +use ed25519_dalek::pkcs8::{DecodePrivateKey, DecodePublicKey}; +use ed25519_dalek::{SigningKey, VerifyingKey}; +use hex_literal::hex; + +#[cfg(feature = "alloc")] +use ed25519_dalek::pkcs8::{EncodePrivateKey, EncodePublicKey}; + +/// Ed25519 PKCS#8 v1 private key encoded as ASN.1 DER. +const PKCS8_V1_DER: &[u8] = include_bytes!("examples/pkcs8-v1.der"); + +/// Ed25519 PKCS#8 v2 private key + public key encoded as ASN.1 DER. +const PKCS8_V2_DER: &[u8] = include_bytes!("examples/pkcs8-v2.der"); + +/// Ed25519 SubjectVerifyingKeyInfo encoded as ASN.1 DER. +const PUBLIC_KEY_DER: &[u8] = include_bytes!("examples/pubkey.der"); + +/// Secret key bytes. +/// +/// Extracted with: +/// $ openssl asn1parse -inform der -in tests/examples/pkcs8-v1.der +const SK_BYTES: [u8; 32] = hex!("D4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F44755842"); + +/// Public key bytes. +const PK_BYTES: [u8; 32] = hex!("19BF44096984CDFE8541BAC167DC3B96C85086AA30B6B6CB0C5C38AD703166E1"); + +#[test] +fn decode_pkcs8_v1() { + let keypair = SigningKey::from_pkcs8_der(PKCS8_V1_DER).unwrap(); + assert_eq!(SK_BYTES, keypair.to_bytes()); + assert_eq!(PK_BYTES, keypair.verifying_key().to_bytes()); +} + +#[test] +fn decode_pkcs8_v2() { + let keypair = SigningKey::from_pkcs8_der(PKCS8_V2_DER).unwrap(); + assert_eq!(SK_BYTES, keypair.to_bytes()); + assert_eq!(PK_BYTES, keypair.verifying_key().to_bytes()); +} + +#[test] +fn decode_verifying_key() { + let verifying_key = VerifyingKey::from_public_key_der(PUBLIC_KEY_DER).unwrap(); + assert_eq!(PK_BYTES, verifying_key.to_bytes()); +} + +#[test] +#[cfg(feature = "alloc")] +fn encode_pkcs8() { + let keypair = SigningKey::from_bytes(&SK_BYTES); + let pkcs8_key = keypair.to_pkcs8_der().unwrap(); + + let keypair2 = SigningKey::from_pkcs8_der(pkcs8_key.as_bytes()).unwrap(); + assert_eq!(keypair.to_bytes(), keypair2.to_bytes()); +} + +#[test] +#[cfg(feature = "alloc")] +fn encode_verifying_key() { + let verifying_key = VerifyingKey::from_bytes(&PK_BYTES).unwrap(); + let verifying_key_der = verifying_key.to_public_key_der().unwrap(); + + let verifying_key2 = VerifyingKey::from_public_key_der(verifying_key_der.as_bytes()).unwrap(); + assert_eq!(verifying_key, verifying_key2); +} diff --git a/ed25519-dalek/tests/validation_criteria.rs b/ed25519-dalek/tests/validation_criteria.rs new file mode 100644 index 000000000..b7ae83874 --- /dev/null +++ b/ed25519-dalek/tests/validation_criteria.rs @@ -0,0 +1,231 @@ +use ed25519::signature::Verifier; +use ed25519_dalek::{Signature, VerifyingKey}; + +use serde::{de::Error as SError, Deserialize, Deserializer}; +use std::{collections::BTreeSet as Set, fs::File}; + +/// The set of edge cases that [`VerifyingKey::verify()`] permits. +const VERIFY_ALLOWED_EDGECASES: &[Flag] = &[ + Flag::LowOrderA, + Flag::LowOrderR, + Flag::NonCanonicalA, + Flag::LowOrderComponentA, + Flag::LowOrderComponentR, + // `ReencodedK` is not actually permitted by `verify()`, but it looks that way in the tests + // because it sometimes occurs with a low-order A. 1/8 of the time, the resulting signature + // will be identical the one made with a normal k. find_validation_criteria shows that indeed + // this occurs 10/58 of the time + Flag::ReencodedK, +]; + +/// The set of edge cases that [`VerifyingKey::verify_strict()`] permits +const VERIFY_STRICT_ALLOWED_EDGECASES: &[Flag] = + &[Flag::LowOrderComponentA, Flag::LowOrderComponentR]; + +/// Each variant describes a specfiic edge case that can occur in an Ed25519 signature. Refer to +/// the test vector [README][] for more info. +/// +/// [README]: https://github.com/C2SP/CCTV/blob/5ea85644bd035c555900a2f707f7e4c31ea65ced/ed25519vectors/README.md +#[derive(Deserialize, Debug, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)] +enum Flag { + #[serde(rename = "low_order")] + LowOrder, + #[serde(rename = "low_order_A")] + LowOrderA, + #[serde(rename = "low_order_R")] + LowOrderR, + #[serde(rename = "non_canonical_A")] + NonCanonicalA, + #[serde(rename = "non_canonical_R")] + NonCanonicalR, + #[serde(rename = "low_order_component_A")] + LowOrderComponentA, + #[serde(rename = "low_order_component_R")] + LowOrderComponentR, + #[serde(rename = "low_order_residue")] + LowOrderResidue, + #[serde(rename = "reencoded_k")] + ReencodedK, +} + +/// This is an intermediate representation between JSON and TestVector +#[derive(Deserialize)] +struct IntermediateTestVector { + number: usize, + #[serde(deserialize_with = "bytes_from_hex", rename = "key")] + pubkey: Vec, + #[serde(deserialize_with = "bytes_from_hex")] + sig: Vec, + msg: String, + flags: Option>, +} + +/// The test vector struct from [CCTV][]. `sig` may or may not be a valid signature of `msg` with +/// respect to `pubkey`, depending on the verification function's validation criteria. `flags` +/// describes all the edge cases which this test vector falls into. +/// +/// [CCTV]: https://github.com/C2SP/CCTV/tree/5ea85644bd035c555900a2f707f7e4c31ea65ced/ed25519vectors +struct TestVector { + number: usize, + pubkey: VerifyingKey, + sig: Signature, + msg: Vec, + flags: Set, +} + +impl From for TestVector { + fn from(tv: IntermediateTestVector) -> Self { + let number = tv.number; + let pubkey = { + let mut buf = [0u8; 32]; + buf.copy_from_slice(&tv.pubkey); + VerifyingKey::from_bytes(&buf).unwrap() + }; + let sig = { + let mut buf = [0u8; 64]; + buf.copy_from_slice(&tv.sig); + Signature::from_bytes(&buf) + }; + let msg = tv.msg.as_bytes().to_vec(); + + // Unwrap the Option> + let flags = tv.flags.unwrap_or_else(Default::default); + + Self { + number, + pubkey, + sig, + msg, + flags, + } + } +} + +// Tells serde how to deserialize bytes from hex +fn bytes_from_hex<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let mut hex_str = String::deserialize(deserializer)?; + // Prepend a 0 if it's not even length + if hex_str.len() % 2 == 1 { + hex_str.insert(0, '0'); + } + hex::decode(hex_str).map_err(|e| SError::custom(format!("{:?}", e))) +} + +fn get_test_vectors() -> impl Iterator { + let f = File::open("VALIDATIONVECTORS").expect( + "This test is only available when the code has been cloned from the git repository, since + the VALIDATIONVECTORS file is large and is therefore not included within the distributed \ + crate.", + ); + + serde_json::from_reader::<_, Vec>(f) + .unwrap() + .into_iter() + .map(TestVector::from) +} + +/// Tests that the verify() and verify_strict() functions succeed only on test cases whose flags +/// (i.e., edge cases it falls into) are a subset of VERIFY_ALLOWED_EDGECASES and +/// VERIFY_STRICT_ALLOWED_EDGECASES, respectively +#[test] +fn check_validation_criteria() { + let verify_allowed_edgecases = Set::from_iter(VERIFY_ALLOWED_EDGECASES.to_vec()); + let verify_strict_allowed_edgecases = Set::from_iter(VERIFY_STRICT_ALLOWED_EDGECASES.to_vec()); + + for TestVector { + number, + pubkey, + msg, + sig, + flags, + } in get_test_vectors() + { + // If all the verify-permitted flags here are ones we permit, then verify() should succeed. + // Otherwise, it should not. + let success = pubkey.verify(&msg, &sig).is_ok(); + if flags.is_subset(&verify_allowed_edgecases) { + assert!(success, "verify() expected success in testcase #{number}",); + } else { + assert!(!success, "verify() expected failure in testcase #{number}",); + } + + // If all the verify_strict-permitted flags here are ones we permit, then verify_strict() + // should succeed. Otherwise, it should not. + let success = pubkey.verify_strict(&msg, &sig).is_ok(); + if flags.is_subset(&verify_strict_allowed_edgecases) { + assert!( + success, + "verify_strict() expected success in testcase #{number}", + ); + } else { + assert!( + !success, + "verify_strict() expected failure in testcase #{number}", + ); + } + } +} + +/// Prints the flags that are consistently permitted by verify() and verify_strict() +#[test] +fn find_validation_criteria() { + let mut verify_allowed_edgecases = Set::new(); + let mut verify_strict_allowed_edgecases = Set::new(); + + // Counts the number of times a signature with a re-encoded k and a low-order A verified. This + // happens with 1/8 probability, assuming the usual verification equation(s). + let mut num_lucky_reencoded_k = 0; + let mut num_reencoded_k = 0; + + for TestVector { + number: _, + pubkey, + msg, + sig, + flags, + } in get_test_vectors() + { + // If verify() was a success, add all the associated flags to verify-permitted set + let success = pubkey.verify(&msg, &sig).is_ok(); + + // If this is ReencodedK && LowOrderA, log some statistics + if flags.contains(&Flag::ReencodedK) && flags.contains(&Flag::LowOrderA) { + num_reencoded_k += 1; + num_lucky_reencoded_k += success as u8; + } + + if success { + for flag in &flags { + // Don't count re-encoded k when A is low-order. This is because the + // re-encoded k might be a multiple of 8 by accident + if *flag == Flag::ReencodedK && flags.contains(&Flag::LowOrderA) { + continue; + } else { + verify_allowed_edgecases.insert(*flag); + } + } + } + + // If verify_strict() was a success, add all the associated flags to + // verify_strict-permitted set + let success = pubkey.verify_strict(&msg, &sig).is_ok(); + if success { + for flag in &flags { + verify_strict_allowed_edgecases.insert(*flag); + } + } + } + + println!("VERIFY_ALLOWED_EDGECASES: {:?}", verify_allowed_edgecases); + println!( + "VERIFY_STRICT_ALLOWED_EDGECASES: {:?}", + verify_strict_allowed_edgecases + ); + println!( + "re-encoded k && low-order A yielded a valid signature {}/{} of the time", + num_lucky_reencoded_k, num_reencoded_k + ); +} diff --git a/ed25519-dalek/tests/x25519.rs b/ed25519-dalek/tests/x25519.rs new file mode 100644 index 000000000..18ae50279 --- /dev/null +++ b/ed25519-dalek/tests/x25519.rs @@ -0,0 +1,54 @@ +//! Tests for converting Ed25519 keys into X25519 (Montgomery form) keys. + +use ed25519_dalek::SigningKey; +use hex_literal::hex; + +/// Tests that X25519 Diffie-Hellman works when using keys converted from Ed25519. +// TODO: generate test vectors using another implementation of Ed25519->X25519 +#[test] +fn ed25519_to_x25519_dh() { + // Keys from RFC8032 test vectors (from section 7.1) + let ed25519_secret_key_a = + hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); + let ed25519_secret_key_b = + hex!("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"); + + let ed25519_signing_key_a = SigningKey::from_bytes(&ed25519_secret_key_a); + let ed25519_signing_key_b = SigningKey::from_bytes(&ed25519_secret_key_b); + + let scalar_a_bytes = ed25519_signing_key_a.to_scalar_bytes(); + let scalar_b_bytes = ed25519_signing_key_b.to_scalar_bytes(); + + assert_eq!( + scalar_a_bytes, + hex!("357c83864f2833cb427a2ef1c00a013cfdff2768d980c0a3a520f006904de90f") + ); + assert_eq!( + scalar_b_bytes, + hex!("6ebd9ed75882d52815a97585caf4790a7f6c6b3b7f821c5e259a24b02e502e11") + ); + + let x25519_public_key_a = ed25519_signing_key_a.verifying_key().to_montgomery(); + let x25519_public_key_b = ed25519_signing_key_b.verifying_key().to_montgomery(); + + assert_eq!( + x25519_public_key_a.to_bytes(), + hex!("d85e07ec22b0ad881537c2f44d662d1a143cf830c57aca4305d85c7a90f6b62e") + ); + assert_eq!( + x25519_public_key_b.to_bytes(), + hex!("25c704c594b88afc00a76b69d1ed2b984d7e22550f3ed0802d04fbcd07d38d47") + ); + + let expected_shared_secret = + hex!("5166f24a6918368e2af831a4affadd97af0ac326bdf143596c045967cc00230e"); + + assert_eq!( + x25519_public_key_a.mul_clamped(scalar_b_bytes).to_bytes(), + expected_shared_secret + ); + assert_eq!( + x25519_public_key_b.mul_clamped(scalar_a_bytes).to_bytes(), + expected_shared_secret + ); +} diff --git a/x25519-dalek/.gitignore b/x25519-dalek/.gitignore new file mode 100644 index 000000000..da57a4b2a --- /dev/null +++ b/x25519-dalek/.gitignore @@ -0,0 +1,13 @@ +target/ +**/*.rs.bk + +.cargo + +*~ +\#* +.\#* +*.swp +*.orig +*.bak + +*.s diff --git a/x25519-dalek/.travis.yml b/x25519-dalek/.travis.yml new file mode 100644 index 000000000..eceb10e85 --- /dev/null +++ b/x25519-dalek/.travis.yml @@ -0,0 +1,26 @@ +language: rust + +rust: + - nightly + +env: + - TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='default' + - TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='nightly' + - TEST_COMMAND=bench EXTRA_FLAGS='' FEATURES='default' + - TEST_COMMAND=build EXTRA_FLAGS='--no-default-features' FEATURES='u32_backend nightly' + - TEST_COMMAND=build EXTRA_FLAGS='--no-default-features' FEATURES='u64_backend nightly' + +matrix: + include: + - rust: stable + env: TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std u64_backend' + - rust: beta + env: TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std u64_backend' + +script: + - cargo $TEST_COMMAND --features="$FEATURES" $EXTRA_FLAGS + +notifications: + slack: + rooms: + - dalek-cryptography:Xxv9WotKYWdSoKlgKNqXiHoD#dalek-bots diff --git a/x25519-dalek/CHANGELOG.md b/x25519-dalek/CHANGELOG.md new file mode 100644 index 000000000..d2c337c03 --- /dev/null +++ b/x25519-dalek/CHANGELOG.md @@ -0,0 +1,98 @@ +# Changelog + +Entries are listed in reverse chronological order. + +# 2.x Series + +* Note: All `x255919-dalek` 2.x releases are in sync with the underlying `curve25519-dalek` 4.x releases. + +## 2.0.0-rc.3 + +* `StaticSecret` serialization and `to_bytes()` no longer returns clamped integers. Clamping is still always done during scalar-point multiplication. +* Update underlying `curve25519_dalek` library to `4.0.0-rc.3`. Notable changes: + * [curve25519-dalek backend] now by default auto selects `simd` backend over `serial` where supported. + + +## 2.0.0-rc.2 + +* Update MSRV to 1.60. +* Update edition to 2021 +* Add `.as_bytes()` and `AsRef<[u8]>` for `Shared/StaticSecret` +* Add `getrandom` feature to provide `random_from_rng` constructors +* Make `StaticSecrets` optional via feature `static_secrets` +* Update underlying `curve25519_dalek` library to `4.0.0-rc.2`. Notable changes: + * [curve25519-dalek backend] additive features have been removed in favor of cfg based selection. + * [curve25519-dalek backend] now by default auto selects the appropriate word size over the previous default `32`. + +## 2.0.0-pre.1 + +* Loosen restriction on zeroize dependency version from =1.3 to 1. +* Update MSRV to 1.51. + +## 2.0.0-pre.0 + +* Update `rand_core` dependency to `0.6`. + +# 1.x Series + +## 1.2 + +* Add module documentation for using the bytes-oriented `x25519()` API. +* Add implementation of `zeroize::Zeroize` for `PublicKey`. +* Move unittests to a separate directory. +* Add cargo feature flags `"fiat_u32_backend"` and `"fiat_u64_backend"` for + activating the Fiat crypto field element implementations. +* Fix issue with removed `feature(external_doc)` on nightly compilers. +* Pin `zeroize` to version 1.3 to support a wider range of MSRVs. +* Add CI via Github actions. +* Fix breakage in the serde unittests. +* MSRV is now 1.41 for production and 1.48 for development. +* Add an optional check to `SharedSecret` for contibutory behaviour. +* Add implementation of `ReusableSecret` keys which are non-ephemeral, but which + cannot be serialised to discourage long-term use. + +## 1.1.1 + +* Fix a typo in the README. + +## 1.1.0 + +* Add impls of `PartialEq`, `Eq`, and `Hash` for `PublicKey` (by @jack-michaud) + +## 1.0.1 + +* Update underlying `curve25519_dalek` library to `3.0`. + +## 1.0.0 + +* Widen generic bound on `EphemeralSecret::new` and `StaticSecret::new` to + allow owned as well as borrowed RNGs. +* Add `PublicKey::to_bytes` and `SharedSecret::to_bytes`, returning owned byte + arrays, complementing the existing `as_bytes` methods returning references. +* Remove mention of deprecated `rand_os` crate from examples. +* Clarify `EphemeralSecret`/`StaticSecret` distinction in documentation. + +# Pre-1.0.0 + +## 0.6.0 + +* Updates `rand_core` version to `0.5`. +* Adds `serde` support. +* Replaces `clear_on_drop` with `zeroize`. +* Use Rust 2018. + +## 0.5.2 + +* Implement `Clone` for `StaticSecret`. + +## 0.5.1 + +* Implement `Copy, Clone, Debug` for `PublicKey`. +* Remove doctests. + +## 0.5.0 + +* Adds support for static and ephemeral keys. + +[curve25519-dalek backend]: https://github.com/dalek-cryptography/curve25519-dalek/#backends + diff --git a/x25519-dalek/Cargo.lock b/x25519-dalek/Cargo.lock new file mode 100644 index 000000000..ff401afbb --- /dev/null +++ b/x25519-dalek/Cargo.lock @@ -0,0 +1,735 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "bitflags", + "clap_lex", + "indexmap", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "cpufeatures" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +dependencies = [ + "libc", +] + +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "curve25519-dalek" +version = "4.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436ace70fc06e06f7f689d2624dc4e2f0ea666efb5aa704215f7249ae6e047a7" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto", + "platforms", + "rustc_version", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.12", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "fiat-crypto" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ace6ec7cc19c8ed33a32eaa9ea692d7faea05006b5356b9e2b668ec4bc3955" + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "os_str_bytes" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" + +[[package]] +name = "platforms" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" + +[[package]] +name = "plotters" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" + +[[package]] +name = "plotters-svg" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "proc-macro2" +version = "1.0.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "regex" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + +[[package]] +name = "serde" +version = "1.0.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.12", +] + +[[package]] +name = "serde_json" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "x25519-dalek" +version = "2.0.0-rc.3" +dependencies = [ + "bincode", + "criterion", + "curve25519-dalek", + "rand_core", + "serde", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.12", +] diff --git a/x25519-dalek/Cargo.toml b/x25519-dalek/Cargo.toml new file mode 100644 index 000000000..087513923 --- /dev/null +++ b/x25519-dalek/Cargo.toml @@ -0,0 +1,63 @@ +[package] +name = "x25519-dalek" +edition = "2021" +# Before changing this: +# - update version in README.md +# - update html_root_url +# - update CHANGELOG +# - if any changes were made to README.md, mirror them in src/lib.rs docs +version = "2.0.0-rc.3" +authors = [ + "Isis Lovecruft ", + "DebugSteven ", + "Henry de Valence ", +] +readme = "README.md" +license = "BSD-3-Clause" +repository = "https://github.com/dalek-cryptography/x25519-dalek" +homepage = "https://dalek.rs/" +documentation = "https://docs.rs/x25519-dalek" +categories = ["cryptography", "no-std"] +keywords = ["cryptography", "curve25519", "key-exchange", "x25519", "diffie-hellman"] +description = "X25519 elliptic curve Diffie-Hellman key exchange in pure-Rust, using curve25519-dalek." +exclude = [ + ".gitignore", + ".travis.yml", + "CONTRIBUTING.md", +] +rust-version = "1.60" + +[badges] +travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"} + +[package.metadata.docs.rs] +rustdoc-args = [ + "--html-in-header", "docs/assets/rustdoc-include-katex-header.html", + "--cfg", "docsrs", +] +features = ["getrandom", "reusable_secrets", "serde", "static_secrets"] + +[dependencies] +curve25519-dalek = { version = "=4.0.0-rc.3", path = "../curve25519-dalek", default-features = false } +rand_core = { version = "0.6", default-features = false } +serde = { version = "1", default-features = false, optional = true, features = ["derive"] } +zeroize = { version = "1", default-features = false, optional = true, features = ["zeroize_derive"] } + +[dev-dependencies] +bincode = "1" +criterion = "0.4.0" +rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } + +[[bench]] +name = "x25519" +harness = false + +[features] +default = ["alloc", "precomputed-tables", "zeroize"] +getrandom = ["rand_core/getrandom"] +zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"] +serde = ["dep:serde", "curve25519-dalek/serde"] +alloc = ["curve25519-dalek/alloc", "serde?/alloc", "zeroize?/alloc"] +precomputed-tables = ["curve25519-dalek/precomputed-tables"] +reusable_secrets = [] +static_secrets = [] diff --git a/x25519-dalek/LICENSE b/x25519-dalek/LICENSE new file mode 100644 index 000000000..6577d97c2 --- /dev/null +++ b/x25519-dalek/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2017-2021 isis agora lovecruft. All rights reserved. +Copyright (c) 2019-2021 DebugSteven. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/x25519-dalek/README.md b/x25519-dalek/README.md new file mode 100644 index 000000000..a25210a88 --- /dev/null +++ b/x25519-dalek/README.md @@ -0,0 +1,139 @@ +# x25519-dalek [![](https://img.shields.io/crates/v/x25519-dalek.svg)](https://crates.io/crates/x25519-dalek) [![](https://docs.rs/x25519-dalek/badge.svg)](https://docs.rs/x25519-dalek) [![](https://travis-ci.org/dalek-cryptography/x25519-dalek.svg?branch=master)](https://travis-ci.org/dalek-cryptography/x25519-dalek) + +A pure-Rust implementation of x25519 elliptic curve Diffie-Hellman key exchange, +with curve operations provided by +[curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek). + +This crate provides two levels of API: a bare byte-oriented `x25519` +function which matches the function specified in [RFC7748][rfc7748], as +well as a higher-level Rust API for static and ephemeral Diffie-Hellman. + +## Examples + + + + + +Alice and Bob are two adorable kittens who have lost their mittens, and they +wish to be able to send secret messages to each other to coordinate finding +them, otherwise—if their caretaker cat finds out—they will surely be called +naughty kittens and be given no pie! + +But the two kittens are quite clever. Even though their paws are still too big +and the rest of them is 90% fuzziness, these clever kittens have been studying +up on modern public key cryptography and have learned a nifty trick called +*elliptic curve Diffie-Hellman key exchange*. With the right incantations, the +kittens will be able to secretly organise to find their mittens, and then spend +the rest of the afternoon nomming some yummy pie! + +First, Alice uses `EphemeralSecret::random()` and then +`PublicKey::from()` to produce her secret and public keys: + +```ignore +use x25519_dalek::{EphemeralSecret, PublicKey}; + +let alice_secret = EphemeralSecret::random(); +let alice_public = PublicKey::from(&alice_secret); +``` + +Bob does the same: + +```ignore +# use x25519_dalek::{EphemeralSecret, PublicKey}; +let bob_secret = EphemeralSecret::random(); +let bob_public = PublicKey::from(&bob_secret); +``` + +Alice meows across the room, telling `alice_public` to Bob, and Bob +loudly meows `bob_public` back to Alice. Alice now computes her +shared secret with Bob by doing: + +```rust +# use rand_core::OsRng; +# use x25519_dalek::{EphemeralSecret, PublicKey}; +# let alice_secret = EphemeralSecret::new(OsRng); +# let alice_public = PublicKey::from(&alice_secret); +# let bob_secret = EphemeralSecret::new(OsRng); +# let bob_public = PublicKey::from(&bob_secret); +let alice_shared_secret = alice_secret.diffie_hellman(&bob_public); +``` + +Similarly, Bob computes a shared secret by doing: + +```rust +# use rand_core::OsRng; +# use x25519_dalek::{EphemeralSecret, PublicKey}; +# let alice_secret = EphemeralSecret::new(OsRng); +# let alice_public = PublicKey::from(&alice_secret); +# let bob_secret = EphemeralSecret::new(OsRng); +# let bob_public = PublicKey::from(&bob_secret); +let bob_shared_secret = bob_secret.diffie_hellman(&alice_public); +``` + +These secrets are the same: + +```rust +# use rand_core::OsRng; +# use x25519_dalek::{EphemeralSecret, PublicKey}; +# let alice_secret = EphemeralSecret::new(OsRng); +# let alice_public = PublicKey::from(&alice_secret); +# let bob_secret = EphemeralSecret::new(OsRng); +# let bob_public = PublicKey::from(&bob_secret); +# let alice_shared_secret = alice_secret.diffie_hellman(&bob_public); +# let bob_shared_secret = bob_secret.diffie_hellman(&alice_public); +assert_eq!(alice_shared_secret.as_bytes(), bob_shared_secret.as_bytes()); +``` + +Voilà! Alice and Bob can now use their shared secret to encrypt their +meows, for example, by using it to generate a key and nonce for an +authenticated-encryption cipher. + +This example used the ephemeral DH API, which ensures that secret keys +cannot be reused; Alice and Bob could instead use the static DH API +and load a long-term secret key. + +# Installation + +To install, add the following to your project's `Cargo.toml`: + +```toml +[dependencies] +x25519-dalek = "2.0.0-rc.3" +``` + +# MSRV + +Current MSRV is 1.60. + +# Documentation + +Documentation is available [here](https://docs.rs/x25519-dalek). + +# Performance and backend selection + +Performance is a secondary goal behind correctness, safety, and clarity, but we aim to be competitive with other implementations. To this end, we allow users to choose their _backend_, i.e., the underlying implementation of elliptic curve and scalar arithmetic. Different backends have different use cases. For example, if you demand formally verified code, you want to use the `fiat` backend (as it was generated from [Fiat Crypto][fiat]). + +Further instructions and details regarding backends can be found in the [curve25519-dalek docs](https://github.com/dalek-cryptography/curve25519-dalek#backends). + +# Note + +This code matches the [RFC7748][rfc7748] test vectors. +The elliptic curve +operations are provided by `curve25519-dalek`, which makes a best-effort +attempt to prevent software side-channels. + +"Secret Messages" cover image and [zine](https://shop.bubblesort.io/products/secret-messages-zine) +copyright © Amy Wibowo ([@sailorhg](https://twitter.com/sailorhg)) + +[rfc7748]: https://tools.ietf.org/html/rfc7748 + +# See also + +- [crypto_box]: pure Rust public-key authenticated encryption compatible with + the NaCl family of encryption libraries (libsodium, TweetNaCl) which uses + `x25519-dalek` for key agreement + +[fiat]: https://github.com/mit-plv/fiat-crypto +[crypto_box]: https://github.com/RustCrypto/nacl-compat/tree/master/crypto_box diff --git a/x25519-dalek/benches/x25519.rs b/x25519-dalek/benches/x25519.rs new file mode 100644 index 000000000..77c832db0 --- /dev/null +++ b/x25519-dalek/benches/x25519.rs @@ -0,0 +1,41 @@ +// -*- mode: rust; -*- +// +// This file is part of x25519-dalek. +// Copyright (c) 2017-2019 isis agora lovecruft +// Copyright (c) 2019 DebugSteven +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft +// - DebugSteven + +//! Benchmark the Diffie-Hellman operation. + +use criterion::{criterion_group, criterion_main, Criterion}; + +use rand_core::OsRng; + +use x25519_dalek::EphemeralSecret; +use x25519_dalek::PublicKey; + +fn bench_diffie_hellman(c: &mut Criterion) { + let bob_secret = EphemeralSecret::random_from_rng(OsRng); + let bob_public = PublicKey::from(&bob_secret); + + c.bench_function("diffie_hellman", move |b| { + b.iter_with_setup( + || EphemeralSecret::random_from_rng(OsRng), + |alice_secret| alice_secret.diffie_hellman(&bob_public), + ) + }); +} + +criterion_group! { + name = x25519_benches; + config = Criterion::default(); + targets = + bench_diffie_hellman, +} +criterion_main! { + x25519_benches, +} diff --git a/x25519-dalek/docs/assets/rustdoc-include-katex-header.html b/x25519-dalek/docs/assets/rustdoc-include-katex-header.html new file mode 100644 index 000000000..d240432aa --- /dev/null +++ b/x25519-dalek/docs/assets/rustdoc-include-katex-header.html @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/x25519-dalek/res/bubblesort-zines-secret-messages-cover.jpeg b/x25519-dalek/res/bubblesort-zines-secret-messages-cover.jpeg new file mode 100644 index 000000000..ca3329832 Binary files /dev/null and b/x25519-dalek/res/bubblesort-zines-secret-messages-cover.jpeg differ diff --git a/x25519-dalek/src/lib.rs b/x25519-dalek/src/lib.rs new file mode 100644 index 000000000..9a5fc1938 --- /dev/null +++ b/x25519-dalek/src/lib.rs @@ -0,0 +1,33 @@ +// -*- mode: rust; -*- +// +// This file is part of x25519-dalek. +// Copyright (c) 2017-2021 isis lovecruft +// Copyright (c) 2019-2021 DebugSteven +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft +// - DebugSteven + +// Refuse to compile if documentation is missing, but only on nightly. +// +// This means that missing docs will still fail CI, but means we can use +// README.md as the crate documentation. + +#![no_std] +#![cfg_attr(feature = "bench", feature(test))] +#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg, doc_cfg_hide))] +#![cfg_attr(docsrs, doc(cfg_hide(docsrs)))] +#![deny(missing_docs)] +#![doc( + html_logo_url = "https://cdn.jsdelivr.net/gh/dalek-cryptography/curve25519-dalek/docs/assets/dalek-logo-clear.png" +)] +#![doc = include_str!("../README.md")] + +//------------------------------------------------------------------------ +// x25519-dalek public API +//------------------------------------------------------------------------ + +mod x25519; + +pub use crate::x25519::*; diff --git a/x25519-dalek/src/x25519.rs b/x25519-dalek/src/x25519.rs new file mode 100644 index 000000000..e1c79d44a --- /dev/null +++ b/x25519-dalek/src/x25519.rs @@ -0,0 +1,377 @@ +// -*- mode: rust; -*- +// +// This file is part of x25519-dalek. +// Copyright (c) 2017-2021 isis lovecruft +// Copyright (c) 2019-2021 DebugSteven +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft +// - DebugSteven + +//! x25519 Diffie-Hellman key exchange +//! +//! This implements x25519 key exchange as specified by Mike Hamburg +//! and Adam Langley in [RFC7748](https://tools.ietf.org/html/rfc7748). + +use curve25519_dalek::{edwards::EdwardsPoint, montgomery::MontgomeryPoint, traits::IsIdentity}; + +use rand_core::CryptoRng; +use rand_core::RngCore; + +#[cfg(feature = "zeroize")] +use zeroize::Zeroize; + +/// A Diffie-Hellman public key +/// +/// We implement `Zeroize` so that downstream consumers may derive it for `Drop` +/// should they wish to erase public keys from memory. Note that this erasure +/// (in this crate) does *not* automatically happen, but either must be derived +/// for Drop or explicitly called. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "zeroize", derive(Zeroize))] +#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] +pub struct PublicKey(pub(crate) MontgomeryPoint); + +impl From<[u8; 32]> for PublicKey { + /// Given a byte array, construct a x25519 `PublicKey`. + fn from(bytes: [u8; 32]) -> PublicKey { + PublicKey(MontgomeryPoint(bytes)) + } +} + +impl PublicKey { + /// Convert this public key to a byte array. + #[inline] + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes() + } + + /// View this public key as a byte array. + #[inline] + pub fn as_bytes(&self) -> &[u8; 32] { + self.0.as_bytes() + } +} + +impl AsRef<[u8]> for PublicKey { + /// View this public key as a byte array. + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +/// A short-lived Diffie-Hellman secret key that can only be used to compute a single +/// [`SharedSecret`]. +/// +/// This type is identical to the `StaticSecret` type, except that the +/// [`EphemeralSecret::diffie_hellman`] method consumes and then wipes the secret key, and there +/// are no serialization methods defined. This means that [`EphemeralSecret`]s can only be +/// generated from fresh randomness where the compiler statically checks that the resulting +/// secret is used at most once. +#[cfg_attr(feature = "zeroize", derive(Zeroize))] +#[cfg_attr(feature = "zeroize", zeroize(drop))] +pub struct EphemeralSecret(pub(crate) [u8; 32]); + +impl EphemeralSecret { + /// Perform a Diffie-Hellman key agreement between `self` and + /// `their_public` key to produce a [`SharedSecret`]. + pub fn diffie_hellman(self, their_public: &PublicKey) -> SharedSecret { + SharedSecret(their_public.0.mul_clamped(self.0)) + } + + /// Generate a new [`EphemeralSecret`] with the supplied RNG. + #[deprecated( + since = "2.0.0", + note = "Renamed to `random_from_rng`. This will be removed in 2.1.0" + )] + pub fn new(mut csprng: T) -> Self { + Self::random_from_rng(&mut csprng) + } + + /// Generate a new [`EphemeralSecret`] with the supplied RNG. + pub fn random_from_rng(mut csprng: T) -> Self { + // The secret key is random bytes. Clamping is done later. + let mut bytes = [0u8; 32]; + csprng.fill_bytes(&mut bytes); + EphemeralSecret(bytes) + } + + /// Generate a new [`EphemeralSecret`]. + #[cfg(feature = "getrandom")] + pub fn random() -> Self { + Self::random_from_rng(&mut rand_core::OsRng) + } +} + +impl<'a> From<&'a EphemeralSecret> for PublicKey { + /// Given an x25519 [`EphemeralSecret`] key, compute its corresponding [`PublicKey`]. + fn from(secret: &'a EphemeralSecret) -> PublicKey { + PublicKey(EdwardsPoint::mul_base_clamped(secret.0).to_montgomery()) + } +} + +/// A Diffie-Hellman secret key which may be used more than once, but is +/// purposefully not serialiseable in order to discourage key-reuse. This is +/// implemented to facilitate protocols such as Noise (e.g. Noise IK key usage, +/// etc.) and X3DH which require an "ephemeral" key to conduct the +/// Diffie-Hellman operation multiple times throughout the protocol, while the +/// protocol run at a higher level is only conducted once per key. +/// +/// Similarly to [`EphemeralSecret`], this type does _not_ have serialisation +/// methods, in order to discourage long-term usage of secret key material. (For +/// long-term secret keys, see `StaticSecret`.) +/// +/// # Warning +/// +/// If you're uncertain about whether you should use this, then you likely +/// should not be using this. Our strongly recommended advice is to use +/// [`EphemeralSecret`] at all times, as that type enforces at compile-time that +/// secret keys are never reused, which can have very serious security +/// implications for many protocols. +#[cfg(feature = "reusable_secrets")] +#[cfg_attr(feature = "zeroize", derive(Zeroize))] +#[cfg_attr(feature = "zeroize", zeroize(drop))] +#[derive(Clone)] +pub struct ReusableSecret(pub(crate) [u8; 32]); + +#[cfg(feature = "reusable_secrets")] +impl ReusableSecret { + /// Perform a Diffie-Hellman key agreement between `self` and + /// `their_public` key to produce a [`SharedSecret`]. + pub fn diffie_hellman(&self, their_public: &PublicKey) -> SharedSecret { + SharedSecret(their_public.0.mul_clamped(self.0)) + } + + /// Generate a new [`ReusableSecret`] with the supplied RNG. + #[deprecated( + since = "2.0.0", + note = "Renamed to `random_from_rng`. This will be removed in 2.1.0." + )] + pub fn new(mut csprng: T) -> Self { + Self::random_from_rng(&mut csprng) + } + + /// Generate a new [`ReusableSecret`] with the supplied RNG. + pub fn random_from_rng(mut csprng: T) -> Self { + // The secret key is random bytes. Clamping is done later. + let mut bytes = [0u8; 32]; + csprng.fill_bytes(&mut bytes); + ReusableSecret(bytes) + } + + /// Generate a new [`ReusableSecret`]. + #[cfg(feature = "getrandom")] + pub fn random() -> Self { + Self::random_from_rng(&mut rand_core::OsRng) + } +} + +#[cfg(feature = "reusable_secrets")] +impl<'a> From<&'a ReusableSecret> for PublicKey { + /// Given an x25519 [`ReusableSecret`] key, compute its corresponding [`PublicKey`]. + fn from(secret: &'a ReusableSecret) -> PublicKey { + PublicKey(EdwardsPoint::mul_base_clamped(secret.0).to_montgomery()) + } +} + +/// A Diffie-Hellman secret key that can be used to compute multiple [`SharedSecret`]s. +/// +/// This type is identical to the [`EphemeralSecret`] type, except that the +/// [`StaticSecret::diffie_hellman`] method does not consume the secret key, and the type provides +/// serialization methods to save and load key material. This means that the secret may be used +/// multiple times (but does not *have to be*). +/// +/// # Warning +/// +/// If you're uncertain about whether you should use this, then you likely +/// should not be using this. Our strongly recommended advice is to use +/// [`EphemeralSecret`] at all times, as that type enforces at compile-time that +/// secret keys are never reused, which can have very serious security +/// implications for many protocols. +#[cfg(feature = "static_secrets")] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "zeroize", derive(Zeroize))] +#[cfg_attr(feature = "zeroize", zeroize(drop))] +#[derive(Clone)] +pub struct StaticSecret([u8; 32]); + +#[cfg(feature = "static_secrets")] +impl StaticSecret { + /// Perform a Diffie-Hellman key agreement between `self` and + /// `their_public` key to produce a `SharedSecret`. + pub fn diffie_hellman(&self, their_public: &PublicKey) -> SharedSecret { + SharedSecret(their_public.0.mul_clamped(self.0)) + } + + /// Generate a new [`StaticSecret`] with the supplied RNG. + #[deprecated( + since = "2.0.0", + note = "Renamed to `random_from_rng`. This will be removed in 2.1.0" + )] + pub fn new(mut csprng: T) -> Self { + Self::random_from_rng(&mut csprng) + } + + /// Generate a new [`StaticSecret`] with the supplied RNG. + pub fn random_from_rng(mut csprng: T) -> Self { + // The secret key is random bytes. Clamping is done later. + let mut bytes = [0u8; 32]; + csprng.fill_bytes(&mut bytes); + StaticSecret(bytes) + } + + /// Generate a new [`StaticSecret`]. + #[cfg(feature = "getrandom")] + pub fn random() -> Self { + Self::random_from_rng(&mut rand_core::OsRng) + } + + /// Extract this key's bytes for serialization. + #[inline] + pub fn to_bytes(&self) -> [u8; 32] { + self.0 + } + + /// View this key as a byte array. + #[inline] + pub fn as_bytes(&self) -> &[u8; 32] { + &self.0 + } +} + +#[cfg(feature = "static_secrets")] +impl From<[u8; 32]> for StaticSecret { + /// Load a secret key from a byte array. + fn from(bytes: [u8; 32]) -> StaticSecret { + StaticSecret(bytes) + } +} + +#[cfg(feature = "static_secrets")] +impl<'a> From<&'a StaticSecret> for PublicKey { + /// Given an x25519 [`StaticSecret`] key, compute its corresponding [`PublicKey`]. + fn from(secret: &'a StaticSecret) -> PublicKey { + PublicKey(EdwardsPoint::mul_base_clamped(secret.0).to_montgomery()) + } +} + +#[cfg(feature = "static_secrets")] +impl AsRef<[u8]> for StaticSecret { + /// View this key as a byte array. + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +/// The result of a Diffie-Hellman key exchange. +/// +/// Each party computes this using their [`EphemeralSecret`] or [`StaticSecret`] and their +/// counterparty's [`PublicKey`]. +#[cfg_attr(feature = "zeroize", derive(Zeroize))] +#[cfg_attr(feature = "zeroize", zeroize(drop))] +pub struct SharedSecret(pub(crate) MontgomeryPoint); + +impl SharedSecret { + /// Convert this shared secret to a byte array. + #[inline] + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes() + } + + /// View this shared secret key as a byte array. + #[inline] + pub fn as_bytes(&self) -> &[u8; 32] { + self.0.as_bytes() + } + + /// Ensure in constant-time that this shared secret did not result from a + /// key exchange with non-contributory behaviour. + /// + /// In some more exotic protocols which need to guarantee "contributory" + /// behaviour for both parties, that is, that each party contributed a public + /// value which increased the security of the resulting shared secret. + /// To take an example protocol attack where this could lead to undesirable + /// results [from Thái "thaidn" Dương](https://vnhacker.blogspot.com/2015/09/why-not-validating-curve25519-public.html): + /// + /// > If Mallory replaces Alice's and Bob's public keys with zero, which is + /// > a valid Curve25519 public key, he would be able to force the ECDH + /// > shared value to be zero, which is the encoding of the point at infinity, + /// > and thus get to dictate some publicly known values as the shared + /// > keys. It still requires an active man-in-the-middle attack to pull the + /// > trick, after which, however, not only Mallory can decode Alice's data, + /// > but everyone too! It is also impossible for Alice and Bob to detect the + /// > intrusion, as they still share the same keys, and can communicate with + /// > each other as normal. + /// + /// The original Curve25519 specification argues that checks for + /// non-contributory behaviour are "unnecessary for Diffie-Hellman". + /// Whether this check is necessary for any particular given protocol is + /// often a matter of debate, which we will not re-hash here, but simply + /// cite some of the [relevant] [public] [discussions]. + /// + /// # Returns + /// + /// Returns `true` if the key exchange was contributory (good), and `false` + /// otherwise (can be bad for some protocols). + /// + /// [relevant]: https://tools.ietf.org/html/rfc7748#page-15 + /// [public]: https://vnhacker.blogspot.com/2015/09/why-not-validating-curve25519-public.html + /// [discussions]: https://vnhacker.blogspot.com/2016/08/the-internet-of-broken-protocols.html + #[must_use] + pub fn was_contributory(&self) -> bool { + !self.0.is_identity() + } +} + +impl AsRef<[u8]> for SharedSecret { + /// View this shared secret key as a byte array. + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +/// The bare, byte-oriented x25519 function, exactly as specified in RFC7748. +/// +/// This can be used with [`X25519_BASEPOINT_BYTES`] for people who +/// cannot use the better, safer, and faster ephemeral DH API. +/// +/// # Example +#[cfg_attr(feature = "static_secrets", doc = "```")] +#[cfg_attr(not(feature = "static_secrets"), doc = "```ignore")] +/// use rand_core::OsRng; +/// use rand_core::RngCore; +/// +/// use x25519_dalek::x25519; +/// use x25519_dalek::StaticSecret; +/// use x25519_dalek::PublicKey; +/// +/// // Generate Alice's key pair. +/// let alice_secret = StaticSecret::random_from_rng(&mut OsRng); +/// let alice_public = PublicKey::from(&alice_secret); +/// +/// // Generate Bob's key pair. +/// let bob_secret = StaticSecret::random_from_rng(&mut OsRng); +/// let bob_public = PublicKey::from(&bob_secret); +/// +/// // Alice and Bob should now exchange their public keys. +/// +/// // Once they've done so, they may generate a shared secret. +/// let alice_shared = x25519(alice_secret.to_bytes(), bob_public.to_bytes()); +/// let bob_shared = x25519(bob_secret.to_bytes(), alice_public.to_bytes()); +/// +/// assert_eq!(alice_shared, bob_shared); +/// ``` +pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] { + MontgomeryPoint(u).mul_clamped(k).to_bytes() +} + +/// The X25519 basepoint, for use with the bare, byte-oriented x25519 +/// function. This is provided for people who cannot use the typed +/// DH API for some reason. +pub const X25519_BASEPOINT_BYTES: [u8; 32] = [ + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; diff --git a/x25519-dalek/tests/x25519_tests.rs b/x25519-dalek/tests/x25519_tests.rs new file mode 100644 index 000000000..d589b3e44 --- /dev/null +++ b/x25519-dalek/tests/x25519_tests.rs @@ -0,0 +1,231 @@ +use curve25519_dalek::edwards::EdwardsPoint; + +use x25519_dalek::*; + +#[test] +fn byte_basepoint_matches_edwards_scalar_mul() { + let mut scalar_bytes = [0x37; 32]; + + for i in 0..32 { + scalar_bytes[i] += 2; + + let result = x25519(scalar_bytes, X25519_BASEPOINT_BYTES); + let expected = EdwardsPoint::mul_base_clamped(scalar_bytes) + .to_montgomery() + .to_bytes(); + + assert_eq!(result, expected); + } +} + +#[test] +#[cfg(feature = "serde")] +fn serde_bincode_public_key_roundtrip() { + use bincode; + + let public_key = PublicKey::from(X25519_BASEPOINT_BYTES); + + let encoded = bincode::serialize(&public_key).unwrap(); + let decoded: PublicKey = bincode::deserialize(&encoded).unwrap(); + + assert_eq!(encoded.len(), 32); + assert_eq!(decoded.as_bytes(), public_key.as_bytes()); +} + +#[test] +#[cfg(feature = "serde")] +fn serde_bincode_public_key_matches_from_bytes() { + use bincode; + + let expected = PublicKey::from(X25519_BASEPOINT_BYTES); + let decoded: PublicKey = bincode::deserialize(&X25519_BASEPOINT_BYTES).unwrap(); + + assert_eq!(decoded.as_bytes(), expected.as_bytes()); +} + +#[test] +#[cfg(feature = "serde")] +fn serde_bincode_static_secret_roundtrip() { + use bincode; + + let static_secret = StaticSecret::from([0x24; 32]); + let encoded = bincode::serialize(&static_secret).unwrap(); + let decoded: StaticSecret = bincode::deserialize(&encoded).unwrap(); + + assert_eq!(encoded.len(), 32); + assert_eq!(decoded.to_bytes(), static_secret.to_bytes()); +} + +#[test] +#[cfg(feature = "serde")] +fn serde_bincode_static_secret_matches_from_bytes() { + use bincode; + + let expected = StaticSecret::from([0x24; 32]); + let decoded: StaticSecret = bincode::deserialize(&[0x24; 32]).unwrap(); + + assert_eq!(decoded.to_bytes(), expected.to_bytes()); +} + +fn do_rfc7748_ladder_test1(input_scalar: [u8; 32], input_point: [u8; 32], expected: [u8; 32]) { + let result = x25519(input_scalar, input_point); + + assert_eq!(result, expected); +} + +#[test] +fn rfc7748_ladder_test1_vectorset1() { + let input_scalar: [u8; 32] = [ + 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, + 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, + 0x9a, 0xc4, + ]; + let input_point: [u8; 32] = [ + 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, + 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, + 0x1c, 0x4c, + ]; + let expected: [u8; 32] = [ + 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, + 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, + 0x85, 0x52, + ]; + + do_rfc7748_ladder_test1(input_scalar, input_point, expected); +} + +#[test] +fn rfc7748_ladder_test1_vectorset2() { + let input_scalar: [u8; 32] = [ + 0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, + 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, + 0xba, 0x0d, + ]; + let input_point: [u8; 32] = [ + 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, + 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, + 0xa4, 0x93, + ]; + let expected: [u8; 32] = [ + 0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, + 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, + 0x79, 0x57, + ]; + + do_rfc7748_ladder_test1(input_scalar, input_point, expected); +} + +#[test] +#[ignore] // Run only if you want to burn a lot of CPU doing 1,000,000 DH operations +fn rfc7748_ladder_test2() { + use curve25519_dalek::constants::X25519_BASEPOINT; + + let mut k: [u8; 32] = X25519_BASEPOINT.0; + let mut u: [u8; 32] = X25519_BASEPOINT.0; + let mut result: [u8; 32]; + + macro_rules! do_iterations { + ($n:expr) => { + for _ in 0..$n { + result = x25519(k, u); + // OBVIOUS THING THAT I'M GOING TO NOTE ANYWAY BECAUSE I'VE + // SEEN PEOPLE DO THIS WITH GOLANG'S STDLIB AND YOU SURE AS + // HELL SHOULDN'T DO HORRIBLY STUPID THINGS LIKE THIS WITH + // MY LIBRARY: + // + // NEVER EVER TREAT SCALARS AS POINTS AND/OR VICE VERSA. + // + // ↓↓ DON'T DO THIS ↓↓ + u = k.clone(); + k = result; + } + }; + } + + // After one iteration: + // 422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079 + // After 1,000 iterations: + // 684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51 + // After 1,000,000 iterations: + // 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424 + + do_iterations!(1); + assert_eq!( + k, + [ + 0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc, 0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, + 0x27, 0x9f, 0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78, 0x3c, 0x60, 0xe8, 0x03, + 0x11, 0xae, 0x30, 0x79, + ] + ); + do_iterations!(999); + assert_eq!( + k, + [ + 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, + 0x4d, 0x3c, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, + 0x99, 0x53, 0x2c, 0x51, + ] + ); + do_iterations!(999_000); + assert_eq!( + k, + [ + 0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd, 0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, + 0x5e, 0x6f, 0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf, 0x5f, 0x4d, 0xd2, 0xd2, + 0x4f, 0x66, 0x54, 0x24, + ] + ); +} + +mod rand_core { + + use super::*; + use ::rand_core::OsRng; + + #[test] + fn ephemeral_from_rng() { + #[allow(deprecated)] + EphemeralSecret::new(OsRng); + EphemeralSecret::random_from_rng(OsRng); + } + + #[test] + #[cfg(feature = "reusable_secrets")] + fn reusable_from_rng() { + #[allow(deprecated)] + ReusableSecret::new(OsRng); + ReusableSecret::random_from_rng(OsRng); + } + + #[test] + #[cfg(feature = "static_secrets")] + fn static_from_rng() { + #[allow(deprecated)] + StaticSecret::new(OsRng); + StaticSecret::random_from_rng(OsRng); + } +} + +#[cfg(feature = "getrandom")] +mod getrandom { + + use super::*; + + #[test] + fn ephemeral_random() { + EphemeralSecret::random(); + } + + #[test] + #[cfg(feature = "reusable_secrets")] + fn reusable_random() { + ReusableSecret::random(); + } + + #[test] + #[cfg(feature = "static_secrets")] + fn static_random() { + StaticSecret::random(); + } +}